Docker系列(四):Dockerfile 配置详解

Docker 通过读取 Dockerfile文件中的指令自动构建镜像,Docker 镜像包含只读层,每一层就代表 Dockerfile 中的一条指令,层与层是堆叠的,每一层是与前一层的变化的增量。使用 docker build命令,用户可以创建一个自动构建,连续执行多条命令行的指令。

官方参考:Dockerfile官方最佳实践, Docker 中文站

概述

Dockerfile 由一行行命令语句组成,支持以#开头的注释行,注释行不能换行。

Dockerfile 基本结构可划分为四个部分:

  1. 基础镜像信息:文件开始必须先指明所基于的基础像名称。
  2. 维护者信息:说明下维护者信息。
  3. 镜像操作指令:RUN指令,每执行一条RUN指令,镜像就添加新的一层,并提交。
  4. 容器启动时执行指令:CMD,用来指定运行容器时的操作命令。

指令

Dockerfile文件中的指令是按先后顺序执行,可以使用的指令有如下:

指令 说明
FROM 指定所创建镜像的基础镜像
MAINTAINER 指定维护者(作者)信息
RUN 运行命令
LABEL 指定生成镜像的元数据标签信息
EXPOSE 声明镜像内服务服务所监听的端口
ENV 指定环境变量
ADD 添加指定的<src>路径下的内容到容器中的<dest>路径下, <src>可以为 URL,如果为 tar 文件,则会自动解压到<dest>路径下
COPY 复制本机的路径下的内容到镜像中的<dest>路径下;一般推荐使用 COPY,而不是ADD
ENTRYPOINT 指定镜像的默认入口
VOLUME 创建数据卷的挂载点
USER 指定运行容器时的用户名或UID
WORKDIR 配置工作目录
ARG 指定镜像内使用的参数(如版本号信息)
ONBUILD 配置当前所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作指令
STOPSIGNAL 容器退出的信号值
HEALTHCHECK 进行健康检查
SHELL 指定使用 shell 时的默认 shell 类型

指令详解

FROM

一个 Dockerfile 以FROM指令开始(启动)。指令指定指定了基础镜像,如果本地没有就会到远程仓库下载。基础镜像推荐官方发行版,理由是控制严格,保持最低文件大小(Debian 低于150M)。

RUN

在当前镜像新的层中执行命令并提交结果,生成新的镜像作为 Dockerfile 中下一步指令的基础镜像。该命令有shellexecform两种形式。

  1. shell 方式: RUN <cmomand>
    在shell中运行,默认情况下,Linux是在 /bin/sh -c下运行, Windows是在 cmd /S /C下运行; 此方式可以使用 \ 将多行命令连接为为一行:

    RUN /bin/bash -c ‘source $HOME/.bashrc;
    echo $HOME’

    连接后等同于一行,如下:
    RUN /bin/bash -c ‘source $HOME/.bashrc; echo $HOME’

  2. exec form 方式RUN ["executable", "param1", "param2"]
    该方式可以避免 shell 命令执行时发生字符串转换,并且可以不包含指定可执行shell文件,exec form 方式会被转换为 JSON 数组,命令和参数必须使用双引号括起来。如果是在 Widnows环境,路径中\\\代替。

CMD

一份 Dockerfile 文件中只能有一条CMD指令,若出现多条时,则只有最后一条CMD指令生效,CMD指令有三种形式:

CMD ["executable","param1","param2"](exec form,首选方式)
CMD ["param1","param2"](作为 ENTRYPOINT 的默认参数)
如果使用此方式,则必须使用 JSON 数组格式 同时指定 CMD 和 ENTRYPOINT 指令。

CMD command param1 param2(shell 方式)

如果用户在docker run指令中指定的参数,则会覆盖掉CMD中指定的默认参数。RUN是执行命令并提交结果;而CMD在构建时并不执行任何操作,是镜像的预期命令,在镜像构建完后执行。

MAINTAINER

用于指定镜像的维护者(作者)。

MAINTAINER kitty kitty@xxx.com

EXPOSE

设置容器必须监听的端口(暴露的端口):EXPOSE port [port ...]

此端口是用于与本地主机的通信,外部应用不能直接访问容器,只能通过访问本地主机的端口再转发到容器的端口。

在创建容器时,需要通过-p参数来指定本地主机的端口与容器暴露的端口的映射关系。

ENV

用于设置环境变量。
语法:有两种方式

  1. ENV <key> <value>
  2. ENV <key>=<value> ...
    如:ENV myName=”John Doe”

ENTRYPOINT

可以让容器像一个可执行程序一样运行,这样在执行docker run命令时可以接收参数。最好的用法是用 ENTRYPOINT 来设置镜像的主要命令,用 CMD 来设置默认参数。

VOLUME

用于指明容器创建或配置的数据存储区域或创建的文件或目录所在路径。推荐使用。

WORKDIR

应该使用绝对路径,而不是繁琐的RUN cd .... && do-someting

ADD 或 COPY

这两个命令在功能上类似,推荐使用COPYCOPY只能将本地文件复制到容器中;ADD额外支持可以将本地的tar提交到镜像中,或添加远程URL的文件。尽量不是使用ADD命令从远程URL获取软件包,应该使用curlwget代替。

不好的例子:
ADD http://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C /usr/src/things all

推荐的例子:
RUN mkdir -p /usr/src/things
&& curl -SL http://example.com/big.tar.xz
| tar -xJC /usr/src/things
&& make -C /usr/src/things all

Dockerfile示例

centos-jdk镜像

  1. 编辑 Dockerfile 文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #基础镜像
    FROM centos:latest

    #作者
    MAINTAINER gxing gxing@163.com

    #在镜像中创建目录
    RUN mkdir -p /usr/local/jdk1.8
    #在镜像中创建工作目录
    RUN mkdir -p /work

    #指定工作目录
    WORKDIR /work

    #复制目录
    COPY jdk1.8.0_172 /usr/local/jdk1.8

    #设置环境变量
    ENV JAVA_HOME="/usr/local/jdk1.8"
    ENV CLASSPATH=".:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar"
    ENV PATH="$JAVA_HOME/bin:$PATH"

    EXPOSE 80
    EXPOSE 8080
  2. 执行构建包含jdk的镜像

    $ docker build -t repos_local/centos-jdk1.8:1.0 .

说明:-t设置 tag 命,通常规则定义是 库/镜像名:tag,tag一般用于表示版本,.表示当前目录下的 Dockerfile 文件。

参考:
五种方式:构建小巧Docker容器的学问

Docker系列(四):Dockerfile 配置详解

http://blog.gxitsky.com/2018/06/20/docker-4-dockerfile/

作者

光星

发布于

2018-06-20

更新于

2021-02-05

许可协议

评论