dockerfile 是创建docker镜像的文本,可以使用docker build -t name . 命令创建对应的docker镜像。docker在创建镜像的过程中会首先创建容器,然后根据每一个命令,构建容器的每一层,最终构建整个镜像的文件。镜像文件使用的时候,也是将每层分别overlay到下层之上。
1. ADD 与COPY命令
Dockerfile中的COPY指令和ADD指令,将主机上的资源复制或添加到容器镜像中,每一行命令都构建容器镜像的一层。
COPY指令和ADD指令的区别:
- ADD命令支持从远程URL获取资源并复制到镜像中,COPY指令只能从执行docker build所在的主机上读取资源并复制到镜像中。
- ADD命令可以将整个tar包,拷贝到镜像文件中,并进行解压缩。
满足同等功能的情况下,推荐使用COPY指令。ADD指令更擅长读取本地tar文件并解压缩。
COPY指令
COPY指令能够将构建命令所在的主机本地的文件或目录,复制到镜像文件系统。
exec格式用法(推荐):
COPY ["
shell格式用法:
COPY
ADD指令
exec格式用法(推荐):
ADD ["
shell格式用法:
ADD
说明,对于从远程URL获取资源的情况,由于ADD指令不支持认证,如果从远程获取资源需要认证,则只能使用RUN wget或RUN curl替代。
另外,如果源路径的资源发生变化,则该ADD指令将使Docker Cache失效,Dockerfile中后续的所有指令都不能使用缓存。因此尽量将ADD指令放在Dockerfile的后面。
注意事项:
- 原路径
源路径可以有多个
源路径是相对于执行build的相对路径
源路径如果是本地路径,必须是build上下文中的路径
源路径如果是一个目录,则该目录下的所有内容都将被加入到容器,但是该目录本身不会 - 目标路径
目标路径必须是绝对路径,或相对于WORKDIR的相对路径
目标路径如果不存在,则会创建相应的完整路径
目标路径如果不是一个文件,则必须使用/结束
路径中可以使用通配符
读取URL远程资源
当要读取URL远程资源的时候,并不推荐使用ADD指令,而是使用RUN指令,在RUN指令中执行wget或curl命令。
RUN mkdir -p /usr/src/things
&& curl -SL http://example.com/big.tar.xz
| tar -xJC /usr/src/things
&& make -C /usr/src/things all
CMD与ENTRYPOINT
CMD指令可以指定容器启动时要执行的命令,但它可以被docker run命令的参数覆盖掉。
ENTRYPOINT 指令和CMD类似,它也可用户指定容器启动时要执行的命令。dockerfile中可以有多条cmd命令,但只是最后一条有效。
如果dockerfile中也有CMD指令,CMD中的参数会被附加到ENTRYPOINT 指令的后面。
如果这时docker run命令带了参数,这个参数会覆盖掉CMD指令的参数,并也会附加到ENTRYPOINT 指令的后面。
这样当容器启动后,会执行ENTRYPOINT 指令的参数部分。可以看出,相对来说ENTRYPOINT指令优先级更高。
CMD命令的参数格式,一般写成 字符串数组的方式,如上面的例子。如:
CMD ["echo","hello world"]
虽然也可写成CMD echo hello word 方式,但这样docker会在指定的命令前加 /bin/sh -c 执行,有时有可能会出问题。 所以推荐采用数据结构的方式来存放命令。
#test
FROM ubuntu
MAINTAINER hello
RUN echo hello1 > test1.txt
RUN echo hello2 > /test2.txt
EXPOSE 80
ENTRYPOINT ["echo"]
CMD ["defaultvalue"]
当运行 docker run image 输出的内容是 defaultvalue,可以看出CMD指令的参数得确是被添加到ENTRYPOINT指令的后面,然后被执行。
当运行docker run myimage hello world 输出的内容是 hello world ,可以看出docker run命令的参数得确是被添加到ENTRYPOINT指令的后面,然后被执行,这时CMD指令被覆盖了。
另外我们可以在docker run命令中通过 --entrypoint 覆盖dockerfile文件中的ENTRYPOINT设置,如:
docker run --entrypoint="echo" myimage good 结果输出good
注意,不管是哪种方式,创建容器后,通过 dokcer ps查看容器信息时,COMMOND列会显示最终生效的启动命令。
EXPOSE 命令
EXPOSE port [port2,port3,...],例如EXPOSE 80这条指令告诉Docker服务器暴露80端口,供容器外部连接使用。
在启动容器的使用使用-P,Docker会自动分配一个端口和转发指定的端口,使用-p可以具体指定使用哪个本地的端口来映射对外开放的端口。
EXPOSE命令只是声明了容器应该打开的端口,并没有实际上将它打开!
如果不用-p或者-P中指定要映射的端口,容器不会映射端口出去。不能在Dockerfile里面进行端口映射,只能在容器启动的时候或者在docker-compose文件中使用ports来指定将要映射的端口。
EXPOSE命令的作用
- 写在Dockerfile中进行声明,能让运维人员或者后来者知道我们开启了容器的哪些端口。
- 当我们声明了EXPOSE端口之后,我们使用-P命令进行随机映射的时候,是会对这个端口进行映射的。
比如说我们现在对一个tomcat容器进行EXPOSE 9999声明,那么我们进行-P随机映射的时候是会对9999端口进行映射的。
WORKDIR命令
格式: WORKDIR /path
为RUN CMD ENTRYPOINT指定配置工作目录,可以使用多个WORKDIR指令,若后续指令用得是相对路径,则会基于之前的命令指定路径。
当最后指定workdir时,容器启动时运行在指定的workdir下。
比如,cmd 指定的指令要访问,同目录下的配置文件,就需要指定workdir,把相应的工作目录切换到workdir下。