文章目录

  • 1. 写在前面
  • 2. 概念
  • 3. 实际操作
  • 3.1 FROM指令
  • 3.2 RUN指令
  • 3.3 构建镜像
  • 4. 常用指令详解
  • 4.1 COPY
  • 4.2 CMD
  • 4.3 ENV
  • 4.4 ARG
  • 4.5 EXPOSE
  • 4.6 WORKDIR
  • 5. 其他指令介绍
  • 5.1 ENTRYPOINT
  • 5.2 ADD
  • 5.3 VOLUME
  • 5.4 USER
  • 5.5 HEALTHCHECK
  • 5.6 ONBUILD
  • 5.7 LABEL


1. 写在前面

  本文主要针对后端开发人员,主要介绍如何编写我们需要的 Dockerfile,同时结合平时的使用经验,对Dockerfile中的命令进行详细的介绍。

2. 概念

  Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

  一般构建流程如下:


编写Dockerfile




Dockerfile RUN...

Dockerfile FROM...

Dockerfile CMD...

docker build


3. 实际操作

  下面使用 Dockerfile 定制镜像,以 python 工程为例,新建 Dockerfile 文件,添加如下内容:

FROM python:3.7
MAINTAINER xiaoi

# 开放端口
EXPOSE 5000

# 设置环境变量
ENV pypi https://pypi.douban.com/simple
ENV DIR /mnt/HttpServer

# 切换工作目录
COPY ./ ${DIR}
WORKDIR ${DIR}

RUN pip install --no-cache-dir -r requirements.txt flask uwsgi -i ${pypi}
CMD ["sh","app.sh"]

3.1 FROM指令

  定制的镜像都是基于FROM的镜像,这里的 python:3.7 就是定制需要的基础镜像,所有的操作都是基于 python:3.7。

3.2 RUN指令

  用于执行后面跟着的命令行命令,有以下2种格式:

  • shell 格式: RUN ./app.sh 8080 greedy
  • exec 格式: RUN ["./app.py", "8080", "greedy"]

  注意:Dockerfile 的指令每次执行都会在原来的基础上新建一层,过多的无意义层,会导致镜像过大。

  下面我们来举个例子:

FROM centos
RUN yum install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-6.2.5.tar.gz"
RUN tar -xvf redis.tar.gz

  以上构建会创建 3 层镜像,为了简化为,改为以下内容:

FROM centos
RUN yum install wget \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-6.2.5.tar.gz" \
    && tar -xvf redis.tar.gz

  通过&&连接执行命令,只创建了1层镜像。

3.3 构建镜像

  构建命令命令如下:

$ docker build -t HttpServer:v1 .

  命令最后的.,表示会在 Dockerfile 文件存放的目录下执行构建操作。

  顺便提一下,docker build命令得知这个路径后,会将路径下的所有内容打包,由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。

  构建过程中会进行构建日志的打印,出现以下日志则表示构建成功:

Successfully built e4c6e1801984
Successfully tagged HttpServer:v1

4. 常用指令详解

4.1 COPY

  复制指令,从宿主机目录中复制文件/目录到容器里的指定路径。

COPY [--chown=<user>:<group>] <源路径> <目标路径>
COPY [--chown=<user>:<group>] ["<源路径>", "<目标路径>"]

  参数说明:

  • [--chown=<user>:<group>]:可选,改变复制到容器内文件的用户和组
  • <源路径>:源文件/源目录,支持通配符
  • <目标路径>:容器内的路径,如路径不存在会自动创建

4.2 CMD

  类似于RUN指令,用于运行程序,但二者运行的时间点不同,区别如下:

  • CMDdocker run时运行
  • RUNdocker build时运行

  注意事项如下:

  • CMD的作用是为启动的容器指定默认要运行的程序,程序运行结束,容器结束
  • CMD指令指定的程序可被docker run命令行参数中指定要运行的程序所覆盖
  • 如果 Dockerfile 中如果存在多个CMD指令,仅最后一个生效
CMD <shell 命令> 
CMD ["<可执行文件或命令>","<param1>","<param2>",...] 
CMD ["<param1>","<param2>",...]  # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

  推荐使用第二种格式,默认的可执行文件是sh

4.3 ENV

  设置环境变量,定义的环境变量,在后续就可以使用这个环境变量。

  例如我们构建 python 工程的 docker,那么指定 pip 源就可以通过ENV设置了。

# 设置环境变量
ENV pypi https://pypi.douban.com/simple

# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt flask uwsgi -i ${pypi}

4.4 ARG

  构建参数,作用与ENV一致,但作用域不一样。ARG设置的环境变量只有docker build的过程中有效,构建好的镜像内不存在这个环境变量。

  构建命令docker build中可以用--build-arg <参数名>=<值>来覆盖。

  格式:

ARG <参数名>[=<默认值>]

4.5 EXPOSE

  用于声明docker内部的端口

  • 便于镜像的使用者理解镜像服务的端口,方便配置映射。
  • 在运行时使用随机端口映射时,也就是docker run -P时,会自动随机映射EXPOSE的端口。

  格式:

EXPOSE <端口1> [<端口2>...]

4.6 WORKDIR

  指定工作目录,用WORKDIR指定的工作目录,会在构建镜像的每一层中都存在。

  docker build构建镜像过程中的,每一个RUN命令都是新建的一层。WORKDIR指定的工作目录,必须是提前创建好的,只有通过WORKDIR创建的目录才会一直存在。

  格式如下:

WORKDIR <工作目录路径>

5. 其他指令介绍

5.1 ENTRYPOINT

  类似于CMD的指令,但不会被docker run的指定参数所覆盖,而且这些命令行参数会被当作参数送给ENTRYPOINT指令指定的程序。

  在docker run时使用--entrypoint,可以覆盖CMD指令指定的程序。

  优点:在执行docker run的时候可以指定ENTRYPOINT运行所需的参数。

  注意:如果 Dockerfile 中如果存在多个ENTRYPOINT的指令,那么只有最后一个生效。

ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

  搭配CMD命令使用:一般是变参才会使用CMD,这里的CMD等于是在给ENTRYPOINT传参

  如果使用以下 Dockerfile 构建镜像:

ENTRYPOINT ["HttpServer", "-p"]
CMD ["10000:5000"]

  不传参运行docker run HttpServer:v1,容器默认执行HttpServer -p 10000:5000

  传参运行docker run HttpServer:v1 -p 20000:5000,容器默认执行HttpServer -p 20000:5000

5.2 ADD

  和COPY的使用格类似(官方推荐使用COPY)。

  优点:在执行<源文件>为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到<目标路径>

  缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。

5.3 VOLUME

  定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。

  作用:

  • 避免重要的数据,因容器重启而丢失。
  • 避免容器不断变大。

  格式:

VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>

  在启动容器docker run的时候,可通过-v参数修改挂载点。

5.4 USER

  用于指定执行后续命令的用户和用户组。

  格式:

USER <用户名>[:<用户组>]

5.5 HEALTHCHECK

  用于指定某个程序来监控 docker 容器服务的运行状态。

  格式:

HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。

5.6 ONBUILD

  用于延迟构建命令的执行,本次构建镜像的过程中不会执行,当有新的 Dockerfile 使用了之前构建的镜像FROM HttpServer时,会执行Dockerfile 里的ONBUILD指定的命令。

  格式:

ONBUILD <指令>

5.7 LABEL

  LABEL指令可以给镜像添加一些元数据,以key-value的形式,格式如下:

LABEL <key>=<value> <key>=<value> <key>=<value> ...

  比如添加镜像作者命令如下:

LABEL org.opencontainers.image.authors="xiaoi"