Contents
  1. 1. Dockerfile指令
    1. 1.1. 1.CMD
    2. 1.2. 2.ENTRYPOINT
    3. 1.3. 3.WORKDIR
    4. 1.4. 4.ENV
    5. 1.5. 5.USER
      1. 1.5.1. 6.VOLUME
    6. 1.6. 7.ADD
    7. 1.7. 8.COPY
    8. 1.8. 9.LABEL
    9. 1.9. 10.STOPSIGNAL
    10. 1.10. 11.ARG
    11. 1.11. 12.ONBUILD

人类的本质是复读机

Dockerfile指令

1.CMD

指定容器启动时要运行的命令(与使用docker run命令启动容器指定要运行的命令类似)

指定要运行的特定命令

1
docker run -i -t flag0/static_web /bin/true

使用CMD命令

1
CMD ["bin/ture"]

也可以为要运行的命令指定参数

给CMD指令传递参数

1
CMD ["/bin/bash","-l"]

这里我们将-l 参数传递给了/bin/bash命令

可以不适用数组,而是直接指定cmd命令,docker会在指定命令前加上/bin/sh -c 在执行时有可能导致意料之外的行为,所以docker推荐使用以数组语法类设置要执行的命令

使用docker run 命令可以覆盖cmd命令,如果我们在Dockerfile里指定了CMD指令,而同时在docker run命令行中也指定了要运行的命令,命令行中指定的命令会覆盖Dockerfile中的CMD指令。

用CMD指令启动容器

在dockerfile中加上

1
CMD ["/bin/bash"]

使用docker build 命令构建一个新镜像

1
docker build -t="flag0/test" .

启动容器

1
2
docker run -t -i flag0/test
root@7840b6efd86c:/#

在docker run命令的结尾并未指定要运行什么命令,实际上Docker使用了CMD指令中指定的命令

覆盖本地命令

1
2
3
[root@iz0201z3qoku45z test]# docker run -i -t flag0/test /bin/ps
PID TTY TIME CMD
1 pts/0 00:00:00 ps

在这里指定了想要运行的命令/bin/ps,该命令会列出所有正在运行的进程,上述命令中容器并没有启动shell,而是通过命令行参数覆盖了CMD指令中指定的参数。

在Dockerfile中只能指定一条CMD指令,如果制定了多条CMD指令,也只有最后一条CMD指令被执行。

2.ENTRYPOINT

ENTRYPOINT提供的命令,不容易在启动容器时被覆盖,docker run命令行中指定的任何参数都会被当作参数再次传递给ENTRYPOINT指令中指定的命令。

ENTRYPOINT指令

1
ENTRYPOINT ["/usr/sbin/nginx"]

类似于CMD指令,我们也可以 在指令中通过通过数组的方式为命令指定相应的参数。

为ENTRYPOINT命令指定参数

1
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]

通过给ENTRYPOINTER传入数组的方式来避免在命令前加入/bin/sh -c带来的各种问题

用新的ENTRYPOINT指令重新构建static_web镜像

1
docker build -t="flag0/static_web" .

使用docker run命令启动包含ENTRYPOINT指令的容器

1
docker run -t -i flag0/static_web1 -g "daemon off;"

启动了一个交互的容器,制定了-g “daemon off;”参数,这个参数会传递给用ENTRYPONIT指定的参数,在这里该命令为/usr/sbin/nginx -g "daemon off;"

同时使用ENTRYPOINT和CMD指令

1
2
ENTRYPOINT ["/usr/sbin/nginx"]
CMD ["-h"]

如果在命令行中指定参数,在命令行中指定的参数都会被传递给Nginx守护进程。例如可以指定-g "daemon off";参数让Nginx守护进程以前台方式运行。

如果在启动容器时不指定任何参数,则在CMD指令中指定的-h参数会被传递给Nginx守护进程,即Nginx服务器会以/usr/sbin/nginx -h的方式启动,该命令用来显示Nginx的帮助信息

使得我们可以构建一个镜像,既可以运行一个默认的命令,也支持通过docker run命令行为该命令指定可覆盖的选项或者标志。

如果需要可以通过docker run 的--entrypoint,标志覆盖ENTRYPOINT指令。

3.WORKDIR

WORKDIR 是创建容器时在容器内部设置工作目录,ENTRYPOINT和CMD指定的程序都会在这个目录下运行

可以使用该指令为Dockerfile后续的一系列指令设置工作目录,也可以为最终的容器设置工作目录

使用WORKDIR指令

1
2
3
4
WORKDIR /opt/webapp/db
RUN bundle install
WORKDIR /opt/webapp
ENTRYPOINT ["rackup"]

我们将工作目录且换成了/opt/webapp/db后运行了bundle install命令

之后又将工作目录设置为/opt/webapp,最后设置了ENTRYPOINT指令来启动rackup命令。

可以通过-w 标志在运行时覆盖工作目录

覆盖工作目录

1
docker run -ti -w /var/log ubuntu pwd

该命令会将容器内的工作目录设置为/var/log

4.ENV

ENV指令用来在镜像构建的过程中设置环境变量

在Dockerfile文件中设置环境变量

1
ENV RVM_PATH /home/rvm/

新的环境变量可以在后续的任何RUN指令中使用,如果在命令前面制定了环境变量前缀一样

为RUN指令设置前缀

1
RUN gem install unicorn

该指令会以下面的方式执行

1
RVM_PATH=/home/rvm/ gem install unicorn

可以在env中指定单个环境变量或者多个环境变量

用ENV设置多个环境变量

1
ENV RVM_PATH=/home/rvm RVM_ARCHFLASS="-arch i386"

在其他Dockerfile指令中使用环境变量

1
2
ENV TARGET_DIR /opt/app
WORKDIR $TARGET_DIR

如果需要可以在环境变量前加上一个反斜线进行转义

Docker容器中环境变量的持久化

这些环境变量会被持久保存到从我们镜像创建的任何容器中

1
2
3
4
env
...
RVM_PATH=/home/rvm/
...

运行时环境变量

也可以使用docker run命令行的-e 标志来传递环境变量,但是这些环境变量只在运行时有效

1
2
3
4
5
6
[root@iz0201z3qoku45z static_web]# docker run -ti -e "WEB_PORT=8080" ubuntu env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=6dafe65637e6
TERM=xterm
WEB_PORT=8080
HOME=/root

5.USER

USER指令用来指定该镜会以什么样的用户的身份来运行,

使用USER指令

1
USER nginx

该镜像的启动的容器会以nginx用户的身份来运行

指定USER和GROUP的各种组合

可以指定用户名或UID以及组或GID

1
2
3
4
5
6
USER user
USER user:group
USER uid
USER uid:gid
USER user:gid
USER uid:group

也可以在docker run命令中通过-u 标志来覆盖该指令指定的值

如果不通过USER指令指定用户,默认用户为root

6.VOLUME

volume指令用于基于镜像创建的容器添加卷。一个卷是可以存在于一个或者多个容器内的特定的目录,这个目录可以绕过联合文件系统,并提供如下共享数据或者对数据进行持久化的功能

  • 卷可以在容器间共享和重用
  • 一个容器可以不是必须和其他容器共享卷
  • 对卷的修改是立即生效
  • 对卷的修改不会对更新镜像产生影响
  • 卷会一直存在直到没有任何容器再使用它

卷功能可以将数据(如源代码)、数据库或者其他内容添加到镜像中而不是将这些内容提交到镜像中,并且允许我们在多个容器间共享这些内容。

使用VOLUME

1
VOLUME ["/opt/project"]

这条指令会为基于此镜像创建的任何容器创建一个名为/opt/project的挂载点

docker cp 运行从容器复制文件和复制文件到容器上

使用VOLUME指令指定多个卷

可以通过指定数组的方式指定多个卷

1
VOLUME ['/opt/project','/data']

7.ADD

ADD 指令用来将构建环境下的文件和目录复制到镜像中。

使用ADD指令

1
ADD software.lic /opt.application/software.lic

这里的ADD指令将构建目录下的software.lic文件复制到镜像中的/opt/application/software.lic

指向源文件的位置参数可以是一个url,或者构建上下文或环境中文件名或者目录。不能对构建上下文之外的文件进行ADD操作

如果目标地址以/结尾,docker就认为源位置指向的是一个目录,如果目的地址不是以/结尾那么Docker就认为源位置指向的是文件

在ADD指令中使用URL作为文件源

1
ADD http://wordpress.org/latest.zip /root/wordpress.zip

将归档文件作为ADD指令中的源文件

ADD在处理本地归档文件时,如果将一个归档文件(gzip、bzip、xz)指定为源文件,Docker会自动将归档文件解开

1
ADD latest.tar.gz /var/www/wordpress/

该命令会将归档文件latest.tar.gz解开到/var/www/wordpress/ 目录下

该指令执行后的输出是原目录已经存在的内容加上归档文件中的内容,如果目的位置的目录下已经存在了和归档文件同名的文件或者目录,那么目的位置中的文件或者目录不会被覆盖

docker不支持以url方式指定的源位置中使用归档文件。

如果目的位置不存在,docker将会自动创建这个全路径,包括路径中的任何目录,新建文件和目录的模式为0755,并且uid和gid都是0

通过ADD指令向镜像添加一个文件或目录,将使Docekrfile中的后续指令都不能继续使用之前的构建缓存

8.COPY

COPY 类似于ADD,他们根本不同是COPY只关心在构建上下文中复制本地文件,而不会做文件提取和解压

使用COPY指令

1
COPY conf.d/ /etc/apache2/

会将conf.d目录下的文件复制到/etc/apache2/ 目录中

文件源路径必须是一个与当前构建环境相对的文件或者目录,本地文件都放到和Dockerfile同一个目录下。

COPY指令的目的位置则必须是容器内部的一个绝对路径。

任何由该指令创建的文件或者目录的UID和GID都会设置为0

如果源路径以/结尾,docker会认为要复制的是目录,并将它复制到目的目录中,如果目的位置不存在,Docker将会自动创建所有需要的目录结构。

9.LABEL

LABEL用于为docker镜像添加元数据,元数据以键值对的形式展现。

添加LABEL指令

1
2
LABEL version="1.0"
LABEL location="New York" type="Data Center" role="Web Server"

LABLE 指令以label =”value”的形式出现,可以在每一条指令中指定一个元数据,或者指定多个元数据,不同的元数据之间用空格分隔。

推荐所有的元数据都放到一条LABEL指令中,以防止不同的元数据指令创建过多镜像层。

使用docker inspect命令查看容器标签

1
2
3
4
5
6
7
8
9
docker inspect flag0/test2
...
"Labels": {
"location": "New York",
"role": "Web Server",
"type": "Data Center",
"vserion": "1.0"
}
...

可以看到用LABEL定义的元数据信息

10.STOPSIGNAL

STOPSIGNAL指令用来设置停止容器时发送什么系统调用信号给容器。

这个信号是内核系统调用表中合法的数,如9,或者SIGNAME格式中的信号名称,如SIGKLL

11.ARG

ARG指令用来定义可以在docker build命令运行时传递给构建运行时的变量,我们只需要在构建时使用--build-arg标志即可。用户只能在哦固件是指定在Dockerfile文件中定义的参数

添加ARG指令

1
2
ARG build
ARG webapp_user=user

第二行的ARG指令设置了一个默认值,如果构建时没有为该参数指定值,就会使用这个默认值。

使用ARG指令

在docker build中使用这些参数

1
docker build --build-arg build=1234 -t flag0/webapp .

构建flag0/webapp镜像时,build变量将会设置为1234,而webapp_user变量则会继承设置的默认值user

不要使用ARG来传递证书或者密钥之类的信息,机密信息在构建过程中以及镜像的构建历史中会被暴露

预定义ARG变量

1
2
3
4
5
6
7
8
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy

想要使用预定义的变量,只需给docker build 命令传递--build-arg <variable>=<value>标志即可

12.ONBUILD

ONBUILD 指令能够为镜像添加触发器(trigger)。当一个镜像被用作其他镜像的基础镜像时(比如用户的镜像需要从某未准备好的位置添加源代码,或者用户需要执行特定于构建镜像的环境的构建脚本),该镜像中的触发器将会被执行。

触发器会在构建过程中插入的新指令,我们可以认为这些指令是紧跟在FROM之后指定的,触发器可以是任何构建指令。

添加ONBUILD指令

1
2
ONBUILD ADD . /app/src
ONBUILD RUN cd /app/src && make

上面的代码会在创建的镜像中加入ONBUILD触发器

docker inspect命令查看镜像中的ONBUID指令

1
2
3
4
5
6
7
docker inspect 508efa4e4bf8
...
"OnBuild":[
"ADD . /app/src",
"RUN cd /app/src && make"
]
...

新的ONBUILD镜像Dockerfile

为Apache2镜像构建一个全新的Dockerfile,该镜像名为flag0/apache2-1

1
2
3
4
5
6
7
8
9
10
FROM ubuntu:14.04
MAINTAINER flag0 "root@flag0.com"
RUN apt-get update && apt-get install -y apache2
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
ONBUILD ADD http://www.baidu.com /var/www/
EXPOSE 80
ENTRYPOINT ["/usr/sbin/apache2"]
CMD ["-D","FOREGROUND"]

构建apache2镜像

1
2
3
4
5
docker build -t="flag0/apache2-1" .
...
Step 7/10 : ONBUILD ADD http://www.baidu.com /var/www/
---> Running in 3d2f8a692641
...

新构建的镜像中包含一条ONBUILD 指令,该指令会使用ADD指令将构建环境所在的目录下的内容全部添加到镜像中的/var/www/ 目录下。

可以基于这个模板来构建Web应用程序

webapp的Dockerfile

通过构建一个名为webapp的镜像来看看如何使用镜像模板功能

1
2
3
4
FROM flag0/apache2
MAINTAINER flag0 "root@flag0.com"
ENV APPLICATION_NAME webapp
ENV ENVIRONMENT development

构建webapp镜像

1
2
3
4
5
6
docker build -t="flag0/webapp" .
Sending build context to Docker daemon 3.072kB
Step 1/5 : FROM flag0/apache2-1:latest
# Executing 1 build trigger
Downloading 154kB
ADD failed: cannot determine filename for source http://www.baidu.com

可以看到,在FROM指令后,docker插入了一条APP指令,这条APP指令就是在ONBUILD触发器中指定的,执行完该ADD指令后,Docker才会继续执行构建文件夹中的后续指令。

这种机制使得每次都会将本地源代码添加到镜像中。

ONBUILD触发器(在其父镜像是不会执行的,只在子镜像中执行)会按照父镜像中指定的顺序执行,并且只能被继承一次(也就是说只能在子镜像中执行,而不会在孙子镜像中执行)

为了防止Dockerfile构建过程中产生递归调用的问题,有几条指令是不能用在ONBUILD指令中的,包括FROM、MAINTAINER、和ONBUILD本身。

Contents
  1. 1. Dockerfile指令
    1. 1.1. 1.CMD
    2. 1.2. 2.ENTRYPOINT
    3. 1.3. 3.WORKDIR
    4. 1.4. 4.ENV
    5. 1.5. 5.USER
      1. 1.5.1. 6.VOLUME
    6. 1.6. 7.ADD
    7. 1.7. 8.COPY
    8. 1.8. 9.LABEL
    9. 1.9. 10.STOPSIGNAL
    10. 1.10. 11.ARG
    11. 1.11. 12.ONBUILD