dockerfile其实就是记录'火箭发射'步骤的文件,它记载了从一个镜像建立另外一个新镜像的步骤。撰写好Dockerfile文件以后,咱们就能够垂手可得的使用docker build
命令来建立镜像了。java
Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,所以每一条指令的内容,就是描述该层应当如何构建。有了 Dockerfile,当咱们须要定制本身额外的需求时,只需在 Dockerfile 上添加或者修改指令,从新生成 image 便可,省去了敲命令的麻烦。python
下面是一个dockerfile文件的例子:linux
FROM openjdk:8-jdk-alpine
MAINTAINER Kurisu "makise_kurisuu@outlook.jp"
LABEL maintainer="makise_kurisuu@outlook.jp" VOLUME /tmp ARG JAR_FILE=target/alice-server.jar
COPY ${JAR_FILE} app.jar ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] 复制代码
部分 | 命令 |
---|---|
基础镜像信息 | FROM |
维护者信息 | MAINTAINER |
镜像操做指令 | RUN、COPY、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等 |
容器启动时执行指令 | CMD、ENTRYPOINT |
FROM
构建的镜像设置基础镜像golang
FROM <image> [AS <name>]
FROM <image>[:<tag>] [AS <name>]
FROM <image>[@<digest>] [AS <name>]
复制代码
FROM
指令初始化新的构建阶段,并为后续指令设置基础镜像,e.g: FROM openjdk:8-jdk-alpine
。所以,Dockerfile文件必须以FROM
指令开头。 而指定的镜像可使任何有效的镜像(推荐使用公共仓库的镜像,由于拉取更为容易)。docker
ARG
是惟一一个能够用于FROM
以前的指令。ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app
FROM extras:${CODE_VERSION}
CMD /code/run-extras 复制代码
FROM golang:1.10.3
COPY server.go /build/ WORKDIR /build RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOARM=6 go build -ldflags '-w -s' -o server ENTRYPOINT ["/build/server"] 复制代码
FROM
指令中添加AS 名称
来指定一个名称给后续阶段的FROM
和COPY --from=<name|index>
使用。RUN
在镜像的构建过程当中执行特定的命令,并生成一个中间镜像。好比安装一些软件、配置一些基础环境,可以使用\来换行。shell
RUN <command> (shell格式)
RUN ["executable", "param1", "param2"] (exec格式)
复制代码
要注意的是,executable是命令,后面的param是参数
采用exec格式指令将会被解析成json格式因此不能使用单引号,而且使用反斜杠也是必需要转移的,这在windows上尤其重要。json
CMD
指定容器运行时的默认参数。ubuntu
CMD ["executable","param1","param2"](exec格式,首选)
CMD ["param1","param2"](给ENTRYPOINT提供默认参数)
CMD command param1 param2(shell格式)
复制代码
注意:
RUN
是在构建的时候执行,并生成一个新的镜像,CMD
在构建时不进行任何操做,在容器运行的时候执行。
若是CMD
用于为ENTRYPOINT
指令提供缺省参数,那么CMD
和ENTRYPOINT
指令都应该使用JSON数组格式。windows
LABEL
给构建的镜像打标签。数组
LABEL <key>=<value> <key>=<value> <key>=<value> ...
复制代码
标签是键值对格式,要在标签中包含空格则需转义或用引号"
括起来。e.g:
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" 复制代码
MAINTAINER(已弃用)
设置做者信息。
MAINTAINER <name>
复制代码
LABEL
比MAINTAINER
更灵活,推荐使用LABEL
,弃用MAINTAINER
。
LABEL maintainer="makise_kurisuu@outlook.jp"
复制代码
EXPOSE
为构建的镜像设置监听端口。
EXPOSE <port> [<port>/<protocol>...]
复制代码
EXPOSE
指令让docker容器在运行的时候监听指定的端口,能够指定端口是upd仍是tcp协议,若是没有指定则默认tcp协议。
EXPOSE
指令并不会发布端口,若是发布端口,则须要在docker run时使用-p来发布和映射一个或多个容器端口、或者使用-P来发布全部公开的端口 并将它们映射到高阶端口。
ENV
在构建的镜像中设置环境变量,在后续的Dockerfile指令中能够直接使用,也能够固化在镜像里,在容器运行时仍然有效。 ENV
指令有两种格式:
"
括起来。ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy
复制代码
或者
ENV myName="John Doe" myDog=Rex\ The\ Dog \
myCat=fluffy
复制代码
推荐使用第二种,一样的这样能减小图层提升效率。
注意:能够在容器运行时指定环境变量,替换镜像中的已有变量,
docker run --env <key>=<value>
。
使用ENV可能会对后续的Dockerfile指令形成影响,若是只须要对一条指令设置环境变量,可使用这种方式:RUN <key>=<value> <command>
ADD
构建镜像时,复制上下文中的文件到镜像内。
ADD <src>... <dest>
ADD ["<src>",... "<dest>"](路径包含空格的必须使用这种格式)
复制代码
<src>
能够是文件、目录,也能够是文件URL。可使用模糊匹配(wildcards,相似shell的匹配),能够指定多个<src>
,必须是在上下文目录和子目录中, 没法添加../a.txt
这样的文件。若是<src>
是个目录,则复制的是目录下的全部内容,但不包括该目录。若是<src>
是个可被docker识别的压缩包, docker会以tar -x的方式解压后将内容复制到<desct>
。<dest>
能够是绝对路径,也能够是相对WORKDIR目录的相对路径。 全部文件的UID和GID都是0。
若是docker发现文件内容被改变,则接下来的指令都不会再使用缓存。
关于复制文件时须要处理的/,基本跟正常的copy一致。
COPY
将主机的文件复制到镜像内,若是目的位置不存在,Docker会自动建立全部须要的目录结构,可是它只是单纯的复制,并不会去作文件提取和解压工做。
COPY <src>... <dest>
COPY ["<src>",... "<dest>"](路径包含空格的必须使用这种格式)
复制代码
注意:须要复制的目录必定要放在Dockerfile文件的同级目录下。
由于构建环境将会上传到Docker守护进程,而复制是在Docker守护进程中进行的。任何位于构建环境以外的东西都是不可用的。 COPY指令的目的的位置则必须是容器内部的一个绝对路径。
COPY指令
ENTRYPOINT
指定镜像的执行程序。ENTRYPOINT
指令有两种格式:
ENTRYPOINT ["executable", "param1", "param2"] (执行格式,首选)
ENTRYPOINT command param1 param2 (shell格式)
复制代码
详细参考:ENTRYPOINT指令
CMD
和ENTRYPOINT
至少得使用一个。ENTRYPOINT
应该被当作docker的可执行程序,CMD应该被当作ENTRYPOINT
的默认参数。 docker run <image> <arg1> <arg2> ...
会把以后的参数传递给ENTRYPOINT
,覆盖CMD指定的参数。能够用docker run --entrypoint
来重置默认的ENTRYPOINT
。
— | No ENTRYPOINT | ENTRYPOINT exec_entry p1_entry | ENTRYPOINT ["exec_entry", "p1_entry"] |
---|---|---|---|
No CMD | error, not allowed | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry |
CMD ["exec_cmd", "p1_cmd"] | exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry exec_cmd p1_cmd |
CMD ["p1_cmd", "p2_cmd"] | p1_cmd p2_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry p1_cmd p2_cmd |
CMD exec_cmd p1_cmd | CMD exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
VOLUME
指定镜像内的目录为数据卷。
VOLUME ["/data"]
复制代码
在容器运行的时候,docker会把镜像中的数据卷的内容复制到容器的数据卷中去。 若是在接下来的Dockerfile指令中,修改了数据卷中的内容,则修改无效。
USER
为接下来的Dockerfile指令指定用户。受影响的指令有:RUN
、CMD
、ENTRYPOINT
。
USER <user>[:<group>] or
USER <UID>[:<GID>]
复制代码
注意:当用户没有主要组时,镜像(或下一条指令)将与该root组一块儿运行。
WORKDIR
为接下来的Dockerfile指令指定当前工做目录,可屡次使用,若是使用的是相对路径,则相对的是上一个工做目录,相似shell中的cd命令。
WORKDIR /path/to/workdir
复制代码
受影响的指令有:RUN
、CMD
、ENTRYPOINT
、COPY
和ADD
。 能够在Dockerfile中屡次使用WORKDIR
指令。若是提供了相对路径,则它将相对于上一个WORKDIR
指令的路径。例如:
WORKDIR /a WORKDIR b WORKDIR c RUN pwd 复制代码
此Dockerfile中pwd
指令将输出 /a/b/c.
。
WORKDIR
指令能够解析以前使用ENV
设置的环境变量,只能使用Dockerfile中显式设置的环境变量。例如:
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME RUN pwd 复制代码
此Dockerfile中pwd
指令将输出 /path/$DIRNAME
。
ARG
指定用户在docker build --build-arg <varname>=<value>
时可使用的参数。
ARG <name>[=<default value>]
复制代码
若是用户指定了未在Dockerfile中定义的构建参数,则构建会输出警告。
[Warning] One or more build-args [foo] were not consumed.
复制代码
构建参数在定义的时候生效而不是在使用的时候。以下面第三行开始的user才是用户构建参数传递过来的user:
FROM busybox
# 此处获取不到用户传来的user
USER ${user:-some_user}
ARG user
USER $user
复制代码
您可使用ARG
或ENV
指令指定RUN
指令可用的变量。使用ENV
指令定义的环境变量始终覆盖同名的ARG
指令。
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER v1.0.0
# 始终是v1.0.0
RUN echo $CONT_IMG_VER 复制代码
正确的用法:
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER ${CONT_IMG_VER:-v1.0.0}
RUN echo $CONT_IMG_VER 复制代码
要在多个阶段中使用arg,每一个阶段都必须包含该ARG指令。
FROM busybox
ARG SETTINGS
RUN ./run/setup $SETTINGS
FROM busybox
ARG SETTINGS
RUN ./run/other $SETTINGS 复制代码
此外docker还内置了一批构建参数,能够不用在Dockerfile中声明:HTTP_PROXY
、http_proxy
、HTTPS_PROXY
、https_proxy
、FTP_PROXY
、 ftp_proxy
、NO_PROXY
、no_proxy
注意:在使用构建参数(而不是在构建参数定义的时候)的指令中,若是构建参数的值发生了变化,会致使该指令发生变化,会从新寻找缓存。
ONBUILD
向镜像中添加一个触发器,当以该镜像为基础镜像再次构建新的镜像时,会触发执行其中的指令。
ONBUILD [INSTRUCTION]
复制代码
好比咱们生成的镜像是用来部署Python代码的,可是由于有多个项目可能会复用该镜像。你能够这样使用:
[...]
# 在下一次以此镜像为base image的构建中,执行ADD . /app/src,将项目代目添加到新镜像中去
ONBUILD ADD . /app/src # 而且build Python代码
ONBUILD RUN /usr/local/bin/python-build --dir /app/src [...]
复制代码
不容许
ONBUILD
使用连接指令ONBUILD ONBUILD
。
ONBUILD
只会继承给子节点的镜像,不会再继承给孙子节点。
ONBUILD
不会触发FROM
、MAINTAINER
指令。
STOPSIGNAL
触发系统信号。
STOPSIGNAL signal
复制代码
STOPSIGNAL
指令设置将发送到容器以退出的系统调用信号。此信号能够是与内核的SysCall表中的位置匹配的有效无符号数字(例如9),也能够是格式为SIGNAME的信号名称(例如SIGKILL)。
HEALTHCHECK
增长自定义的心跳检测功能,屡次使用只有最后一次有效。格式:
HEALTHCHECK [OPTIONS] CMD command (经过在容器内运行命令来检查容器运行情况)
HEALTHCHECK NONE (禁用从基础映像继承的任何运行情况检查)
复制代码
可选的OPTION:
--interval=DURATION
(检测间隔,默认值:30s)--timeout=DURATION
(命令超时时间,默认值:30s)--start-period=DURATION
(初始化后开始检查时间,默认值:0s)--retries=N
(连续N次失败后标记为不健康,默认值:3次)Start Period为须要时间引导的容器提供初始化时间。在此期间的探测失败将不计入最大重试次数。可是,若是运行情况检查在开始期间成功,则容器将被视为已启动,而且全部连续失败将计入最大重试次数。
<command>
能够是shell脚本,也能够是exec格式的json数组。 docker以<command>
的退出状态码来区分容器是否健康,这一点同shell一致:
HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost/ || exit 1 复制代码
你可使用docker inspect
命令查看健康状态。
当容器的运行情况发生更改时,将生成带有新状态的health_status事件。
SHELL
更改后续的Dockerfile指令中所使用的shell。默认的shell是["bin/sh", "-c"]
。可屡次使用,每次都只改变后续指令。
SHELL ["executable", "parameters"] 复制代码