文章目录
- 一、Dockerfile介绍
- 二、Dockerfile镜像制作和流程使用
- 三、Dockerfile文件的制作镜像的分层结构
- 四、Dockerfile文件格式
- 五、Dockerfile相关指令
-
- [5.1 FROML:指定基础镜像](#5.1 FROML:指定基础镜像)
- [5.2 LABEL:指定镜像元数据](#5.2 LABEL:指定镜像元数据)
- [5.3 RUN:执行shell指令](#5.3 RUN:执行shell指令)
- [5.4 ENV:设置环境变量](#5.4 ENV:设置环境变量)
- [5.5 COPY:复制文本](#5.5 COPY:复制文本)
- [5.6 ADD:复制和解包文件](#5.6 ADD:复制和解包文件)
- [5.7 CMD启动容器命令](#5.7 CMD启动容器命令)
- [5.8 ENTRYPOINT:入口点](#5.8 ENTRYPOINT:入口点)
- [5.9 ARG:构建参数](#5.9 ARG:构建参数)
- [5.10 VOLUME:匿名卷](#5.10 VOLUME:匿名卷)
- [5.11 EXPOSE:暴露端口](#5.11 EXPOSE:暴露端口)
- [5.12 WORKDIR:指定工作目录](#5.12 WORKDIR:指定工作目录)
- [5.13 ONBUILD:子镜像引用父镜像的指令](#5.13 ONBUILD:子镜像引用父镜像的指令)
- [5.14 USER:指定当前用户](#5.14 USER:指定当前用户)
- [5.15 HEALTHCHECK:健康检查](#5.15 HEALTHCHECK:健康检查)
- [5.16 STOPSIGNAL:退出容器的信号](#5.16 STOPSIGNAL:退出容器的信号)
- [5.17 SHELL:指定shell](#5.17 SHELL:指定shell)
- [5.18 .dokcerignore文件](#5.18 .dokcerignore文件)
- [5.19 Dockerfile构建过程和指令总结](#5.19 Dockerfile构建过程和指令总结)
- [六、构建镜像的docker build命令](#六、构建镜像的docker build命令)
一、Dockerfile介绍
DockerFile是一种被Docker程序解释执行的脚本,由一条条的命令组成的,每条命令对应linux下面的一条命令,Docker程序将这些DockerFile指令再翻译成真正的linux命令,其有自己的书写方式和支持的命令,Docker程序读取DockerFile并根据指令生成Docker镜像,相比手动制作镜像的方式,DockerFile更能直观的展示镜像是怎么产生的,有了DockerFile,当后期有额外的需求时,只要在之前的DockerFile添加或者修改响应的命令即可重新生成新的Docker镜像,避免了重复手动制作镜像的麻烦,类似于shell脚本一样,可以方便高效的制作镜像
二、Dockerfile镜像制作和流程使用

三、Dockerfile文件的制作镜像的分层结构

例:按照业务类型或系统类型等方式划分创建目录环境,方便后期镜像比较多的时候进行分类
Shell
[root@node4 ~]# mkdir -p /data/dockerfile/{web/{nginx,tomcat,jdk},system/{centos,ubuntu,apline,debian}}
[root@node4 ~]# tree /data/dockerfile/
/data/dockerfile/
├── system
│ ├── apline
│ ├── centos
│ ├── debian
│ └── ubuntu
└── web
├── jdk
├── nginx
└── tomcat
9 directories, 0 files
四、Dockerfile文件格式
dockerfile官方说明:https://docs.docker.com/engine/reference/builder/
帮助:man 5 dockerfile
DockerFile文件说明
-
每一行以Dockerfile的指令开头,指令不区分大小写,但是惯例使用大写
-
使用#开始作为注释
-
每一行只支持一条指令,每条指令可以携带多个参数
-
指令按文件的顺序从至下进行执行
-
每个指令的执行会生成一个新的镜像层,为了减少分层和镜像大小,尽可能将多条指令合并成一条指令
-
制镜像一般可能需要反复多次,每次执行dockfile都按顺序执行,从头开始,已经执行过的指令已经缓存,不需要再执行,如果后续有一行新的指令没执行过,其往后的指令将会重新执行,所以为加速镜像制作,将最常变化的内容放下dockerfile的文件的后面
五、Dockerfile相关指令
dockerfile文件中的常见指令
Shell
ADD
COPY
ENV
EXPOSE
FROM
LABEL
STOPSIGNAL
USER
VOLUME
WORKDIR
5.1 FROML:指定基础镜像
FROM就是指定基础镜像,此指令通常必需放在Dockerfile文件第一个非注释行。后续的指令都是运行于此基准镜像所提供的运行环境
例:
Shell
FROM [--platform=<platform>]<image>[AS <name>]
FROM [--platform=<platform>]<image>[:<tag>][AS <name>]
FROM [--platform=<platform>]<image>[@<digest>][AS <name>]
#说明:
--platform指定镜像的平台,比如:linux/amd64,linux/arm64,or windows/amd64 tag和digest是可选项,如果不指定,默认为latest
FROM scratch #所有镜像的起源镜像,相当于object类
FROM ubuntu
FROM ubuntu:bionic
FROM debian:buster-slim
5.2 LABEL:指定镜像元数据
可以指定镜像元数据,如:镜像作者等
Shell
LABEL <key>=<value> <key>=<value> <key>=<value> ...
例:
Shell
LABEL version="1.0"
LABEL description="This text illustrates"
一个镜像可以有多个label,还可以写在一行中,即多标签写法,可以减少镜像的的大小
例:
Shell
#一行格式
LABEL multi.label1="value1" multi.label2="value2" other="value3'
#多行格式
LABEL multi.label1="value1"\
multi.label2="value2"\
other="value3"
MAINTAINER:指令维护者信息,此指令已过时,用LABEL代替
5.3 RUN:执行shell指令
RUN指令用来在构建镜像阶段需要执行FROM指定镜像所支持的Shll命令。
注:RUN可以写多个,每一个RUN指令都会建立一个镜像层,所以尽可能合并成一条指令,比如将多个shell命令通过&&连接一起成为在一条指令
每个RUN都是独立运行的和前一个RUN无关
Shell
#shell格式:相当于/bin/sh-c <命令> 此种形式支持环境变量
RUN <命令>
#exec格式:此种形式不支持环境变量,注意:是双引号,不能是单引号
RUN["可执行文件","参数1","参数2"]
#exec格式可以指定其它shell
RUN ["/bin/bash","-c","echo hello wang"]
5.4 ENV:设置环境变量
ENV可以定义环境变量和值,会被后指铃如:ENV,ADD,COPY,RUN等通过 K E Y 或 KEY或 KEY或{KEY}进行引用,并在容器运行时保持
Shell
#变量赋值格式1
ENV <key> <value> #此格式只能对一个key赋值,<key>之后的所有内容均会被视作其<value>的组成部分
#变量赋值格式2
ENV <key1>=<value1> <key2>=<value2> \ #此格式可以支持多个key赋值,定义多个变量建议使用,减少镜像层
<key3>=<value3> ...
#如果<value>中包含空格,可以以反斜线 \ 进行转义,也可通过对<value>加引号进行标识;另外,反斜线也可用于续行
#只使用一次变量
RUN <key>=<value> <command>
#引用变量
RUN $key ......
#变量支持高级赋值格式
${key:-word}
$[kye:+word}
如果运行容器时如果需要修改变量,可以执行下面通过基于exec机制实现
注意:下面方式只影响容器运行时环境,而不影响构建镜像的过程,即只能覆盖docker run时的环境变量,而不会影响docker build时环境变量的值
Shell
docker run -e|--env <key>=<value>
#说明
-e,--env list #Set environment variables
--env-file filename #Read in a file of environment variables
5.5 COPY:复制文本
复制本地宿主机的内容到容器中
Shell
COPY [--chown=<user>:<group>] <src>...<dest>
COPY [--chowm-<user>:<group>] ["<src>",..."<dest>"]#路径中有空白字符时,建议使用此格式
说明:
-
·以是多个,可以使用通配符,通配符规则满足Go的filepath.Match规则filepath.Match参考链接https://go1ang.org/pkg/path/filepath/#Match
-
必须是build上下文中的路径(为Dockerfile所在目录的相对路径),不能是其父目录中的文件
-
如果是目录,则其内部文件或子目录会被递归复制,但目录自身不会被复制
-
如果指定了多个,或在其中使用了通配符,则必须是一个目录,且必须以/结尾
-
可以是绝对路径或者是WORKDIR指定的相对路径
-
使用COPY指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等
-
如果事先不存在,它将会被自动创建,这包括其父目录路径即递归创建目录
5.6 ADD:复制和解包文件
该命令可认为是增强版的COPY,不仅支持COPY,还支持自动解缩。可以将复制指定的到容器中
Shell
ADD [--chown=<user>:<group>] <src>...<dest>
ADD [--chowm-<user>:<group>] ["<src>",..."<dest>"]#路径中有空白字符时,建议使用此格式
说明:
-
可以是Dockerfile所在目录的一个相对路径;也可是一个URL;还可是一个tar文件(自动解压)
-
可以是绝对路径或者是WORKDIR指定的相对路径
-
如果是目录,只复制目录中的内容,而非目录本身
-
如果是一个URL,下载后的文件权限自动设置为600
-
如果为URL且不以/结尾,则指定的文件将被下载并直接被创建,如果以/结尾,则文件名URL指定的文件将被直接下载并保存为/
-
如果是一个本地文件系统上的打包文件如:g2,bz2,xz,它将被解包,其行为类以于"tar -x"命令,但是通过URL获取到的tar文件将不会自动展开(注:zip后缀的包不会被解压)
-
如果有多个,或其间接或直接使用了通配符,则必须是一个以/结尾的目录路径,如果不以/结尾,则其被视作一个普通文件。
5.7 CMD启动容器命令
一个容器中需要持续运行的进程一般只有一个,CMD用来指定启动容器时默认执行的一个命令,且其运行结束后,容器也会停止,所以一般CMD指定的命令为持续运行且为前台命令。
-
每个Dockerfile只能有一条CMD命令。如果指定了多条,只有最后一条被执行
-
如果用户启动容器时用docker run xxx指定运行的命令,则会覆盖CMD指定的命令
Shell
#使用exec执行,推荐方式,第一个参数必须是命令的全路径,此种形式不支持环境变量
CMD ["executable","paraml","param2"]
#在/bin/sh中执行,提供给需要交互的应用;此种形式支持环境变量
CMD command paraml param2
#提供给ENTRYPOINT命令的默认参数
CMD ["param1","param2"]
例:
Shell
CMD ["nginx","-g","daemon off;"]
5.8 ENTRYPOINT:入口点
功能类似于CMD,配置容器启动后执行的命令及参数
Shell
#使用exec执行
ENTRYPOINT ["executable","param1","param2"]
#shell中执行
ENTRYPOINT command param1 param2
-
ENTRYPOINT不能被docker run提供的参数覆盖,而是追加,即如果docker run命令有参数,那么参数全部都会作为ENTRYPOINT的参数
-
如果docker run后面没有额外参数,但是dockerfile中的CMD里有(即上面CMD的第三种用法),即Dockerfile中有CMD也有ENTRYPOINT,那么CMD的全部内容会作为ENTRYPOINTE的参数
-
如果docker run后面有额外参数,同时Dockerfile中即有CMD也有ENTRYPOINT,那么docker run后面的参数覆盖掉CMD参数内容最终作为ENTRYPOINT的参数
-
可以通过docker run --entrypoint string参数在运行时替换,注意string不要加空格
-
使用CMD要在运行时重新写命令本身,然后在后面才能追加运行参数,ENTRYPOINT则可以运行时无需重写命令就可以直接接受新参数
-
每个Dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个生效
5.9 ARG:构建参数
ARG指令在build阶段指定变量,和ENV不同的是,容器运行时不会存在这些环境变量
Shell
ARG <name>[=<default value>]
如果和ENV同名,ENV覆盖ARG变量
可以用docker build-build-arg<参数名>=<值> 来覆盖
说明:ARG和FROM
Shell
#FROM指令支持由第一个FROM之前的任何ARG指令声明的变量
#例
ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app
#在FROM之前声明的ARG在构建阶段之外,所以它不能在FROM之后的迁何指令中使用。要使用在第一个FROM之前声明的ARG的默认值,请在构建阶段内使用没有值的ARG指令
#例:
ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version
5.10 VOLUME:匿名卷
在容器中创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等,一般会将宿主机中的目录挂载至VOLUME指令指定的容器目录。即使容器后期被删除,此宿主机的目录仍会保留,从而实现容器数据的持久保存。
Shell
VOLUME <容器内路径>
VOLUME ["<容器内路径1>","<容器内路径2>"...]
注意
-
Dockerfile中的VOLUME实现的是匿名数据卷无法指定宿主机路径和容器目录的挂载关系
-
通过docker rm -fv <容器ID>删除容器的同时,也会删除VOLUME指定的卷
5.11 EXPOSE:暴露端口
指定服务端的容器需要对外暴露监听的端口号,以实现容器与外部通信。
EXPOSE仅仅是声明容器打算使用什么端口而已,并不会真正暴露端口,即不会自动在宿主机进行端口映射。
因此,在启动容器时需要通过-P或-p,Docker主机才会真正分配一个端口转发到指定暴露的端口才可使用
注意:即使Dockerfile没有EXPOSE端口指令,也可以通过docker run -p临时暴露容器内程序真正监听的端口,所以EXPOSE相当于指定默认的暴露端口,可通过docker run -P进行真正暴露
Shell
EXPOSE <port>[/ <protocol>][<port>[/ <protocol> ..]
#说明
<protocol>用于指定传输层协议,可为tCp或udp二者之一,默认为TCP协议
5.12 WORKDIR:指定工作目录
为后续的RUN、CMD、ENTRYPOINT指令配置工作目录,当容器运行后,进入容器内WORKDIR指定的默认目录
WORKDIR指定工作目录(或称当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR会自行创建
可以使用多个ORKDIR指铃,后续命令如果参数是相对路径,则会基于之前命令指定的路径
例:
Shell
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
结果为/a/b/c
5.13 ONBUILD:子镜像引用父镜像的指令
可以用来配置当构建当前镜像的子镜像时,会自动触发执行的指令,但在当前镜像构建时,并不会执行,即延迟到子镜像构建时才执行
Shell
ONBUILD [INSTRUCTION]
如果基于image-A创建新的镜像image-B时,新的Dockerfile中使用FROM image-A指定基础镜像时,会自动执行ONBUILD指令内容,等阶于在后面添动加了两条指令。
说明:
-
尽管任何指令都可注册成为触发器指令,但ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令
-
使用ONBUILD指令的镜像,推荐在标签中注明,例收如ruby:1.9-onbui1d
5.14 USER:指定当前用户
指定运行容器时的用户名或UID,后续的RUN也会使用指定用户
当服务不需要管理员权限时,可以通过该命令指定运行用户
这个用户必须是事先建立好的,否则无法切换
如果没有指定USER,默认是root身份执行
Shell
USER <user>[:<group>]
USER <UID>[:<GID>]
5.15 HEALTHCHECK:健康检查
检查容器的健康性
Shell
HEALTHCHECK [选项] CMD <命令> #设置检查容器健康状况的命令
HEALTHCHECK NONE #如果基础镜像有健康检查指令,使用这行可以屏薇掉其健康检查指令
HEALTHCHECK支持下列选项:
--interval=<间隔> #两次健康检查的间隔,默认为30秒
--timeout=<时长> #健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认30秒
--retries=<次数> #当连续失败指定次数后,则将容器状态视为unhealthy,默认3次
--start-period=<FDURATION> #default:0s
#检查结果返回值:
0 #success the container is healthy and ready for use
1 #unhealth the container is not working correctly
2 #reserved do not use this exit code
例:
Shell
FROM nginx
RUN apt-get update & apt-get install -y curl &8 rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s
CMD curl -fs http://localhost/ || exit 1
5.16 STOPSIGNAL:退出容器的信号
该STOPSIGNAL指令设置将被发送到容器退出的系统调用信号。该信号可以是与内核syscall表中的位置匹配的有效无符号数字(例如9),也可以是SIGNAME格式的信号名称(例如SIGKILL)
5.17 SHELL:指定shell
SHELL指令允许覆盖用于命令的shell形式的默认SHELL,必须在Dockerfile中以JSON形式编写SHELL指令。
5.18 .dokcerignore文件
官方文档:https://docs.docker.com/engine/reference/builder/#dockerignore-file,与.gitignore文件类似,生成构建上下文时Docker客户端应忽略的文件和文件夹指定模式
dockerignore使用Go的文件路径规则filepath.Match
参考链接:https://golang.org/pkg/path/filepath/#Match
完整的语法
Shell
# #以#开头的行为注释
* #匹配任何非分隔符字符序列
? #匹配任何单个非分隔符
N #表示\
** #匹配任意数量的目录(包括零)例如,**/*.go将排除在所有目录中以.go结尾的所有文件,包括构建上下文的根。
! #表示取反,可用于排除例外情况

5.19 Dockerfile构建过程和指令总结
Dockerfile构建过程
-
从基础镜像运行一个容器
-
执行一条指令,对容器做出修改
-
执行类似docker commit的操作,提交一个新的中间镜像层(可以利用中间层镜像创建容器进行调试和排错)
-
再基于刚提交的镜像运行一个新容器
-
执行Dockerfile中的下一条指令,直至所有指令执行完毕
六、构建镜像的docker build命令
docker build命令使用Dockerfile文件创建镜像
Shell
[root@node4 ~]# docker build --help
Usage: docker build [OPTIONS] PATH | URL | -
说明:
PATH | URL | - #可以使是本地路径,也可以是URL路径。若设置为-,则从标准输入获取Dockerfi1e的内容
-f,--file string #Dockerfile.文件名,默认为PATH/Dockerfile
--force-rm #总是删除中间层容器,创建镜像失败时,删除临时容器
--no-cache #不使用之前构建中创建的缓存
-q --quiet=false #不显示Dockerfile的RUN运行的输出结果
--rm=true #创建镜像成功时,删除临时容器
-t --tag list #设置注册名称、镜像名称、标签。格式为<注册名称>/<镜像名称>:<标签>(标签默认为latest)
Build an image from a Dockerfile
Options:
--add-host list Add a custom host-to-IP mapping (host:ip)
--build-arg list Set build-time variables
--cache-from strings Images to consider as cache sources
--cgroup-parent string Optional parent cgroup for the container
--compress Compress the build context using gzip
--cpu-period int Limit the CPU CFS (Completely Fair Scheduler) period
--cpu-quota int Limit the CPU CFS (Completely Fair Scheduler) quota
-c, --cpu-shares int CPU shares (relative weight)
--cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems string MEMs in which to allow execution (0-3, 0,1)
--disable-content-trust Skip image verification (default true)
-f, --file string Name of the Dockerfile (Default is 'PATH/Dockerfile')
--force-rm Always remove intermediate containers
--iidfile string Write the image ID to the file
--isolation string Container isolation technology
--label list Set metadata for an image
-m, --memory bytes Memory limit
--memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap
--network string Set the networking mode for the RUN instructions during build (default "default")
--no-cache Do not use cache when building the image
--pull Always attempt to pull a newer version of the image
-q, --quiet Suppress the build output and print image ID on success
--rm Remove intermediate containers after a successful build (default true)
--security-opt strings Security options
--shm-size bytes Size of /dev/shm
-t, --tag list Name and optionally a tag in the 'name:tag' format
--target string Set the target build stage to build.
--ulimit ulimit Ulimit options (default [])
查看镜像的构建历史:docker history 镜像ID
不利用缓存重新构建镜像:docker build --no-cache -t ...