Dockerfile
自制镜像
基于容器制作
Dockerfile
Dockerfile是用来构建Docker镜像的源码
Dockerfile格式
#Comment 注释信息
INSTRUCTION arguments 指令 参数
指令一般为大写(不区分大小写)
在Dockerfile中的指令是顺序执行,有先后次序性
所有镜像制作过程都是建立在某个已存在镜像的基础上制作;
第一个非注释行必须写“FORM”
制作镜像过程中可以使用环境变量,也可做环境变量替换;与bash shell用法一样
支持bash shell中特殊用法
${variable:-word}
${variable:+word}
Dockerfile工作流程
制作镜像时,必须有一个专用工作目录,里面有个Dockerfile文件且首字母大写;
将所有打包进镜像的文件都放置于工作目录,所需文件的起始路径为工作目录;工作目录可以有子目录;
.dockerignore file:黑名单列表,一行写一个文件路径,可使用通配符;包括ignore file本身;
基于Dockerfile制作镜像是由docker build来完成,而docker build也会隐藏式的启动一个容器;因此,在Dockerfile中可以执行许多Shell命令,所执行的Shell命令都是底层镜像所提供的;所有的制作环境都是低层镜像启动容器所能够提供的环境
Dockerfile Instructions Dockerfile指令
FROM
FROM指令是最重要的一个且必须为Dockerfile文件开篇的第一个非注释行,用于为映像文件构建过程指定基准镜像,后续的指令运行于此基准镜像所提供的运行环境
实践中,基准镜像可以是任何可用镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会从Docker Hub Registry上拉取所需的镜像文件
如果找不到指定的镜像文件,docker build会返回一个错误信息
Syntax
FROM <repository>[:<tag>]或
FROM <repository>@<digest>
<reposotiry>:指定作为base image的名称;
<tag>:base image的标签,为可选项,省略时默认为latest;
MAINTANIER(depreacted)
用于让Dockerfile制作者提供本人的详细信息
Dockerfile并不限制MAINTAINER指令可在出现的位置,但推荐将其放置于FROM指令之后
Syntax
MAINTAINER <author's detail>
<author's detail>可以是任何文本信息,但约定俗成地使用作者名称及邮件地址
例:MAINTAINER "liuyutang <lyt0688@qq.com>"
LABEL
用于让用户为镜像指定元数据
Syntax
LABEL <key>=<value> <key>=<value> <key>=<value>...
COPY
用于从Docker主机复制文件至创建的新映像文件(从宿主机的当前工作目录把某些文件复制到目标映像中)
Syntax
COPY <src>...<dest>或
COPY ["<src>"..."<dest>"]
<src>:要复制的源文件或目录,支持使用通配符
<dest>: 目标路径,即正在创建的image的文件系统路径;建议为<dest>使用绝对路径,否则,COPY指定则以WORKDIR为其起始路径;
注意:在路径中有空白字符时,通常使用第二种格式
文件复制准则
<src>必须是build上下文中的路径,不能是其父目录中的文件
如果<src>是目录,则其内部文件或子目录会被递归复制,但<src>目录自身不会被复制
如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,且必须以/结尾
如果<dest>事先不存在,它将会被自动创建,这包括其父目录路径
ADD
ADD指令类似于COPY指令,ADD支持使用TAR文件和URL路径
Syntax
ADD <src> ... <dest>或
ADD ["<src>",..."<dest>"]
操作准则
同COPY指令
如果<src>为URL且<dest>不以/结尾,则<src>指定的文件将被下载并直接被创建为<dest>;如果<dest>以/结尾,则文件名URL指定的文件将被直接下载并保存为<dest>/<filename>
如果<src>是一个本地系统上的压缩格式的tar文件,它将被展开为一个目录,其行为类似于“tar -x”命令;然而,通过URL获取到的tar文件将不会自动展开;
如果<src>有多个,或其间接或直接使用了通配符,则<dest>必须是一个以/结尾的目录路径;如果<dest>不以/结尾,则其被视作一个普通文件,<src>的内容将被直接写入到<dest>;
WORKDIR
用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和ADD指定设定工作目录
Syntax
WORKDIR <dirpath>
在Dockerfile文件中,WORKDIR指令可出现多次,其路径也可以为相对路径,不过,其是相对此前一个WORKDIR指令指定的路径
另外,WORKDIR也可调用由ENV指定定义的变量
例如
WORKDIR /var/log
WORKDIR $STATEPATH
VOLUME
用于在image中创建一个挂载点目录,以挂载Docker host上的卷或其它容器上的卷
Syntax
VOLUME <mountpoint>或
VOLUME ["<mountpoint>"]
如果挂载点目录路径下此前在文件存在,docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中
EXPOSE
用于为容器打开指定要监听的端口以实现与外部通信
Syntax
EXPOSE <port>[/<protocol>][<port>[/<protocol>]...]
<protocol>用于指定传输层协议,可为tcp或者udp二者之一,默认为tcp协议
EXPOSE指令可一次指定多个端口,例如
EXPOSE 11211/udp 11211/tcp
ENV
用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的其它指令(如ENV,ADD,COPY等)所调用
调用格式为$variable_name或${variable_name}
Syntax
ENV <key> <value> 或
ENV <key>=<value> ...
第一种格式中,<key>之后的所有内容均会被视作其<value>组成部分,因此,一次只能设置一个变量;
第二种格式可用一次设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<value>中包含空格,可以以反斜线(\)进行转义,也可通过对<value>加引号进行标识;另外,反斜线也可用于续行;
定义多个变量时,建议使用第二种方式,以便在同一层中完成所有功能;
RUN
用于指定docker build过程中运行的程序,其可以是任何命令
Syntax
RUN <command>或
RUN ["<executable>","<param1>","<param2>"]
第一种格式中,<command>通常是一个shell命令,且以"/bin/sh -c"来运行它,这意味着此进程在容器中的PID不为1,不能接收Unix信号,因此,当使用docker stop <container>命令停止容器时,此进程接收不到SIGTERM信号;
第二种语法格式中的参数是一个JSON格式的数组,其中<executable>为要运行的命令,后面的<paramN>为传递给命令的选项或参数;然而,此种格式指定的命令不会以"/bin/sh -c"来发起,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行;不过,如果要运行的命令依赖于此shell特性的话,可以将其替换为类似下面的格式:
RUN ["/bin/bash","-c","<executable>","<param1>"]
注意:json数组中,要使用双引号
建议使用格式
RUN COMMAND 1 && \
COMMAND 2
CMD
类似于RUN指令,CMD指令也可用于运行任何命令或应用程序,不过,二者的运行时间点不同
RUN指令运行于映像文件构建过程中,而CMD指令运行于基于Dockerfile构建出的新映像文件启动一个容器时
CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止;不过,CMD指定的命令其可以被docker run的命令行选项所覆盖
在Dockerfile中可以存在多个CMD指令,但仅最后一个会生效
Syntax
CMD <command>或
CMD ["<executable>","<param1>","<param2>"]或
CMD ["<param1>","<param2"]
前两种语法格式的意义同RUN
第三种则用于为ENTRYPOINT指令提供默认参数
使用示例
~]#mkdir img2 ~]#cd img2 img2]#vim Dockerfile FROM busybox LABEL maintainer="Liuyutang <lyt0688@qq.com>" app="httpd" ENV WEB_DOC_ROOT="/data/web/html" RUN mkdir -p $WEB_DOC_ROOT && \ echo '<h1>Busybox httpd server.</h1>' > ${WEB_DOC_ROOT}/index.html CMD /bin/httpd -f -h ${WEB_DOC_ROOT ~]#docker run --name tinyweb2 -it --rm -P tinyhttpd:v0.2-1 img2]#docker build -t tinyhttpd:v0.2-1 ./ ~]#docker exec -it tinyweb2 /bin/sh / # / # ps PID USER TIME COMMAND 1 root 0:00 /bin/httpd -f -h /data/web/html 6 root 0:00 /bin/sh 12 root 0:00 ps / # printenv WEB_DOC_ROOT=/data/web/html HOSTNAME=42026724afa9 SHLVL=1 HOME=/root TERM=xterm PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PWD=/ / #
ENTRYPOINT
类似CMD指令功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序
与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定的程序
不过,docker run命令的--entrypoint选项的参数
USER
用于指定运行image时或运行Dockerfile中任何RUN、CMD、
HEALTHCHECK
使用健康状态检测的工具来进行检测
Syntax
HEALTHCHECK [OPTIONS] CMD command
HEALTHCHECK NONE
OPTIONS
--interval=DURATION (default:30s)
--timeout=DURATION (default:30s)
--start-period=DURATION (default: 0s) 生产中建议修改
--retries=N (default: 3)
返回值
0:success 成功
1:unhealthy 不健康
2:reserved 预留
示例
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1
SHELL
用于指定运行程序默认要使用的Shell;Linux默认使用的是["/bin/sh", "-c"],Windows 默认使用的是 ["cmd", "/S","/C"]
STOPSIGNAL
Syntax
STOPSIGNAL signal
ARG
定义变量,只在build过程中使用;一个dockerfile能够适用不同场景
示例:
img3]#vim Dockerfile FROM nginx:1.14-alpine ARG author="liuyutang" LABEL maintainer=${author} ENV NGX_DOC_ROOT='/data/web/html/' ADD index.html ${NGX_DOC_ROOT} ADD entrypoint.sh /bin/ EXPOSE 80/tcp HEALTHCHECK --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:10080/ CMD ["/usr/sbin/nginx","-g","daemon off;"] ENTRYPOINT ["/bin/entrypoint.sh"] img3]#docker build --build-arg author="IT <IT@qq.com>" -t myweb:v0.3-10 ./ img3]#docker image inspect myweb:v0.3-10
ONBUILD
用于在Dockerfile中定义一个触发器
Dockerfile用于build映像文件,此映像文件亦可作为base image被另一个Dockerfile用作FROM指令的参数,并以之构建新的映像文件
在后面的这个Dockerfile中的FROM指令在build过程中被执行时,将会“触发”创建其base image的Dockerfile文件中的ONBUILD指令定义的触发器
Syntax
ONBUILD <INSTRUCTION>
尽管任何指令都可注册成为触发器指令,但ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令
使用包含ONBUILD指令的Dockerfile构建的镜像,应该使用特殊的标签,例如ruby:2.0-onbuild
在ONBUILD指令中使用ADD或COPY指令应该格外小心,因为新构建过程的上下文在缺少指定的源文件时会失败
注意:在Dockerfile中一个指令会生成一个新层;因此,如果两条指令可以合并在一起,尽量合在一起
镜像制作有两个阶段
docker build
docker run
基于Dockerfile制作镜像
使用docker build命令
~]#docker build --help Usage: docker build [OPTIONS] PATH | URL | - Build an image from a Dockerfile
转载于:https://blog.51cto.com/10461810/2154791