dockerfile文件构建容器
前言:在之前的时候有说过docker构建镜像有两种方式:
(1)docker cumin制作镜像;但是不利于用户之间的共享属于黑盒操作
(2)通过dockerfile文件创建容器;利于用户之间的共享;可以知道镜像之前做过什么样的改动
1:Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令。Docker程序将这些Dockerfile指令翻译真正的Linux命令。Dockerfile有自己书写格式和支持的命令,Docker程序解决这些命令间的依赖关系,类似于Makefile。Docker程序将读取Dockerfile,根据指令生成定制的image。相比image这种黑盒子,Dockerfile这种显而易见的脚本更容易被使用者接受,它明确的表明image是怎么产生的。有了Dockerfile,当我们需要定制自己额外的需求时,只需在Dockerfile上添加或者修改指令,重新生成image即可,省去了敲命令的麻烦。
2:docker的组成部分: (四部分)
# 注释信息,说明
(1)基础镜像信息 FROM
(2)维护者的信息 MAINTAINER
(3)镜像的操作指令 RUN
(4)容器启动时执行的指令 CMD
注:基础镜像信息一定要放在最前面;后面跟其他的命令
*在构建dockerfile文件的时候的指令分为两种:
构建指令 和 设置指令
构建指令:表示在创建容器的时候所使用的命令
设置指令: 表示在容器里运行的时候所使用的命令
那么接下来说一说dockerfile的文件格式:
(1)FROM(指定基础image)
构建指令,必须指定且需要在Dockerfile其他指令的前面。后续的指令都依赖于该指令指定的image。FROM指令指定的基础image可以是官方远程仓库中的,也可以位于本地仓库。
语法格式: FROM <image>:<tag> 也可省略后面的tag那将表示最新的image
(2)MAINTAINER(用来指定镜像创建者信息)
构建指令,用于将image的制作者相关的信息写入到image中。当我们对该image执行docker inspect命令时,输出中有相应的字段记录该信息。(本行内容可以省略但是在生产环境下要写,可以知道是谁创建的格式)
语法格式:MAINTAINER <name>
(3)RUN(安装软件用)
构建指令,RUN可以运行任何被基础image支持的命令
语法格式:RUN <command> (the command is run in a shell - `/bin/sh -c`)
(4)CMD(设置container启动时执行的操作)
设置指令,用于container启动时指定的操作。该操作可以是执行自定义脚本,也可以是执行系统命令
语法格式:CMD command param1 param2 在 /bin/sh中执行,提供给需要交互的应用;
(5)ENTRYPOINT(设置container启动时执行的操作)
设置指令,指定容器启动时执行的命令,可以多次设置,但是只有最后一个有效。
两种格式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2 (shell中执行)。
配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。
每个 Dockerfile 中只能有一个 ENTRYPOINT ,当指定多个时,只有最后一个起效。
(6)USER(设置container容器的用户,默认是root用户)
设置指令:格式为 USER daemon
指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。
当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户
(7)EXPOSE(指定容器需要映射到宿主机器的端口)
格式为 EXPOSE <port> [<port>...]
设置指令,该指令会将容器中的端口映射成宿主机器中的某个端口。当你需要访问容器的时候,可以不是用容器的IP地址而是使用宿主机器的IP地址和映射后的端口。
(8)ENV(用于设置环境变量)
构建指令,指定一个环境变量,会被后续 RUN 指令使用,并在容器运行时保持。
格式: ENV <key> <value>
(9)ADD(从src复制文件到container的dest路径)
构建指令,所有拷贝到container中的文件和文件夹权限为0755,uid和gid为0;
如果是一个目录,那么会将该目录下的所有文件添加到container中,不包括目录;
如果文件是可识别的压缩格式,则docker会帮忙解压缩(注意压缩格式);
如果<src>是文件且<dest>中不使用斜杠结束,则会将<dest>视为文件,<src>的内容会写入<dest>;
如果<src>是文件且<dest>中使用斜杠结束,则会<src>文件拷贝到<dest>目录下。
格式:ADD <src> <dest>
(10)COPY
构建指令:格式为 COPY <src><dest>
复制本地主机的<src>(为Dockerfile所在目录的相对路径)到容器中的<dest>。
(11)VOLUME(指定挂载点)
设置指令,使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用。我们知道容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令。
格式: VOLUME ["<mountpoint>"]
(12)WORKDIR(切换目录)
设置指令,可以多次切换(相当于cd命令),对RUN,CMD,ENTRYPOINT生效。为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录。
格式: WORKDIR /path/to/workdir
(13)ONBUILD(在子镜像中执行)
ONBUILD <Dockerfile关键字>
设置指令:ONBUILD 指定的命令在构建镜像时并不执行,而是在它的子镜像中执行。一般不使用此选项
格式为 ONBUILD [INSTRUCTION] 。
3:我们就根据上面的这些配置项,制作一个sshd的镜像模板并且提供http访问的应用:
(1)创建一个工作目录:
编写run.sh文件
#!/bin/sh
/usr/sbin/httpd -D DFOREGROUND
/usr/sbin/sshd -D
注:因为在docker中无法使用service和systemctl启动服务,所以只能使用服务的绝对路径启动服务
在主机上生成ssh秘钥对,并创建authorized_keys文件
将公钥导到新建的docker目录下方便后续的dockerfile调用
2:编写Dockerfile
以上选项的含义解释:
FROM docker.io/centos:latest选择一个已有的os镜像作为基础
MAINTAINER 镜像的作者
RUN yum install -y openssh-server sudo安装openssh-server和sudo软件包
添加测试用户admin,密码admin,并且将此用户添加到sudoers里
RUN useradd admin
RUN echo "admin:admin" | chpasswd
RUN echo "admin ALL=(ALL) ALL" >> /etc/sudoers
下面这两句比较特殊,在centos6上必须要有,否则创建出来的容器sshd不能登录
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
注意:centos7上必须要有,否则创建出来的容器sshd不能登录
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
将公钥信息上传到远程连接用户的宿主目录的.ssh下
ADD authorized_keys /home/admin/.ssh/authorized_keys
启动sshd服务并且暴露22端口
RUN mkdir /var/run/sshd
EXPOSE 22 80
CMD ["/run.sh"] 也可以写成这种方式CMD ["/usr/sbin/sshd", "-D"]
在sshd_dockerfile目录下,使用docker build命令来创建镜像,注意:在最后还有一个”.”,
执行docker images查看新生成的镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
centos httpdv1 4bb560917dd0 6 minutes ago 301.3 MB
centos httpd 204f2669758a 18 minutes ago 301.3 MB
centos ssh ecc0972a6319 About an hour ago 301.3 MB
在宿主主机打开一个终端,连接刚才新建的容器
注:admin用户是容器中的用户,192.168.1.102地址是宿主机的地址。
测试sudo执行授权命令: