Dockerfile 语法及最佳实践

343 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

FROM 指令:用于指定基础镜像,如果没有指定标签,默认为 latest

  • 出于安全考虑,尽量使用官方镜像作为基础镜像。
  • FROM scratch 制作基础镜像。scratch 是一个空镜像,可以用于构建 busybox 等超小镜像,可以说是真正的从零开始构建属于自己的镜像。
  • FROM centos 使用基础镜像
  • 举例:FROM ubuntu:14.04

LABEL 指令,用于定义镜像元数据。

  • 语法:LABEL <key>=<value> <key>=<value> ...
  • LABEL 指令有点类似于代码中的注释,用于记录镜像的元数据,也是必不可少的。
  • LABEL maintainer="jpch89@outlook.com"。这种写法是 MAINTAINER <name> 指令的替代方案,因为 MAINTAINER 指令已经过时了。
  • LABEL version="1.0"
  • LABEL description="This is description"

RUN 指令,用于执行命令。

  • 每运行一次 RUN,镜像都会生成新的一层。
  • 为了避免无用分层,建议合并多条命令为一行,使用反斜线 \ 在行尾连接命令。
RUN yum update && yum install -y vim \
    python-dev  # 反斜线换行

WORKDIR 指令,用于设置当前工作目录。

  • 类似于 Linux 中的 cd 命令,推荐使用 WORKDIR 而不要使用 RUN cd
  • 尽量使用绝对路径,因为绝对目录更加清晰,而相对目录容器出错。
  • WORKDIR /test,如果没有会自动创建 /test 目录。
  • WORKDIR demo
  • RUN pwd,打印的应该是 /test/demo

ADD <src> <dest> 指令与 COPY 指令基本相同,都可以把本地文件添加到镜像中,但是 ADD 还支持下载以及自动解压缩。

  • ADD hello /,把当前目录下的 hello 文件添加到镜像的根目录中。
  • ADD test.tar.gz /,添加到根目录并解压缩
  • WORKDIR /root 然后 ADD hello test/,效果是把 hello 添加到了 /root/test 文件夹
  • WORKDIR /root 然后 COPY hello test/,效果同上
  • 大部分情况下,优先使用 COPYADD 有解压缩功能
  • 如果是添加远程文件或者目录,请使用 RUN curl 或者 RUN wget

EXPOSE 指令:

  • 语法:EXPOSE <port> [<port>/<protocol>...]
  • 向外部暴露容器端口,可以指定协议为 tcp 或者 udp,如果未指定,默认为 tcp
  • EXPOSE 80 443 8080/tcp
  • 注意:如果想建立容器与宿主机之间的端口映射,必须在容器启动的时候加上 -p 参数。

ENV 指令,设置环境变量。

  • 语法:ENV <key> <value>,不支持一次性赋值多个。
  • 或者:ENV <key>=<value> <key>=<value>,支持一次性赋值多个。
  • 举例:
ENV MYSQL_VERSION 5.6
RUN apt-get install -y mysql-server="${MYSQL_VERSION}" \
&& rm -rf /var/lib/apt/lists/*
  • 尽量使用 ENV 增强 Dockerfile 的可维护性

VOLUME 指令,设置数据卷。有两种形式:

  • JSON 数组形式:VOLUME ["/var/log/"]
  • 直接写多个参数:VOLUME /var/log /var/db
  • 注意:这里的目录都是宿主机的目录,并非容器内部目录
  • 另外,通常还是使用 docker run 的时候通过 -v 参数

官方名称是 EXEC 格式与 SHELL 格式。