Dockerfile命令速查表

FROM 命令

FROM <p_w_picpath>:<tag>
用于设置基础镜像,一般是Dockerfile的第一句。如果没有指定 tag ,则默认tag是latest。

MAINTAINER

MAINTAINER <name>
用来指定维护者的姓名和联系方式。

RUN

RUN <command> 或 RUN ["executable", "param1", "param2"]
每条 RUN 指令将在当前镜像基础上执行指定命令,并提交为新的镜像。

ADD

ADD <src> <dest>
将 <src> 文件复制到 <dst> 文件:<src> 是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件 url,<dst> 是容器中的绝对路径。

COPY

COPY <src> <dest>
复制本地主机的 <src> (为Dockerfile所在目录的相对路径)到容器中的 <dest>,与ADD指令差不多

<src>可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的filepath.Match 规则

例如

COPY hom* /mydir/
COPY hom?.txt /mydir/


在 Docker 官方的最佳实践文档中要求,尽可能的使用 COPY ,因为 COPY 的语义很明确,就是复制文件而已,而 ADD 则包含了更复杂的功能,其行为也不一定很清晰。最适合使用 ADD 的场合,就是所提及的需要自动解压缩的场合。


另外需要注意的是, ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。


因此在 COPY 和 ADD 指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD 。


ENTRYPOINT

ENTRYPOINT ["executable", "param1", "param2"] :推荐使用的 exec 形式

ENTRYPOINT command param1 param2 :shell 形式
配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。一个 Dockerfile 中只能有一个 ENTRYPOINT,如果有多个,则最后一个生效。

CMD

CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式;
CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用;
CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数;
指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。

如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。


提到 CMD 就不得不提容器中应用在前台执行和后台执行的问题。这是初学者常出现的一个混淆。

Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 upstart/systemd 去启动后台服务,容器内没有后台服务的概念。

一些初学者将 CMD 写为:

CMD service nginx start

然后发现容器执行后就立即退出了。甚至在容器内去使用 systemctl 命令结果却发现根本执行不了。这就是因为没有搞明白前台、后台的概念,没有区分容器和虚拟机的差异,依旧在以传统虚拟机的角度去理解容器。

对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。

而使用 service nginx start 命令,则是希望 upstart 来以后台守护进程形式启动 nginx 服务。而刚才说了 CMD service nginx start 会被理解为 CMD ["sh", "-c", "service nginx start"] ,因此主进程实际上是 sh 。那么当service nginx start 命令结束后, sh 也就结束了, sh 作为主进程退出
了,自然就会令容器退出。

正确的做法是直接执行 nginx 可执行文件,并且要求以前台形式运行。比如:

CMD ["nginx", "-g", "daemon off;"]


WORKDIR

WORKDIR /path/to/workdir
为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录。

可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
则最终路径为 /a/b/c 。

EXPOSE

EXPOSE <port> [<port>...]
告诉 Docker 服务端容器暴露的端口号,供互联系统使用。例如 EXPOSE 8080 3000,开放 8080 和 3000 端口。

ENV

ENV <key> <value>
指定一个环境变量,会被后续 RUN 指令使用,并在容器运行时保持。

VOLUME

VOLUME ["/data"]
创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。

USER

USER <UID/Username>
为容器内指定 CMD RUN ENTRYPOINT 命令运行时的用户名或UID。

ONBUILD

ONBUILD [INSTRUCTION]
配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。例如,利用Dockerfile创建了一个镜像A,其中Dockerfile中有这么几个命令

ONBUILD RUN mkdir test
ONBUILD ADD app.js /test/app.js
那么镜像B基于镜像A去构建的时候,默认会在最后加上这两行命令



实战

我们通过一个编译nginx的Dockerfile来实战看看

先mkdir dockerfile,在cd到该目录

[root@localhost dockerfile]# ll
total 972
-rw-r--r--. 1 root root    289 Jun 27 15:08 Dockerfile
-rw-r--r--. 1 root root    546 Jun 27 08:52 install_nginx.sh
-rw-r--r--. 1 root root 980831 Apr 17 21:28 nginx-1.12.0.tar.gz
-rw-r--r--. 1 root root   1353 Jun 27 10:08 nginx.conf

可以看到,这个目录有4个文件

nginx.conf就是我线上优化好缺省的配置文件

install_nginx.sh是基础搭建脚本

内容如下

[root@localhost dockerfile]# more install_nginx.sh
#!/bin/bash

useradd site

cat > /etc/yum.repos.d/CentOS-Base.repo <<EOF
[base]
name=aliyun - base
baseurl=http://mirrors.aliyun.com/centos/6/os/x86_64/
enabled=1
gpgcheck=0

[epel]
name=aliyun - epel
baseurl=http://mirrors.aliyun.com/epel/6Server/x86_64/
enabled=1
gpgcheck=0
EOF

yum -y install pcre-devel zlib-devel gcc gcc-c++ ncurses-devel perl cmake zip unzip screen

tar zxf nginx-1.12.0.tar.gz

cd nginx-1.12.0

./configure --prefix=/usr/local/nginx

make && make install

cd ..

mv -f nginx.conf /usr/local/nginx/conf/nginx.conf


Dockerfile内容如下

FROM hasedon/centos6.5
MAINTAINER yee.wql <yee.wql@gmail.com>
ADD install_nginx.sh nginx-1.12.0.tar.gz nginx.conf /root/
WORKDIR /root
RUN /bin/bash install_nginx.sh && echo "hello world!" >/usr/local/nginx/html/index.html
EXPOSE 80
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]


构建镜像

[root@localhost dockerfile]# docker build -t mynginx .


构建完以后,检查镜像

[root@localhost dockerfile]# docker p_w_picpaths
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mynginx             latest              2ab9d60af257        3 minutes ago       733MB


再就可以运行镜像了

[root@localhost dockerfile]# docker run -d -p 80:80 --name mynginx mynginx
[root@localhost dockerfile]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
ce9903642f63        mynginx             "/usr/local/nginx/..."   2 seconds ago       Up 1 second         0.0.0.0:80->80/tcp   mynginx


最后访问下页面

使用Dockerfile构建镜像_docker