Dockerfile使用详解
一 Dockerfile介绍
Dockerfile是一种被Docker程序解释执行的脚本,由一条条的命令组成,每条命令对应linux下面的一条命令,Docker程序将这些Dockerfile指令在翻译成真正的linux命令,其有自己的书写方式和支持的命令,Docker程序读取Dockerfile并根据指令生成Docker镜像,相比手动制作镜像的方式,Dockerfile更能直观的展示镜像时怎么产生的,有了Dockerfile,当后期有额外的需求时,只要在之前的Dockerfile添加或者修改相应的命令即可重新生成新的docker镜像,避免了重复手动制作镜像。
Docker守护程序Dockerfile逐一运行指令。
二 Dockerfile制作流程
三 Dockerfile文件格式
3.1 Dockerfile文件说明
- 每一行以Dockerfile的指令开头,指令不区分大小写,但是惯例使用大写
- 使用#开始作为注释
- 每一行只支持一条指令,每条指令可以携带多个参数
- 指令按文件的顺序从上至下进行执行
- 每个指令的执行会生成一个新的镜像层,为了减少分层和镜像大小,仅可能将多条指令合并成一条指令
- 制作镜像一般可能需要反复多次,每次执行Dockerfile都按顺序执行,从头开始,已经执行过的指令已经缓存,不需要在执行,如果后续有一行新的执行没有执行过,其往后的执行将会重新执行,所以为加速镜像制作,将最常变化的内容放在Dockerfile的文件后面
3.2 Dockerfile相关指令
- FROM:就是指定基础镜像,此指令通常必须放在Dockerfile文件第一个非注释行,后续的指令都是运行于此基准镜像所提供的运行环境
- LABEL:指定镜像元数据,如镜像作者等
- MAINTAINER:指定维护者信息,此指令已过时,用LABEL替代
- RUN:用来在构建镜像阶段需要执行FROM指定镜像所支持的shell命令
- shell格式
- RUN <命令>
- exec格式
- RUN ["/bin/bash","-c","ls"]
- shell格式
- ENV:设置环境变量,会被后续指令通过$KEY或${KEY}进行引用,并在容器运行时保持
- COPY:复制本地宿主机的文件到容器内
- ADD:该命令可认为是增强版的COPY,不仅支持COPY,还支持自动伸缩。可以将复制指定的文件到容器内
- 可以是Dockerfile所在目录的一个相对路径,也可以是一个URL,还可以是一个tar文件会自动解压
- 可以是绝对路径或者是WORKDIR指定的相对路径
- 如果是目录,只复制目录中的内容,而非目录本身
- 如果是一个URL,下载后的文件权限自动设置为600
- 如果为URL且不以/结尾,则指定的文件将被下载并直接被创建,如果以/结尾,则文件名URL指定的文件将被直接下载并保存为/<filename>
- 如果是本地文件系统上的打包文件,如:gz,bz2,xz,它将被解压,但是通过URL获取到的tar文件将不会自动展开
- 如果有多个或其间接使用了通配符,则必须是一个以/结尾的目录路径,如果不以/结尾,则其被视作一个普通文件
- CMD:启动容器命令
- 如果docker run没有指定任何的执行命令或者Dockerfile里也没有ENTRYPOINT,那么启动容器时就会执行CMD指定的默认命令
- 每个Dockerfile只能有一条CMD命令。如果指定了多条,只有最后一条被执行
- 如果用户启动容器时用docker run 指定运行命令,则会覆盖CMD指定的命令
- ENTRYPOINT:功能类似于CMD,配置容器启动后执行的命令及参数
- ENTRYPOINT不能被docker run提供的参数覆盖,而是追加,即如果docker run命令有参数,那么参数全部都会作为ENTTRYPOINT的参数
- 如果docker run后面没有额外参数,但是Dockerfile中的CMD里有,即Dockerfile中即有CMD也有ENTRYPOINT,那么CMD全部内容作为ENTRYPOINT的参数
- 如果docker run后面有额外的参数,同时Dockerfile中既有CMD也有ENTRYPOINT,那么docker run后面的参数覆盖掉CMD参数内容,最终作为ENTRYPOINT的参数
- 可以通过docker run --entrypoint string参数在运行时替换注意string不要加空格
- 使用CMD要在运行时从新写命令本身,然后在后面才能追加运行参数,ENTRYPOINT则可以运行时无需重写命令就可以直接接收新参数
- 每个Dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个生效
- ARG:构建参数,在build阶段指定变量和ENV不同的是,容器运行时不会存在这些环境变量
- VOLUME:匿名卷
- 在容器创建一个可以从本地主机或其它容器挂载的挂载点,一般用来存放数据库和需要保持的数据等,一般会将宿主机上的目录挂载至VOLUME指令指定的容器目录,即时容器后期删除,此宿主机的目录仍会保留,从而实现容器数据的持久保持
- EXPOSE:暴露端口,指定服务端的容器需要对外暴露的端口号,以实现容器与外部通信
- WORKDIE:指定工作目录,为后续的RUN、CMD、ENTRYPOINT指定配置工作目录,当容器运行后,进入容器内WORKDIR指定的默认目录,当该目录不存在时会自动创建
- ONBUILD:子镜像引用父镜像的指令,可以用来配置当构建镜像的子镜像时,会自动触发执行的指令,但在当前镜像构建时,并不会执行,即延迟到子镜像构建时才执行
- USER:指定当前用户,指定运行容器的用户名或UID,后续的RUN也会指定用户,需要指定的用户名存在
- HEALTHCHECK:健康检查
- STOPSIGNAL:退出容器的信号
- SHELL:指定shell
3.3 .dockerignore文件
与.gitignore文件类似,生成构建上下文时docker客户端应忽略的文件和文件夹指定模式。
.dockerignore使用go的文件路径规则filepath.Match
- # #以#开头的行为注释
- * #匹配任何非分隔符字符序列
- ? #匹配任何单个非分隔符
- \\ #表示 \
- ** #匹配任意数量的目录,例如,**/**.go 将排除在所有目录中以.go结尾的所有文件
- ! #表示取反,可用于排除例外情况
四 docker build命令
4.1 docker build命令使用帮助
~# docker build -h
Flag shorthand -h has been deprecated, please use --help
Usage: docker build [OPTIONS] PATH | URL | -
Options:
--Add -host list #添加一个自定义主机到ip的映射(host:ip)
--build-arg list #设置构建时变量
--cache-from strings #图像作为缓存源
--cgroup-parent string #容器的可选父cgroup
--compress #使用gzip压缩构建上下文
--CPU -period int #限制CPU的CFS(完全公平调度)周期
--CPU -quota int #限制CPU CFS(完全公平调度)配额
-c,--CPU -shares int #CPU份额(相对权重)
--cpu -cpu string #允许执行的cpu (0-3, 0,1)
--cpuset-mems string #允许执行的MEMs (0- 3,0,1)
--disable-content-trust #跳过图像验证(默认为true)
-f,--file string # Dockerfile的名称(默认为'PATH/Dockerfile')
--force-rm #始终删除中间容器
--iidfile string #将图像ID写入文件
--isolation string #容器隔离技术
--label list #设置图像的元数据
-m,--内存字节#内存限制
--memory-swap bytes #交换限制等于内存加上交换:'-1'表示启用无限交换
--network string #在构建过程中设置RUN指令的网络模式(默认为“default”)
--no-cache #在构建映像时不要使用缓存
--pull #总是尝试拖动图像的新版本
-q,--quiet #在成功时禁止构建输出和打印映像ID
--rm #在成功构建后删除中间容器(默认为true)
--Security -opt strings #安全选项
--shm-size bytes # /dev/shm的大小
-t,--tag list #名称和一个可选的' Name:tag'格式的标签
--target string #设置目标构建阶段为构建。
--ulimit ulimit # ulimit选项(默认[])
4.2 使用示例
docker build . docker build -f /path/to/a/Dockerfile . docker build -t shykes/myapp . docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .