Docker Dockerfile指令说明(十二)

Docker Dockerfile指令说明(十二)

Scroll Down

通常创建镜像三种方法:

  1. 基于已有镜像创建
  2. 基于本地模板创建
  3. 基于Dockerfile创建

本篇主要讲解通过Dockerfile创建镜像

1. 指令说明

Dockerfile是由一组指令组成的文件,其中每条指令对应Linux中的一条命令,Docker程序将读取Dockerfile中的指令生成指定镜像。

Dockerfile结构大致分为四个部分:

  1. 基础镜像信息
  2. 维护者信息
  3. 镜像操作指令
  4. 容器启动时执行指令

Dockerfile每行支持一条指令,每条指令可带多个参数,支持使用以#号开头的注释。

Dockerfile中指令的一般格式为INSTRUCTION arguments,包括“配置指令”(配置镜像信息)和“操作指令”(具体执行操作)

指令表格

分类 指令 说明
配置指令
ARG 定义创建镜像过程中使用的变量
FROM 指定所创建镜像的基础镜像
LABEL 为生成的镜像添加元数据标签信息
EXPOSE 声明镜像内服务监听的端口
ENV 指定环境变量
ENTRYPOINT 指定镜像的默认入口命令
VOLUME 创建一个数据卷挂载点
USER 指定运行容器时的用户名或UID
WORKDIR 配置工作目录
ONBUILD 创建子镜像时指定自动执行的操作指令
STOPSIGNAL 指定退出的信号值
HEALTHCHECK 配置所启动容器如何进行健康检查
SHELL 指定默认shell类型
操作指令
RUN 运行指定命令
CMD 启动容器时指定默认执行的命令
ADD 添加内容到镜像
COPY 复制内容到镜像

2. 配置指令

2.1 ARG

定义创建镜像过程中使用的变量。

ARG<name>[=<default value>]

在执行docker build时,可以通过-build-arg[=]来为变量赋值。当镜像编译成功后,ARG指定的变量将不再存在(ENV指定的变量将在镜像中保留)。

Docker内置了一些镜像创建变量,用户可以直接使用而无须声明,包括(不区分大小写)HTTP PROXY、HTTPS PROXY、FTP PROXY、NO PROXY。

2.2 FROM

指定所创建镜像的基础镜像。

FROM <image>[As <name>]

FROM <image>:<tag>[As <name>]

FROM <image>@<digest>[As<name>]

任何Dockerfile中第一条指令必须为FROM指令。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个FROM指令(每个镜像一次)。

为了保证镜像精简,可以选用体积较小的镜像如Alpine或Debian作为基础镜像。例如:

ARG VERSION=9.3
FROM debian:${VERSION}

2.3 LABEL

LABEL指令可以为生成的镜像添加元数据标签信息。这些信息可以用来辅助过滤出特定镜像。

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

例如:

LABEL version="1.0.0-rc3"
LABEL author="yeasy@github"date="2020-01-01"
LABEL description="This text illustrates \
that label-values can span multiple lines."

2.4 EXPOSE

声明镜像内服务监听的端口

EXPOSE命名适用于设置容器对外映射的容器端口号,如tomcat容器内使用的端口8081,则用EXPOSE命令可以告诉外界该容器的8081端口对外,在构建镜像时用docker run -p可以设置暴露的端口对宿主机器端口的映射。

EXPOSE <port>[<port>/<protocols..]

例如:

EXPOSE 22 808 443

注意该指令只是起到声明作用,并不会自动完成端口映射。

如果要映射端口出来,在启动容器时可以使用-p参数(Docker主机会自动分配一个宿主机的临时端口)或-p HOST_PORT:CONTAINER_PORT参数(具体指定所映射的本地端口)。

EXPOSE 8081 其实等价于 docker run -p 8081 当需要把8081端口映射到宿主机中的某个端口(如8888)以便外界访问时,则可以用docker run -p 8888:8081

2.5 ENV

指定环境变量,在镜像生成过程中会被后续RUN指令使用,在镜像启动的容器中也会存在。

ENV <key><value>或NV <key>=<value>…。

例如:

ENV APPVERSION=1.0.0
ENV APP_HOME=/usr/local/app
ENV PATH $PATH:/usr/1ocal/bin

指令指定的环境变量在运行时可以被覆盖掉,如docker run--env =cvalue> built_image。

注意当一条ENV指令中同时为多个环境变量赋值并且值也是从环境变量读取时,会为变量都赋值后再更新。如下面的指令,最终结果为keyl=value1 key2=value2:

ENV keyl=value2
ENV keyl=value1 key2=5{key1}

2.6 ENTRYPOINT

指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数。

支持两种格式:

ENTRYPOINT["executable","paraml","param2"]:exec调用执行;

ENTRYPOINT command paraml param2:shell中执行。

此时,CMD指令指定值将作为根命令的参数。

每个Dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个起效。

在运行时,可以被--entrypoint参数覆盖掉,如docker run --entrypoint。

ENTRYPOINT的作用和用法和CMD一模一样,但是ENTRYPOINT有和CMD有2处不一样:

  • CMD的命令会被docker run的命令覆盖而ENTRYPOINT不会
  • CMD和ENTRYPOINT都存在时,CMD的指令变成了ENTRYPOINT的参数,并且此CMD提供的参数会被 docker run 后面的命令覆盖

2.7 VOLUME

创建一个数据卷挂载点。

VOLUME用来创建一个可以从本地主机或其他容器挂载的挂载点。例如我们知道tomcat的webapps目录是放web应用程序代码的地方,此时我们要把webapps目录挂载为匿名卷,这样任何写入webapps中的心都不会被记录到容器的存储层,让容器存储层无状态化。

VoLUME["/data"]。

运行容器时可以从本地主机或其他容器挂载数据卷,一般用来存放数据库和需要保持的数据等。

如创建tomcat的webapps目录的一个挂载点

VOLUME /usr/local/tomcat/webapps

这样,在运行容器时,也可以用过docker run -v来把匿名挂载点挂载都宿主机器上的某个目录,如

docker run -d -v /home/tomcat_webapps:/usr/local/tomcat/webapps

2.8 USER

指定运行容器时的用户名或UID,后续的RUN等指令也会使用指定的用户身份。

USER命令用于指定当前望下执行的用户,需要注意的是这个用户必须是已经存在,否则无法指定。它的用法和WORKDIR有点像,切换用户。

USER daemon。

当服务不需要管理员权限时,可以通过该命令指定运行用户,并且可以在Dockerfile中创建所需要的用户。例如:

RUN groupadd -r postgres && useradd --no-log-init -r -g postgres postgres

要临时获取管理员权限可以使用gosu命令。

2.9 WORKDIR

为后续的RUN、CMD、ENTRYPOINT指令配置工作目录。

WORKDIR /path/to/workdir。

可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如:

WORKDIR /a
WORKDIR b
WORKDIR C
RUN pwd

则最终路径为/a/b/c。

因此,为了避免出错,推荐WORKDIR指令中只使用绝对路径。

2.10 ONBUILD

指定当基于所生成镜像创建子镜像时,自动执行的操作指令。
意思就是:这个镜像创建后,如果其它镜像以这个镜像为基础,会先执行这个镜像的ONBUILD命令

ONBUTLD [INSTRUCTION]

例如,使用如下的Dockerfile创建父镜像 ParentImage,指定ONBUILD指令:

#Dockerfile for ParentImage
[...]
ONBUILD ADD ./app/src
ONBUILD RUN /usr/1oca1/bin/python-build --dir /app/src
[...]

使用docker build命令创建子镜像childImage时(FROM ParentImage),会首先执行Parent Image中配置的ONBUILD指令:

#Dockerfile for ChildImage
FROM Parent Image

等价于在childImage的Dockerfile中添加了如下指令:

#Automatically run the following when building ChildImage
ADD ./app/src
RUN /usr/1ocal/bin/python-build --dir /app/src

由于ONBUILD指令是隐式执行的,推荐在使用它的镜像标签中进行标注,例如ruby:2.1-onbuild。

ONBUILD指令在创建专门用于自动编译、检查等操作的基础镜像时,十分有用。

2.11 STOPSIGNAL

指定所创建镜像启动的容器接收退出的信号值:

STOPSIGNAL signal

2.12 HEALTHCHECK

配置所启动容器如何进行健康检查(如何判断健康与否),自Docker1.12开始支持。

格式有两种:

HEALTHCHECK [OPTIONS]CMD command:   # 根据所执行命令返回值是否为0来判断;

HEALTHCHECK NONE                   # 禁止基础镜像中的健康检查。

OPTION支持如下参数:

  • -interval=DURATION(default:30s):过多久检查一次;
  • -timeout=DURATION(default:30s):每次检查等待结果的超时;
  • -retries=N(default:3):如果失败了,重试几次才最终确定失败

2.13 SHELL

指定其他命令使用shell时的默认shell类型:

SHELL ["executable","parameters"]

默认值为["/bin/sh","-c"]。

3. 操作指令

3.1 RUN

RUN指令在新镜像内部执行的命令,如:执行某些动作、安装系统软件、配置系统信息之类

格式如下两种:

1)shell格式:就像直接在命令行中输入的命令一样。

RUN < command > 

如在nginx里的默认主页中写”hello“:

RUN echo 'hello ' >/etc/nginx/html/index.html

2)exec格式

RUN ["可执行文件", "参数1", "参数2"]

如在新镜像中用yum方式安装nginx:

RUN ["yum","install","nginx"]

注:多行命令不要写多个RUN,原因是Dockerfile中每一个指令都会建立一层.多少个RUN就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错,RUN书写时的换行符是\

注意后者指令会被解析为JSON数组,因此必须用双引号。前者默认将在shell终端中运行命令,即/bin/sh-c;后者则使用exec执行,不会启动shell环境。

指定使用其他终端类型可以通过第二种方式实现,例如RUN["/bin/bash","-c","echo hel1o]。

每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像层。当命令较长时可以使用\来换行。例如:

RUN apt-get update \
&& apt-get instal1-y libsnappy-dev zlib1g-dev 1ibbz2-dev \
&& rm -rf /var/cache/apt \
&& rm -rf /var/1ib/apt/1ists/*

3.2 CMD

CMD指令用来指定启动容器时默认执行的命令。

支持三种格式:

CMD ["executable","param1","param2"]   # 相当于执行executable paraml param2,推荐方式;

CMD command param1 param2              # 在默认的Shell中执行,提供给需要交互的应用;

CMD ["param1","param2"]               # 提供给ENTRYPOINT的默认参数。

每个Dockerfile只能有一条CMD命令。如果指定了多条命令,只有最后一条会被执行。

如果用户启动容器时候手动指定了运行的命令(作为run命令的参数),则会覆盖掉CMD指定的命令。

3.3 ADD

添加内容到镜像。

ADD <src> <dest>

该命令将复制指定的路径下内容到容器中的路径下。

其中可以是Dockerfile所在目录的一个相对路径(文件或目录);也可以是一URL;还可以是一个tar文件(自动解压为目录)可以是镜像内绝对路径,或者相对于工作目录(WORKDIR)的相对路径。

路径支持正则格式,例如:

ADD *.c /code/

3.4 COPY

复制内容到镜像。

COPY <src> <dest>

复制本地主机的(为Dockerfile所在目录的相对路径,文件或目录)下内容到镜像中的。目标路径不存在时,会自动创建。
路径同样支持正则格式。
COPY与ADD指令功能类似,当使用本地目录为源目录时,推荐使用COPY。

如把宿主机中的package.json文件复制到容器中/usr/src/app/目录下:

COPY package.json /usr/src/app/

222.jpg