WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
则最终路径为 /a/b/c。
ONBUILD
格式为 ONBUILD [INSTRUCTION]。
配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。
例如,Dockerfile 使用如下的内容创建了镜像 image-A。
[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]
如果基于 image-A 创建新的镜像时,新的Dockerfile中使用 FROM image-A指定基础镜像时,会自动执行 ONBUILD 指令内容,等价于在后面添加了两条指令。
FROM image-A #Automatically run the followingADD . /app/srcRUN /usr/local/bin/python-build --dir /app/src
使用 ONBUILD 指令的镜像,推荐在标签中注明,例如 ruby:1.9-onbuild。
3.创建镜像
编写完Dockerfile文件后,通过运行docker build命令来创建自定义的镜像。Docker build命令格式如下:
docker build [options] <path>
该命令将读取指定路径下(包括子目录)的 Dockerfile,并将该路径下所有内容发送给 Docker 服务端,由服务端来创建镜像。因此一般建议放置 Dockerfile 的目录为空目录。也可以通过 .dockerignore 文件(每一行添加一条匹配模式)来让 Docker 忽略路径下的目录和文件。
例如下面使用Dockerfile样例来创建了镜像test:0.0.1,其中-t选项用来指定镜像的tag。Dockerfile文件内容如下:
复制代码
FROM ubuntu:14.04
MAINTAINER lienhua34@xxx.com
RUN mkdir /opt/leh
RUN touch /opt/leh/test
CMD echo "Hello lienhua34"
复制代码
下面运行docker build命令生成镜像test:0.0.1,
复制代码
lienhua34@test$ sudo docker build -t test:0.0.1 .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM ubuntu:14.04
---> a5a467fddcb8
Step 2 : MAINTAINER lienhua34@163.com
---> Running in ce9e7b02f075
---> 332259a92e74
Removing intermediate container ce9e7b02f075
Step 3 : RUN mkdir /opt/leh
---> Running in e93f0a98040f
---> 097e177cf37f
Removing intermediate container e93f0a98040f
Step 4 : RUN touch /opt/leh/test
---> Running in f1531d3dea1a
---> 0f68852f8356
Removing intermediate container f1531d3dea1a
Step 5 : CMD echo "Hello lienhua34"
---> Running in cf3c5ce2af46
---> 811ce27ce692
Removing intermediate container cf3c5ce2af46
Successfully built 811ce27ce692
复制代码
然后启动该镜像的容器来查看结果,
lienhua34@test$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
test 0.0.1 811ce27ce692 32 seconds ago 187.9 MB
lienhua34@test$ sudo docker run -ti test:0.0.1
Hello lienhua34
Dockerfile文件的每条指令生成镜像的一层(注:一个镜像不能超过127层)。Dockerfile中的指令被一条条地执行。每一步都创建一个新的容器,在容器中执行指令并提交修改。当所有指令执行完毕后,返回最终的镜像id。
4.Dockerfile文件中的CMD和ENTRYPOINT指令差异对比
CMD指令和ENTRYPOINT指令的作用都是为镜像指定容器启动后的命令,那么它们两者之间有什么各自的优点呢?
为了更好地对比CMD指令和ENTRYPOINT指令的差异,我们这里再列一下这两个指令的说明,
CMD
支持三种格式
CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式;
CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用;
CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数;
指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。
如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。
ENTRYPOINT
两种格式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2(shell中执行)。
配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。
每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效。
从上面的说明,我们可以看到有两个共同点:
都可以指定shell或exec函数调用的方式执行命令;
当存在多个CMD指令或ENTRYPOINT指令时,只有最后一个生效;
而它们有如下差异:
差异1:CMD指令指定的容器启动时命令可以被docker run指定的命令覆盖,而ENTRYPOINT指令指定的命令不能被覆盖,而是将docker run指定的参数当做ENTRYPOINT指定命令的参数。
