使用Dockerfile构建镜像

什么是Dockerfile

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

Dockerfile 文件具有特定的语法规则。

Docker 按照顺序执行 Dockerfile 文件里的指令集合。

官方文档:https://docs.docker.com/engine/reference/builder/

Dockerfile常用指令

FROM

指定基于哪个基础镜像来构建新镜像,如果没有指定tag,则使用默认latest。

FROM <image>:<tag>

Docker 中存在一个特殊的镜像 scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。如果以 scratch 为基础镜像的话,意味着不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。

FROM scratch

注:

  • FROM 必须是第一个非注释行指令
  • 默认会从本地查找指定的基础镜像,如果本地不存在,则会从远程拉取所需镜像。

RUN

用于执行命令行命令,有两种格式:

RUN <command>
RUN ["executable", "param1", "param2"]

示例:

 RUN tar -xvf redis.tar.gz

需要执行多个命令时,推荐使用 && 符号连接多个命令,这样执行后,只会创建 1 层镜像:

RUN apt-get update \
    && mkdir -p /usr/src/redis \
    && tar -xvf redis.tar.gz

LABEL

以键值对的形式给镜像添加一些元数据(metadata)。

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

示例:

LABEL version="1.0" org.opencontainers.image.authors="xxx"

MAINTAINER (deprecated)

指定镜像作者及联系方式,已经弃用,推荐使用 LABEL

EXPOSE

暴露端口,可以指定端口是监听TCP还是UDP,如果不指定协议,默认为TCP。

要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。-p 是映射宿主机端口和容器端口,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会在宿主机和容器进行端口映射。

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

示例:

EXPOSE 80/udp

要同时在 TCP 和 UDP 上公开,请包含两行:

EXPOSE 80/tcp
EXPOSE 80/udp

ENV

设置环境变量。

两种方式:

ENV <key> <value>

# 此语法不允许在单个ENV指令中设置多个环境变量,推荐使用第一种
ENV <key1>=<value1> <key2>=<value2>... 

COPY

从上下文目录中复制文件或者目录到镜像内指定路径。

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

<src>:源文件或者源目录可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则

<dest>:可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR 指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。

示例:

# 复制所有以 "hom" 开头的文件
COPY hom* /mydir/

# ?被替换为任何单个字符,例如 "home.txt"。
COPY hom?.txt /mydir/

# 使用相对路径,将 "test.txt" 添加到 <WORKDIR>/relativeDir/
COPY test.txt relativeDir/

ADD

ADD 指令和 COPY 的使用基本一致。ADDCOPY的不同在于:

  • 如果 <src> 为一个 tar 压缩文件,压缩格式为 gzip, bzip2 以及 xz 的情况下,ADD 指令将会自动解压缩这个文件到 <dest>中 。
  • <src> 可以是一个 URL,这种情况下,Docker 引擎会试图去下载这个链接的文件放到 <dest>中。
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

CMD

启动容器时需要执行的命令。如果存在多个 CMD 指令,则只会有最后一个生效。使用docker run命令启动容器时指定要运行的程序可以覆盖 CMD 指令。

有以下三种格式:

CMD ["executable","param1","param2"]
CMD ["param1","param2"] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数
CMD command param1 param2

RUN 指令的区别:CMD 是在 docker run 时运行,而 RUN 是在 docker build 是执行。

ENTRYPOINT

类似 CMD 指令,但是不会被 docker run 指定的指令所覆盖。如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

有以下二种格式:

# exec格式
ENTRYPOINT ["executable", "param1", "param2"]
# shell格式
ENTRYPOINT command param1 param2

注意:

  • 运行 docker run 命令时如果使用了 --entrypoint 选项,将覆盖 CMD 指令指定的程序。

  • 搭配 CMD 命令使用, CMD 相当于是在给 ENTRYPOINT 传参。

VOLUME

定义匿名数据卷。

格式如下:

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

在启动容器执行 docker run 的时候,我们可以通过 -v 参数修改挂载的数据目录。

USER

指定执行指令的用户。

有两种格式:

USER <user>[:<group>]
USER <UID>[:<GID>]

WORKDIR

指定工作目录,用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。如该目录不存在,WORKDIR 会帮你建立目录。

WORKDIR /path/to/workdir

ARG

设置在构建过程中使用的环境变量,也就是说ARG 设置的环境变量只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

ARG <name>[=<default value>]

一个 Dockerfile 文件可能包含一个或多个ARG指令。用户在使用docker build 构建时,可以使用--build-arg <varname>=<value> 标志的命令将其传递给构建器。

FROM busybox
ARG user1
ARG buildno

SHELL

更改执行shell命令的程序。

SHELL ["executable", "parameters"]

Linux 上的默认 shell 是["/bin/sh", "-c"],Windows 上是["cmd", "/S", "/C"]。该SHELL指令在 Windows 上特别有用,因为 Windows 有两种常用且截然不同的本机 shell:cmdpowershell,以及可用的备用 shell,包括sh

ONBUILD

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

ONBUILD <其他指令>

STOPSIGNAL

设置容器退出时发出的关闭信号。

STOPSIGNAL signal

HEALTHCHECK

指定某个程序或者指令来监控容器的运行状态。

# 设置检查容器健康状况的命令
HEALTHCHECK [OPTIONS] CMD command
# 如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK NONE

HEALTHCHECK 支持下列选项:

  • --interval=<间隔>:两次健康检查的间隔,默认为 30 秒;
  • --timeout=<时长>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
  • --retries=<次数>:当连续失败指定次数后,则将容器状态视为 unhealthy,默认 3 次。

CMD, ENTRYPOINT 一样,HEALTHCHECK 只可以出现一次,如果写了多个,只有最后一个生效。

使用Dockerfile构建镜像

(1)编写Dockerfile文件

vi Dockerfile
  • 文件名一般就叫 Dockerfile。

Dockerfile文件内容如下:

FROM centos:7
LABEL version="1.0" org.opencontainers.image.authors="charles"
WORKDIR /usr/local
RUN mkdir -p /usr/local/java && mkdir -p /usr/local/tomcat
ADD jdk-11.0.12_linux-x64_bin.tar.gz /usr/local/java
ADD apache-tomcat-10.0.10.tar.gz /usr/local/tomcat
EXPOSE 8081
ENV JAVA_HOME /usr/local/java/jdk-11.0.12
ENV PATH $PATH:$JAVA_HOME/bin
CMD ["/usr/local/tomcat/apache-tomcat-10.0.10/bin/catalina.sh", "run"]

(2)使用 docker build 命令从 Dockerfile 和“上下文”构建 Docker 镜像。构建的上下文可以是构建执行所在的本地路径,也可以是远程URL,如Git库、tarball或文本文件等。

docker build [OPTIONS] PATH | URL | -

Options:

  • --add-host:添加自定义主机到 IP 映射(host:ip)。
  • --build-arg:设置构建时的变量。
  • --compress:默认false,使用 gzip 压缩构建上下文。
  • --file, -f:Dockerfile的完整路径,默认值为("PATH/Dockerfile")。
  • --label:设置镜像的元数据。
  • --no-cache:构建镜像时不使用缓存。
  • --tag, -t,镜像的名字及标签,通常name:tag或者name格式,可以在一次构建中为一个镜像设置多个tag。

构建镜像:

在Dockerfile同级目录执行如下命令。

docker build -f Dockerfile -t mycentos:7 .

注意:jdk、tomcat和Dockerfile目录相同。

(3)基于刚刚创建的镜像启动容器:

docker run -id --name mycentos7 -p 8080:8080 mycentos:7

访问:http://127.0.0.1:8080/ 可以看到 tomcat 成功启动页面。

上一篇:一文详解Vue插槽slot的使用与案例展示,看完就彻底明白了


下一篇:分享一个简单好看的背景图