Dockerfile书写规则
官方建议指令越少越好,每一个指令都会创建一层,极占空间。
FROM
指定目前需要构建镜像的基础镜像
FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
# --platform 可选 用于指定构建的平台,默认不填为本机平台
# image 必填 镜像名 所有镜像默认继承scratch镜像
# tag 可选 镜像标签,默认为latest
# digest 可选 摘要,默认为latest
# AS 可选 别名,用于后续的镜像阶段构建
# FROM --platform=linux/amd64 mongo:4.3 AS db
RUN
两种写法,bash-like或者json-like
-
RUN <command>
shell-like写法,直接执行命令,在Linux中默认执行/bin/sh -c
,Windows中默认执行cmd /S /C
# 使用反斜杠换行书写
RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'
RUN ["executable", "param1", "param2"]
# 参数是json-like书写格式,需要使用双引号
# json-like写法不支持“$HELLO”的环境变量
RUN ["/bin/bash", "-c", "echo hello"]
CMD
与RUN命令区别在于,RUN命令直接执行并提交结果,CMD只是将命令存下来,等容器启动时才执行;与ENTRYPOINGT命令配合使用效果更佳
CMD ["executable","param1","param2"]
json-likeCMD ["param1","param2"]
作为ENTERYPOINT指令的默认参数CMD command param1 param2
shell-like
demo区分RUN和CMD
FROM alpine
RUN echo "hahaha run test"
CMD ["echo","hahahaha CMD"]
[root@seeter hu5ky]# docker build -t test:testruncommond .
Sending build context to Docker daemon 2.56kB
Step 1/3 : FROM alpine
---> cc0abc535e36
Step 2/3 : RUN echo "hahaha run test"
---> Running in b3d0cb324936
hahaha run test ----------> RUN命令直接执行
Removing intermediate container b3d0cb324936
---> e920fa254b3e
Step 3/3 : CMD ["echo","hahahaha CMD"]
---> Running in bd23af78c1e0 -----------> 不执行
Removing intermediate container bd23af78c1e0
---> 1ec19a656013
Successfully built 1ec19a656013
Successfully tagged test:testruncommond
---------------------------
[root@seeter hu5ky]# docker run test:testruncommond
hahahaha CMD ---------> docker run后才会执行
LABEL
用来设定docker镜像的metadata(镜像的描述数据类似位置,大小,作者等),以键值对的形式存在
LABEL <key>=<value> <key>=<value> <key>=<value> ...
------------
# 多标签写法
LABEL "auth"="hu5ky"
LABEL "time"="2020/04/27"
# 单标签单行写法
LABEL "auth"="hu5ky" "time"="2020/04/27"
# 单标签多行写法(个人推荐)
LABEL "auth"="hu5ky" \
"time"="2020/04/27"
demo
[root@firevision-aibuilding-test zc]# docker image inspect --format='{{.Config.Labels}}' test:testruncommond
map[auth:hu5ky time:2020/04/27]
MAINTAINER
MAINTAINER <name> <email>
镜像创建者 官方不推荐使用,可以使用
LABEL maintainer="SvenDowideit@home.org.au" eg.
EXPOSE
用于在运行时暴露容器端口并指定协议,未指定协议则默认为TCP
EXPOSE <port> [<port>/<protocol>...]
EXPOSE 80/tcp
EXPOSE 80/udp
EXPOSE
可以配合-P/-p命令使用:
-
-P
当使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。 -
-p
-p(小写)则可以指定要映射的IP和端口,但是在一个指定端口上只可以绑定一个容器。支持的格式有hostPort:containerPort
ip:hostPort:containerPort
ip::containerPort
。-p命令会直接忽略EXPOSE
中的端口.
ENV
k-v键值对,用于设定环境变量
-
ENV <key> <value>
# 一次设置一个 -
ENV <key>=<value> ...
# 一次设置多个
在docker run --env
时可以对Fockerfile的ENV
参数进行修改
ADD
将宿主机的文件或远程文件添加到容器内部
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
如果文件路径包含空格,使用这种方式。
demo
# 支持通配符写法
ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/
# --chown 可选 指定用户与组对应关系
# src 必填 宿主机文件或者url 如果为URL需要权限验证,啧需要第三方工具下载,ADD命令不支持验权
# dest 必填 docker内部路径
ADD
命令遵循以下规则
src
中的路径不可以是相对路径,错误写法:ADD ../something /something
。因为Dockerfile第一步就是将当前上下文以及子路径发送到docker daemon中。../
的写法不被支持。如果
src
是一个URL,且dest
最后不以斜杠/
结尾,则URL中文件被下载并拷贝到dest
中。-
如果
src
是一个URL,则docker自动将url最后的名称作为目标路径的文件名。# 正确用法 ADD http://example.com/foobar / # 最后会出现/foobar文件 # 错误写法 ADD http://example.com / # 无效
如果
src
是一个目录,则整个目录都会被拷贝,包括文件系统的metadata,但是文件夹不会被拷贝,只会拷贝其中的内容。如果
src
是一个压缩包,则会被解压到dest
中
COPY
同ADD
,只是src
不能为URL
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
ENTRYPOINT
ENTRYPOINT ["executable", "param1", "param2"]
json-likeENTRYPOINT command param1 param2
bash-like
与CMD
比较
-
docker run
指定command时,CMD
指令会被覆盖,而ENTRYPOINT
不会
demo
FROM ubuntu
CMD echo hahahahahahCMD
ENTRYPOINT ["echo", "hahahahha entrypoint"]
ENTRYPOINT echo hahahhhahahahENTRYPOINT
# ENTRYPOINT 不会被覆盖
[root@seeter hu5ky]# docker run test:test echo hahahahecho
hahahhhahahahENTRYPOINT
FROM ubuntu
CMD echo hahahahahahCMD
# CMD被command替换
[root@seeter hu5ky]# docker run test:test echo hahahahecho
hahahahecho
-
CMD
和ENTRYPOINT
同时使用时,CMD
将作为ENTRYPOINT
的参数。
demo
FROM ubuntu
CMD echo hahahahahahCMD
ENTRYPOINT ["echo", "hahahahha entrypoint"]
# CMD被视为ENTRYPOINT参数
[root@seeter hu5ky]# docker run test:test
hahahaha entrypoint echo hahahaha CMD
- 多个
ENTRYPOINT
同时使用时,最后一个ENTRYPOINT
生效。
demo
FROM ubuntu
CMD echo hahahahahahCMD
ENTRYPOINT ["echo", "hahahahha entrypoint"]
ENTRYPOINT echo hahahhhahahahENTRYPOINT
[root@seeter hu5ky]# docker run test:test
hahahhhahahahENTRYPOINT
VOLUME
VOLUME ["/data"]
VOLUME /data
作用仅仅是创建一个匿名挂载点,指定host存储时,需使用docker run -v
USER(待补充)
USER <user>[:<group>]
USER <UID>[:<GID>]
WORKDIR
为WORKDIR
后的所有命令指定运行目录
WORKDIR /path/to/workdir
demo
# 如果使用多次`WORKDIR`指令,且第一个是绝对路径,后面的是相对路径,则后续的所有路径就将追加在前一个路径中
FROM ubuntu
WORKDIR /app
WORKDIR hu5ky
RUN pwd
CMD echo hahahahahahCMD
VOLUME /home/hu5ky/volume/ /app/volume/
[root@seeter hu5ky]# docker build -t test:test .
Sending build context to Docker daemon 3.072kB
Step 1/6 : FROM ubuntu
---> 1d622ef86b13
Step 2/6 : WORKDIR /app
---> Running in 252cabc124c2
Removing intermediate container 252cabc124c2
---> 0577acce038d
Step 3/6 : WORKDIR hu5ky
---> Running in 83a45ee392c2
Removing intermediate container 83a45ee392c2
---> 8e3a8ccfd5b4
Step 4/6 : RUN pwd
---> Running in c66ebc01af08
/app/hu5ky ----------->完整路径
···
demo
# 可以结合环境变量使用
FROM ubuntu
ENV DIRPATH /app
WORKDIR $DIRPATH
WORKDIR hu5ky/$PPP
RUN pwd
[root@seeter hu5ky]# docker build -t test:test .
Sending build context to Docker daemon 3.072kB
Step 1/5 : FROM ubuntu
---> 1d622ef86b13
Step 2/5 : ENV DIRPATH /app
---> Using cache
---> 072a81455e5d
Step 3/5 : WORKDIR $DIRPATH
---> Running in 1c40421a9bb3
Removing intermediate container 1c40421a9bb3
---> 881bb05f37ce
Step 4/5 : WORKDIR hu5ky/$PPP
---> Running in 055cbeedebda
Removing intermediate container 055cbeedebda
---> 36b3343fa7cc
Step 5/5 : RUN pwd
---> Running in f4ee0bbb3182
/app/hu5ky ---------> 输出路径
Removing intermediate container f4ee0bbb3182
---> 8a6c3f753250
Successfully built 8a6c3f753250
Successfully tagged test:test
ARG
如果在FROM
前使用了ARG
,这个ARG
只能在FROM
中使用,在FROM
之后的指令中全都无效
-
ARG <name>[=<default value>]
缺省值会被--build-arg <varname>=<value>
替换
用户可以通过docker build
中的--build-arg <varname>=<value>
参数来指定,如果Dockerfile中没有指定ARG
参数,在build时会报出warning
demo
FROM ubuntu
ARG user
RUN echo $user
[root@firevision-kgm-test zhangc]# docker build --build-arg user=what_user .
Sending build context to Docker daemon 2.048kB
Step 1/3 : FROM ubuntu
---> 1d622ef86b13
Step 2/3 : ARG user
---> Running in 46f865af728e
Removing intermediate container 46f865af728e
---> 3742534d7867
Step 3/3 : RUN echo $user
---> Running in 5535d80b3b89
what_user. ------> 输出
Removing intermediate container 5535d80b3b89
---> 856eec9724e5
Successfully built 856eec9724e5
同时使用ARG
和ENV
指令,以ENV
的参数为准,一般来说ENV
的优先级高于ARG
demo
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER v1.0.0
RUN echo $CONT_IMG_VER
[root@seeter hu5ky]# docker build --build-arg CONT_IMG_VER=v2.0.1 .
Sending build context to Docker daemon 3.072kB
Step 1/4 : FROM ubuntu
---> 1d622ef86b13
Step 2/4 : ARG CONT_IMG_VER
---> Using cache
---> 993483f26804
Step 3/4 : ENV CONT_IMG_VER v1.0.0
---> Running in 2535a58ab1d4
Removing intermediate container 2535a58ab1d4
---> bc3012e82989
Step 4/4 : RUN echo $CONT_IMG_VER
---> Running in c55abb96daf7
v1.0.0. ---------> env指令的参数
Removing intermediate container c55abb96daf7
---> 114fc834f42d
Successfully built 114fc834f42d
结合ENV
和ARG
使用demo
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER ${CONT_IMG_VER:-v1.0.0}
RUN echo $CONT_IMG_VER
[root@seeter hu5ky]# docker build .
Sending build context to Docker daemon 3.072kB
Step 1/4 : FROM ubuntu
---> 1d622ef86b13
Step 2/4 : ARG CONT_IMG_VER
---> Running in 2ccf8e734837
Removing intermediate container 2ccf8e734837
---> af95bb2aeb4b
Step 3/4 : ENV CONT_IMG_VER ${CONT_IMG_VER:-v1.0.0}
---> Running in 3bf09240355e
Removing intermediate container 3bf09240355e
---> d845d51f801f
Step 4/4 : RUN echo $CONT_IMG_VER
---> Running in 8b34d0bd089b
v1.0.0
Removing intermediate container 8b34d0bd089b
---> e00f86d7c62a
Successfully built e00f86d7c62a
ARG
指令有一组预定义的参数,不需要在Dockerfile中指定
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy
直接在--build-arg <varname>=<value>
中指定即可
ONBUILD(待补充)
ONBUILD <INSTRUCTION>
STOPSIGNAL(待补充)
STOPSIGNAL signal
HEALTHCHECK
用来告诉Docker怎么去检查容器的运行情况,甚至可以检测出一个运行的容器中存在的死循环和无法创建新链接的情况
HEALTHCHECK [OPTIONS] CMD command
HEALTHCHECK NONE
当指定了运行状况检查的容器时,除了其正常状态外,它还具有运行状况。此状态最初为starting。只要运行状况检查通过,它将变为healthy(以前处于任何状态)。在一定数量的连续失败之后,它变为unhealthy.
--interval=DURATION
(默认 30s)--timeout=DURATION
(默认 30s)--start-period=DURATION
(默认 0s)--retries=N
(默认 3)
运行状况检查将首先在容器启动后的间隔秒数--interval
内运行,然后在之前每次检查完成后的间隔秒数内运行。
如果单次检查花费的时间超过超时--timeout
秒数,则认为检查失败。
连续多次重试--retries
失败后,才可以将某一容器的状态判断为unhealthy。
开始时间段--start-period
为需要时间进行 bootstrap 的容器提供了初始化时间。在此期间内的探针故障将不计入最大重试次数--retries
。但是,如果运行状况检查在启动期间成功,则认为该容器已启动,并且所有连续失败将计入最大重试次数--retries
。
Dockerfile文件中只允许出现一次HEALTHCHECK
,多个该指令最后一个生效。
HEALTHCHECK
后面可以跟CMD
指令,例如:HEALTHCHECK CMD /bin/check-running
,此CMD
命令和Dockerfile中的一样,shell-like和json-like。
- 0: success - 可用
- 1: unhealthy - 有问题
- 2: reserved - 保留字段,官方不让使用这个
每5m检查一次,3s超时则为失败
demo
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1
SHELL(待补充)
-
SHELL ["executable", "parameters"]
必须为json-like