Dockerfile 指令详解

FROM

  • FROM 指定基础镜像,因此一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令
  • 格式: FROM <基础镜像>

RUN

  • RUN 指令是用来执行命令行命令的。
  • 格式:
    shell 格式:RUN <命令>
    exec 格式: RUN ["可执行文件", "参数1", "参数2"]
  • 每一个RUN 的行为:新建立一层,在其上执行这些命令,执行结束后, commit 这一层的修改,构成新的镜像,可使用&&将各个所需命令串联起来

COPY 复制文件

  • COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。
  • 格式:
    COPY [--chown=<user>:<group>] <源路径>... <目标路径>
    COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
  • <源路径> 可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的filepath.Match 规则。
  • <目标路径> 可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR 指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。
  • --chown=<user>:<group>选项用来改变文件的所属用户及所属组。

注意:使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。


ADD 更高级的复制文件

  • ADD 指令将从 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置,如果是压缩文件则自动解压。
  • 格式:
    ADD[--chown=<user>:<group>] <源路径>... <目标路径>
    ADD[--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
  • <源路径> 除了肯容易是构建上下文目录外,还可以是一个 URL 。
  • <目标路径> 可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR 指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。
  • --chown=<user>:<group>选项用来改变文件的所属用户及所属组。
  • ADD 指令基本与 COPY 指令一样,但在COPY 指令基础上添加了以下功能:
    a. <源路径> 可以是一个 URL ,这种情况下,Docker 引擎会试图去下载这个链接的文件放到 <目标路径> 去,下载后的文件权限自动设置为 600 。
    b. 如果 <源路径> 为一个 tar 压缩文件的话,压缩格式为 gzip , bzip2 以及xz 的情况下, ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。
  • ADD 指令相对于 COPY 指令的劣势:
    a. 如果自动设置的600权限并不是想要的权限,那么还需要增加额外的一层 RUN 进行权限调整。
    b. 如果下载的是个压缩包,需要解压缩,也一样还需要额外的一层 RUN 指令进行解压缩。
  • ADD 指令与 COPY 指令选择原则:
    a. 所有的文件复制均使用 COPY 指令
    b. 仅在需要自动解压缩的场合使用 ADD 指令

CMD 容器启动命令

  • CMD 指令就是用于指定默认的容器主进程的启动命令的。
  • 格式:
    shell 格式: CMD <命令>
    exec 格式: CMD ["可执行文件", "参数1", "参数2"...]
    参数列表格式: CMD ["参数1", "参数2"...](在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数)
  • 在指令格式上,一般推荐使用 exec 格式,这类格式在解析时会被解析为 JSON数组,因此一定要使用双引号 " ,而不要使用单引号。
  • 如果使用 shell 格式的话,实际的命令会被包装为 sh -c 的参数的形式进行执行。
    CMD echo $HOME 将会被转换成 CMD [ "sh", "-c", "echo $HOME" ]
  • Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 systemd 去启动后台服务,容器内没有后台服务的概念。
  • 对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。
  • CMD 只可以出现一次,如果写了多个,只有最后一个生效。

ENTRYPOINT 入口点

  • ENTRYPOINT 是在指定容器启动程序及参数。
  • 格式:
    shell 格式: ENTRYPOINT <命令>
    exec 格式: ENTRYPOINT ["可执行文件", "参数1", "参数2"...]
  • 当指定了 ENTRYPOINT 后, CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令
  • ENTRYPOINT 指令比 CMD 指令更好的使用:
    a. 让镜像变成像命令一样使用
    b. 在应用运行前做准备工作
  • ENTRYPOINT 只可以出现一次,如果写了多个,只有最后一个生效。

ENV 设置环境变量

  • 设置环境变量,无论是后面的其它指令,如 RUN ,还是运行时的应用,都可以直接使用这里定义的环境变量。
  • 格式有:
    ENV <key> <value>
    ENV <key1>=<value1> <key2>=<value2>...
  • 通过环境变量,只需使用不同的环境变量即可让一份 Dockerfile 制作更多的镜像,升级镜像构建版本的时候,只需要更新相应环境变量即可, Dockerfile 构建维护变得更轻松了。
  • 下列指令可以支持环境变量展开:
    ADD 、 COPY 、 ENV 、 EXPOSE 、 LABEL 、 USER 、 WORKDIR 、 VOLUME 、STOPSIGNAL 、 ONBUILD 。

ARG 构建参数

  • ARG 和 ENV 的效果一样,都是设置环境变量,但A RG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。
  • 格式: ARG <参数名>[=<默认值>]
  • Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build 中用 --build-arg <参数名>=<值> 来覆盖。

VOLUME 定义匿名卷

  • 容器运行时应该尽量保持容器存储层不发生写操作, VOLUME 可保证了容器存储层的无状态化。
  • 格式:
    VOLUME ["<路径1>", "<路径2>"...]
    VOLUME <路径>
  • 为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。

EXPOSE 声明端口

  • EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。
  • 格式为 EXPOSE <端口1> [<端口2>...]
  • Dockerfile 中写入这样的声明有两个好处:
    a. 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;
    b. 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

注意:EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。


WORKDIR 指定工作目录

  • WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在, WORKDIR 会帮你建立目录。
  • 格式为 WORKDIR <工作目录路径>

USER 指定当前用户

  • USER 改变之后层的执行 RUN , CMD 以及ENTRYPOINT 这类命令的身份
  • 格式:USER <用户名>[:<用户组>]
  • USER 只是帮助切换到指定用户,这个用户必须是事先建立好的,否则无法切换。

HEALTHCHECK 健康检查

  • HEALTHCHECK 指令是告诉 Docker 应该如何进行判断容器的状态是否正常。
  • 格式:
    HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令, <命令> 分为shell 格式,和 exec 格式,命令的返回值决定了该次健康检查的成功与否: 0 :成功; 1 :失败; 2 :保留,不要使用这个值。
    HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
  • 通过该指令指定一行命令,用这行命令来判断容器主进程的服务状态是否还正常,从而比较真实的反应容器实际状态。
  • 当在一个镜像指定了 HEALTHCHECK 指令后,用其启动容器,初始状态会为starting ,在 HEALTHCHECK 指令检查成功后变为 healthy ,如果连续一定次数失败,则会变为 unhealthy 。
  • HEALTHCHECK 支持下列选项:
    --interval=<间隔>:两次健康检查的间隔,默认为 30 秒;
    --timeout=<时长>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
    --retries=<次数>:当连续失败指定次数后,则将容器状态视为unhealthy ,默认 3 次。
  • HEALTHCHECK 只可以出现一次,如果写了多个,只有最后一个生效。

ONBUILD 为他人做嫁衣裳

  • 格式:ONBUILD <其它指令>
  • ONBUILD 后面跟的其它指令在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。
  • Dockerfile 中的其它指令都是为了定制当前镜像而准备的,唯有 ONBUILD 是为了帮助别人定制自己而准备的。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,423评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,147评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,019评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,443评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,535评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,798评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,941评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,704评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,152评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,494评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,629评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,295评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,901评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,978评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,333评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,499评论 2 348