镜像构建Dockerfile的介绍

一、概述
dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
官方文档:
https://docs.docker.com/engine/reference/builder/
dockerfile 示例:
https://github.com/dockerfile/
二、dockerfile 结构
dockerfile 结构主要分为四部分:
基础镜像信息
维护者信息
镜像操作指令
容器启动时执行指令 (cmd/entrypoint)
【温馨提示】dockerfile 每行支持一条指令,每条指令可携带多个参数(支持&&),支持使用以“#“号开头的注释(jason 文件不支持#注释),但是也非必须满足上面的四点。
三、常用 dockerfile 操作指令
arg—— 定义创建镜像过程中使用的变量 ,唯一一个可以在 from 之前定义 。
from——基于某个镜像, from前面只能有一个或多个arg指令 。
maintainer(已弃用) —— 镜像维护者姓名或邮箱地址 。
volume —— 指定容器挂载点到宿主机自动生成的目录或其他容器
run——执行镜像里的命令,跟在 liunx 执行命令一样,只需要在前面加上 run 关键词就行。
copy——复制本地(宿主机)上的文件到镜像。
add——复制并解压(宿主机)上的压缩文件到镜像。
env——设置环境变量。
workdir —— 为 run、cmd、entrypoint、copy 和 add 设置工作目录,就是切换目录 。
user —— 为 run、cmd、和 entrypoint 执行命令指定运行用户。
expose —— 声明容器的服务端口(仅仅是声明) 。
cmd—— 容器启动后执行的命令 ,多个 cmd 只会执行最后一个,跟 entrypoint 的区别是,cmd 可以作为 entrypoint 的参数,且会被 yaml 文件里的 command 覆盖。
entrypoint—— 容器启动后执行的命令 ,多个只会执行最后一个。
healthchech —— 健康检查 。
onbuild——它后面跟的是其它指令,比如 run, copy 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。
label——label 指令用来给镜像添加一些元数据(metadata),以键值对的形式 ,替换 maintainer。
1)镜像构建(docker build)
docker build -t text:v1 . --no-cache# 要在构建后将映像标记到多个存储库中,请在运行命令-t时添加多个参数docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .### 参数解释# -t:指定镜像名称# . :当前目录dockerfile# -f:指定dockerfile路径#  --no-cache:不缓存  
2)运行容器测试(docker run)
# 非交互式运行docker run centos:7.4.1708 /bin/echo hello world### 交互式执行# -t: 在新容器内指定一个伪终端或终端。#-i: 允许你对容器内的标准输入 (stdin) 进行交互。# 会登录到docker环境中,交互式docker run -it centos:7.4.1708 /bin/bash# -d:后台执行,加了 -d 参数默认不会进入容器docker run -itd centos:7.4.1708 /bin/bash### 进入容器# 在使用 -d 参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入:#docker exec -it :推荐大家使用 docker exec -it 命令,因为此命令会退出容器终端,但不会导致容器的停止。#docker attach:容器退出,会导致容器的停止。docker exec -it  b2c0235dc53 /bin/bashdocker attach  b2c0235dc53  
3)arg
构建参数,与 env 作用一致。不过作用域不一样。arg 设置的环境变量仅对 dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。唯一一个可以在 from 之前定义 。构建命令 docker build 中可以用 --build-arg = 来覆盖。
语法格式:
arg [=]  
示例:
# 在from之前定义arg,只在 from 中生效arg version=lasterfrom centos:${version}# 在from之后使用,得重新定义,不需要赋值arg versionrun echo $version >/tmp/image_version  
4)from
定制的镜像都是基于 from 的镜像 ,【必选项】
语法格式:
from [--platform=]  [as ]from [--platform=] [:] [as ]from [--platform=] [@] [as ]  
如果引用多平台图像,可选--platform标志可用于指定图像的平台。from例如,linux/amd64、 linux/arm64或windows/amd64。默认情况下,使用构建请求的目标平台。全局构建参数可用于此标志的值,例如允许您将阶段强制为原生构建平台 ( --platform=$buildplatform),并使用它交叉编译到阶段内的目标平台。
示例:
arg version=latestfrom busybox:$version# from --platform=linux/amd64 busybox:$versionarg versionrun echo $version > image_version  
5)maintainer(已弃用)
镜像维护者信息
语法格式:
maintainer   
示例:
label org.opencontainers.image.authors=svendowideit@home.org.au  
6)volume
定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
作用:
避免重要的数据,因容器重启而丢失,这是非常致命的。
避免容器不断变大。
在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。
语法格式:
# 后面路径是容器内的路径,对应宿主机的目录是随机的volume [, ...]volume   
示例:
from ubunturun mkdir /myvolrun echo hello world > /myvol/greetingvolume /myvol  
7)run
用于执行后面跟着的命令行命令。
语法格式:
run (shell形式,命令在 shell 中运行,默认/bin/sh -c在 linux 或cmd /s /cwindows 上)
run [executable, param1, param2](执行形式)
示例:
# 以下三种写法等价run /bin/bash -c 'source $home/.bashrc; echo $home'run /bin/bash -c 'source $home/.bashrc; echo $home'run [/bin/bash, -c, source $home/.bashrc; echo $home]  
8)copy
拷贝(宿主机)文件或目录到容器中,跟 add 类似,但不具备自动下载或解压的功能 。所有新文件和目录都使用 0 的 uid 和 gid 创建,除非可选--chown标志指定给定的用户名、组名或 uid/gid 组合以请求复制内容的特定所有权。
语法格式:
copy [--chown=:] ... copy [--chown=:] [,... ]  
示例:
# 添加所有以“hom”开头的文件:copy hom* /mydir/# ?替换为任何单个字符,例如“home.txt”。copy hom?.txt /mydir/# 使用相对路径,并将“test.txt”添加到/relativedir/:copy test.txt relativedir/# 使用绝对路径,并将“test.txt”添加到/absolutedir/copy test.txt /absolutedir/# 修改文件权限copy --chown=55:mygroup files* /somedir/copy --chown=bin files* /somedir/copy --chown=1 files* /somedir/copy --chown=10:11 files* /somedir/  
9)add
拷贝文件或目录到容器中,如果是 url 或压缩包便会自动下载或自动解压 。
add 指令和 copy 的使用格类似(同样需求下,官方推荐使用 copy)。功能也类似,不同之处如下:
add 的优点:在执行 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 。
add 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
语法格式:
add [--chown=:] ... add [--chown=:] [,... ]  
示例:
# 通配符add hom* /mydir/# 相对路径,拷贝到workdir目录下relativedir/add test.txt relativedir/# 绝对路径add test.txt /absolutedir/# 更改权限add --chown=55:mygroup files* /somedir/add --chown=bin files* /somedir/add --chown=1 files* /somedir/add --chown=10:11 files* /somedir/  
add 和 copy 的区别和使用场景:
add 支持添加远程 url 和自动提取压缩格式的文件,copy 只允许从本机中复制文件
copy 支持从其他构建阶段中复制源文件(--from)
根据官方 dockerfile 最佳实践,除非真的需要从远程 url 添加文件或自动提取压缩文件才用 add,其他情况一律使用 copy
10)env
设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
语法格式:
env = =...# 省略=此语法不允许在单个env指令中设置多个环境变量,并且可能会造成混淆。env    
示例:
env java_home=/usr/local/jdkenv my_name=john doe my_dog=rex the dog     my_cat=fluffy# 此语法不允许在单个env指令中设置多个环境变量,并且可能会造成混淆。env java_home /usr/local/jdk  
11)workdir
指定工作目录。用 workdir 指定的工作目录,会在构建镜像的每一层中都存在。(workdir 指定的工作目录,必须是提前创建好的)。
语法格式:
workdir   
示例:
from busyboxenv foo=/barworkdir ${foo}   # workdir /bar  
12)user
用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。
语法格式:
user [:]user [:]  
示例:
from busyboxrun groupadd --system --gid=9999 admin && useradd --system --home-dir /home/admin --uid=9999 --gid=admin adminuser admin:admin# user 9999:9999  
13)expose
暴露端口 ,仅仅只是声明端口。
作用:
帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
在运行时使用随机端口映射时,也就是 docker run -p 时,会自动随机映射 expose 的端口。
语法格式:
# 默认情况下,expose假定 tcp。expose  [/...]  
示例:
expose 80/tcp 443/tcpexpose 80 443expose 80/tcpexpose 80/udp  
14)cmd
类似于 run 指令,用于运行程序,但二者运行的时间点不同:cmd 在构建镜像时不会执行,在容器运行 时运行。
语法格式:
cmd cmd [,,,...]cmd [,,...]  # 该写法是为 entrypoint 指令指定的程序提供默认参数  
推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。
示例:
cmd cat /etc/profilecmd [/bin/sh,-c,/etc/profile]  
注意:如果 dockerfile 中如果存在多个 cmd 指令,仅最后一个生效。
15)entrypoint
类似于 cmd 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 entrypoint 指令指定的程序。但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 entrypoint 指令指定的程序。在 k8s 中 command 也会覆盖 entrypoint 指令指定的程序
语法格式:
# exec形式,这是首选形式:entrypoint [executable, param1, param2]# 外壳形式:entrypoint command param1 param2  
示例:
from ubuntuentrypoint [top, -b]# cmd作为entrypoint参数cmd [-c]# 与下面的等价entrypoint [top, -b -c]entrypoint  top -b -c  
注意:如果 dockerfile 中如果存在多个 entrypoint 指令,仅最后一个生效。
16)healthcheck
用于指定某个程序或者指令来监控 docker 容器服务的运行状态。
语法格式:
healthcheck [options] cmd command(通过在容器内运行命令检查容器运行状况)healthcheck none(禁用从基础映像继承的任何运行状况检查)  
选项cmd有:
--interval=duration(默认30s:):间隔,频率
--timeout=duration(默认30s:):超时时间
--start-period=duration(默认0s:):为需要时间引导的容器提供初始化时间, 在此期间探测失败将不计入最大重试次数。
--retries=n(默认3:):重试次数
命令的exit status指示容器的运行状况。可能的值为:
0:健康状态,容器健康且已准备完成。
1:不健康状态,容器工作不正常。
2:保留,不要使用此退出代码。
示例:
from nginxmaintainer securitithealthcheck --interval=5s --timeout=3s   cmd curl -f http://localhost/ || exit 1cmd [usr/sbin/nginx, -g, daemon off;]  
17)onbuild
onbuild 是一个特殊的指令,它后面跟的是其它指令,比如 run, copy 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。
语法格式:
onbuild   
示例:
from node:slimrun mkdir /appworkdir /apponbuild copy ./package.json /apponbuild run [ npm, install ]onbuild copy . /app/cmd [ npm, start ]  
18)label
label 指令用来给镜像添加一些元数据(metadata),以键值对的形式。用来替代 maintainer。
语法格式:
label = = = ...  
示例:比如我们可以添加镜像的作者
label org.opencontainers.image.authors=runoob  
四、arg 和 env 的区别
arg 定义的变量只会存在于镜像构建过程,启动容器后并不保留这些变量
env 定义的变量在启动容器后仍然保留
五、cmd,entrypoint,command,args 场景测试
当用户同时在 kubernetes 中的 yaml 文件中写了command和args的时候,默认是会覆盖dockerfile中的命令行和参数,完整的情况分类如下:
1)command 和 args 不存在场景测试
如果 command 和 args 都没有写,那么用dockerfile默认的配置。
dockerfile
from centoscopy test.sh /run chmod +x /test.sh### entrypoint将作为的子命令启动/bin/sh -c,它不会传递参数,要传递参数只能这样传参# entrypoint [/bin/sh,-c,/test.sh entrypoint]entrypoint [/test.sh,entrypoint]cmd [cmd]  
/tmp/test.sh
#!/bin/bashecho $*  
构建
docker build -t test1:v1 -f dockerfile .  
yaml 编排
cat < test1.yamlapiversion: apps/v1kind: deploymentmetadata:  name: testspec:  replicas: 1  selector:    matchlabels:      app: test  template:    metadata:      labels:        app: test    spec:      nodename: local-168-182-110      containers:      - name: test        image: test:v1        #command: ['/bin/sh','-c','/test.sh']        #args: ['args']eof  
执行
kubectl apply -f test.yaml  
2)command 存在,但 args 存在场景测试
如果 command 写了,但 args 没有写,那么 docker 默认的配置会被忽略而且仅仅执行.yaml文件的 command(不带任何参数的)。
cat < test2.yamlapiversion: apps/v1kind: deploymentmetadata:  name: test2spec:  replicas: 1  selector:    matchlabels:      app: test2  template:    metadata:      labels:        app: test2    spec:      nodename: local-168-182-110      containers:      - name: test2        image: test:v1        # ['/bin/sh','-c','/test.sh command','hello'],加了'/bin/sh','-c',也是不能外部传参,不会输出hello,只能通过这样传参,['/bin/sh','-c','/test.sh command'];cmd里面的参数会被忽略        command: ['/test.sh']        # command带参数        # command: ['/test.sh','command']        #args: ['args']eof  
3)command 不存在,但 args 存在场景测试
如果 command 没写,但 args 写了,那么 docker 默认配置的 entrypoint 的命令行会被执行,但是调用的参数是.yaml中的 args,cmd 的参数会被覆盖,但是 entrypoint 自带的参数还是会执行的。
cat < test3.yamlapiversion: apps/v1kind: deploymentmetadata:  name: test3spec:  replicas: 1  selector:    matchlabels:      app: test3  template:    metadata:      labels:        app: test3    spec:      nodename: local-168-182-110      containers:      - name: test3        image: test:v1        # ['/bin/sh','-c','/test.sh command','hello'],加了'/bin/sh','-c',也是不能外部传参,不会输出hello,只能通过这样传参,['/bin/sh','-c','/test.sh command'];cmd里面的参数会被忽略        # command: ['/test.sh']        # command带参数        # command: ['/test.sh','command']        args: ['args']eof  
4)command 和 args 都存在场景测试
如果如果 command 和 args 都写了,那么 docker 默认的配置被忽略,使用.yaml的配置。
cat < test4.yamlapiversion: apps/v1kind: deploymentmetadata:  name: test4spec:  replicas: 1  selector:    matchlabels:      app: test4  template:    metadata:      labels:        app: test4    spec:      nodename: local-168-182-110      containers:      - name: test4        image: test:v1        # ['/bin/sh','-c','/test.sh command','hello'],加了'/bin/sh','-c',也是不能外部传参,不会输出hello,只能通过这样传参,['/bin/sh','-c','/test.sh command'];cmd里面的参数会被忽略        # command: ['/test.sh']        # command带参数,command和args都会带上        command: ['/test.sh','command']        args: ['args']eof  
镜像构建 dockerfile 的介绍就到这里了,有疑问的小伙伴欢迎给我留言哦!


你是区块链相关的圈内人吗
Mac并非完全不受恶意软件的侵害
TI如何实现低噪声和高精度的方法详解
安科瑞智能照明控制系统在办公楼上的应用
一文详解开关电源的各种过压保护电路
镜像构建Dockerfile的介绍
长安汽车:阿维塔NCA功能已覆盖6座城市,年内将实现全国覆盖
各家车企纷纷“落户”硅谷,自主品牌的海外之路
动力电池原材料价格上涨 新能源汽车整车厂转嫁压力
探索将氧化还原活性的含硝基基聚合物作为电化学储能材料
单片机具体应用_单片机具体应用领域
教你用CAM350把两块班子拼在一起
MAX13174E +5V、多协议、引脚可选的电缆端接器(含
NEXTCHIP
Linux内核学习的经验总结
物联网与医疗企业将不断深入融合未来有望迎来新一轮发展
数字万用表电路板铜丝的作用
简谈基于FPGA的千兆以太网
配送机器人也正颠覆着整个物流行业的“最后一公里”
智慧园区建设实践方案