前言
Docker可以通过读取Dockerfile中的指令来自动构建图像。Dockerfile是一个文本文档,包含用户可以在命令行上调用的所有命令来组装一个图像。使用docker构建用户可以创建一个自动构建,该构建可以连续执行多个命令行指令。
构建方法
# 这里的"."代表了目录结构上下文
docker build .
# -f可以指定Dockerfile文件路劲,但是后面一定要用".",并且你当前的位置一定要在文件所要上传的目录位置
docker build -f /path/Dockerfile .
# -t 指定构建后的镜像名称
docker build -t host-1 -f /path/Dockerfile .
# --no-cache表示构建过程中的所产生的缓存不做保留
docker build --no-cache .
构建由Docker守护进程运行,而不是由CLI运行。构建流程要做的第一件事是将整个上下文(递归地)发送给守护进程。在大多数情况下,最好从一个空目录作为上下文开始,并将Dockerfile保存在该目录中。只添加构建Dockerfile所需的文件。要在构建上下文中使用文件,Dockerfile引用一条指令中指定的文件,例如一条复制指令。要提高构建的性能,可以通过在上下文目录中添加.dockerignore文件来排除文件和目录。有关如何创建.dockerignore文件的信息,请参阅此页上的文档。传统上,Dockerfile称为Dockerfile,位于上下文的根目录中。在docker build中使用-f标志指向文件系统中任何位置的Dockerfile。
指令详解
Dockerfile中的指令都会产生一个镜像层,哪怕你只是一个很小的声明也会产生一个镜像层。
ARG
ARG是docker.17版本之后出现的功能,是用来声明dockerfile所使用的变量,语法如下:
ARG <name>[=<default value>]
示例如下:
ARG VERSION=latest FROM busybox:$VERSION ARG VERSION RUN echo $VERSION > image_version # 或者 FROM busybox ARG user1=someuser ARG buildno=1
注意:ARG变量定义从Dockerfile中定义它的行开始生效,而不是从命令行或其他地方使用参数开始。使用ENV指令定义的环境变量总是覆盖同名的ARG指令。
FROM
FROM指令初始化一个新的构建阶段,并为后续指令设置基本映像。因此,一个有效的Dockerfile必须从FROM指令开始。图像可以是任何有效的图像—从公共存储库中提取图像尤其容易。语法如下:
FROM <image> [AS <name>] FROM <image>[:<tag>] [AS <name>] FROM <image>[@<digest>] [AS <name>]
注意:FROM指令中有一个特殊镜像"scratch",表示使用空镜像,不依赖任何底层。
RUN
RUN指令将在当前映像之上的新层中执行任何命令并提交结果。生成的提交映像将用于Dockerfile中的下一步。RUN指令支持两种格式,样式如下:
RUN <command> RUN ["executable", "param1", "param2"] 示例1 RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME' 示例2 RUN ["/bin/bash", "-c", "echo hello"]
注意:如果使用exec执行的这种方式,括号内的参数一定要用双引号括起来
CMD
CMD一般用于镜像构建之后预定默认运行的指令,类似于操作系统的开机自启动,因为容器中没有开机与关机这一说,所以只能设定预定运行程序;注意CMD是默认运行指令,言外之意它与其他指令冲突的时候,它不会运行。尤其是ENTRYPOINT;语法格式如下:
CMD ["executable","param1","param2"] CMD ["param1","param2"]
CMD command param1 param2
需要注意:当镜像运行的时候,用户手动指定了程序,则CMD里面的内容会自动失效;若Dockerfile中有ENTRYPOINT指令,则CMD会将后面的内容当成参数传递到ENTRYPOINT指令中,就是上面的第二种使用方式。
详情请参考:https://blog.csdn.net/u010900754/article/details/78526443
LABEL
LABEL主要用来设置一些描述信息的标签,语法格式如下:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
示例如下:
LABEL "com.example.vendor"="ACME Incorporated" LABEL com.example.label-with-value="foo" LABEL version="1.0" LABEL description="This text illustrates that label-values can span multiple lines." LABEL multi.label1="value1" multi.label2="value2" other="value3" LABEL multi.label1="value1" multi.label2="value2" other="value3"
EXPOSE
- EXPOSE指令通知Docker容器在运行时监听指定的网络端口。您可以指定端口监听TCP还是UDP,如果没有指定协议,则默认为TCP。
- EXPOSE指令实际上并不发布端口。它作为构建映像的人员和运行容器的人员之间的一种文档类型,用于发布关于哪些端口的信息。要在运行容器时实际发布端口,请使用docker run上的-p标志发布和映射一个或多个端口,或者使用-p标志发布所有公开的端口并将它们映射到高阶端口。
- EXPOSE默认情况下假定TCP。你也可以指定UDP:
# 语法 EXPOSE <port> [<port>/<protocol>...] # 示例 EXPOSE 80/udp EXPOSE 80/udp
ENV
设定容器运行时的环境变量,语法如下:
ENV <key> <value> ENV <key>=<value>
示例如下:
ENV myName="John Doe" myDog=Rex The Dog myCat=fluffy ENV myName John Doe ENV myDog Rex The Dog ENV myCat fluffy
ADD
ADD指令从复制新的文件、目录或远程文件url,并将它们添加到路径的映像文件系统中。可以指定多个资源,但是如果它们是文件或目录,它们的路径将被解释为相对于构建上下文的源。语法如下:
ADD [--chown=<user>:<group>] <src>... <dest> ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
示例
ADD ["http://pic37.nipic.com/20140113/8800276_184927469000_2.png","/opt"]
注意:ADD添加文件到指定目录并解压,还可支持URL,但是URL仅支持web协议,不支持其他协议,例如:ftp传输协议
COPY
COPY指令从复制新的文件,并将它们添加到路径的映像文件系统中;COPY不会自动解压,不支持URL。语法如下:
COPY [--chown=<user>:<group>] <src>... <dest> COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
ENTRYPOINT
ENTRYPOINT指定容器运行后必须运行的内容,ENTRYPOINT必须指定运行入口,同CMD类似,多条ENTRYPOINT只有最下面那条能够执行,语法如下:
ENTRYPOINT ["executable", "param1", "param2"] ENTRYPOINT command param1 param2
注意:ENTRYPOINT的内容也是可以在docker run的时候进行覆盖,只需要使用--entrypoint选项即可
示例如下:
FROM debian:stable RUN apt-get update && apt-get install -y --force-yes apache2 EXPOSE 80 443 VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"] ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"] # 或者 FROM ubuntu ENTRYPOINT exec top -b
VOLUME
VOLUME 指令可以在镜像中创建挂载点,将镜像中的内容挂载到本地,这样只要通过该镜像创建的容器都有了挂载点。但是通过 VOLUME 指令创建的挂载点,无法指定主机上对应的目录,是自动生成的。语法如下:
VOLUME ["/data"]
示例如下:
FROM ubuntu RUN mkdir /myvol RUN echo "hello world" > /myvol/greeting VOLUME /myvol
USER
设定容器运行时的用户与用户组,当没有指定USER指令时,默认采用管理员用户,语法如下:
USER <user>[:<group>] or USER <UID>[:<GID>]
WORKDIR
指定当前工作的工作目录,docker官方推荐使用的指令,不建议使用"RUN cd"这样的方式来进行目录的切换,语法如下:
WORKDIR /path/to/workdir
示例如下:
WORKDIR /a WORKDIR b WORKDIR c RUN pwd
ONBUILD
当我们在一个Dockerfile文件中加上ONBUILD指令,该指令对利用该Dockerfile构建镜像(比如为A镜像)不会产生实质性影响。但是当我们编写一个新的Dockerfile文件来基于A镜像构建一个镜像(比如为B镜像)时,这时构造A镜像的Dockerfile文件中的ONBUILD指令就生效了,在构建B镜像的过程中,首先会执行ONBUILD指令指定的指令,然后才会执行其它指令。需要注意的是,如果是再利用B镜像构造新的镜像时,那个ONBUILD指令就无效了,也就是说只能再构建子镜像中执行,对孙子镜像构建无效。其实想想是合理的,因为在构建子镜像中已经执行了,如果孙子镜像构建还要执行,相当于重复执行,这就有问题了。 语法如下:
ONBUILD [INSTRUCTION]
示例如下:
# 第一个Dockerfile FROM ubuntu MAINTAINER hello ONBUILD RUN mkdir mydir # 第二个Dockerfile FROM imagea MAINTAINER hello1
STOPSIGNAL
设置容器优雅的退出进程与程序,这样可以保持数据的安全性与用户体验。语法如下:
STOPSIGNAL signal
示例:
STOPSIGNAL sigkill
信号参考大全:https://www.cnblogs.com/guge-94/p/11019605.html
信号退出原理:https://www.jb51.net/article/96617.htm
HEALTHCHECK
对容器运行的指定内容做健康检查,语法如下:
HEALTHCHECK [OPTIONS] CMD command HEALTHCHECK NONE
选项讲解如下:
--interval=DURATION (default: 30s)
--timeout=DURATION (default: 30s)
--start-period=DURATION (default: 0s)
--retries=N (default: 3)
- interval:间隔(s秒、m分钟、h小时),从容器运行起来开始计时interval秒(或者分钟小时)进行第一次健康检查,随后每间隔interval秒进行一次健康检查;还有一种特例请看timeout解析。
- timeout:执行command需要时间,比如curl 一个地址,如果超过timeout秒则认为超时是错误的状态,此时每次健康检查的时间是timeout+interval秒
- retries:连续检查retries次,如果结果都是失败状态,则认为这个容器是unhealth的
示例如下:
HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
参考地址:https://blog.csdn.net/tech_salon/article/details/77255915
SHELL
用于指定执行程序所使用的解释器,一般主要应用与Windows场景,因为linux一般都是用bash,语法如下:
SHELL ["executable", "parameters"]
示例如下:
FROM microsoft/windowsservercore # Executed as cmd /S /C echo default RUN echo default # Executed as cmd /S /C powershell -command Write-Host default RUN powershell -command Write-Host default # Executed as powershell -command Write-Host hello SHELL ["powershell", "-command"] RUN Write-Host hello # Executed as cmd /S /C echo hello SHELL ["cmd", "/S", "/C"] RUN echo hello