Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux 或 Windows 操作系统的机器上,也可以实现虚拟化。本文介绍 Dockerfile 各项命令的作用,以及如何使用 Dockerfile 打包 java 程序为镜像,并导出和运行。

一、Dockerfile

FROM

FROM <image>
FROM <image>:<tag>
FROM <image>:<digest>

定制的镜像是基于 FROM 的镜像,这里的 openjdk 就是定制需要的基础镜像。后续的操作都是基于 openjdk

FROM openjdk:8-jdk-alpine

MAINTAINER

MAINTAINER <messages>

声明作者信息,可以放在文件任何位置,建议放在FROM后面。

MAINTAINER nineya

不过,MAINTAINER并不推荐使用,更推荐使用LABEL来指定镜像作者。

LABEL maintainer="nineya"

LABEL

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

LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式。

WORKDIR

WORKDIR <工作目录路径>

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。

USER

USER <user>[:<usergroup>]
USER <UID>[:<UID>]

为 RUN、CMD 和 ENTRYPOINT 执行 Shell 命令指定运行用户。

RUN

RUN <commands>
RUN ["executable", "param1", "param2",...]

使用镜像构建容器时需要运行的命令。RUN 命令在构建时会创建一个新层,如非特殊的需要,建议一个Dockerfile在需要使用 RUN 命令的时候尽可能的只用一个 RUN 命令,将多条 RUN命 令进行合并可以有效降低构建的镜像的层数。

可用于添加依赖包

RUN ["yum", "install", "httpd"]
RUN yum install httpd

CMD

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

在容器启动时执行,可被 docker run 命令行参数中指定要运行的程序所覆盖。如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

如果存在 ENTRYPOINT 命令,则 CMD 内容将做为 ENTRYPOINT 的参数。

可用于做默认启动命令

CMD echo "hello world"

COPY

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

复制指令,从上下文目录中复制文件或者目录到容器里指定路径。可选参数 --chown=<user>:<group> 用于改变复制到容器内文件的拥有者和属组,源文件或者源目录,这里可以是通配符表达式。

COPY hom* /mydir/
COPY hom?.txt /mydir/

ADD

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

ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

  • ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
  • ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

ENV

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

ENV DAPP_NAME="sdk" \
    TZ=Asia/Shanghai

ARG

ARG <name>[=<value>]

构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

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

ENTRYPOINT

RUN <commands>
RUN ["executable", "param1", "param2",...]

启动容器时执行的Shell命令,同 CMD 类似,只是由 ENTRYPOINT 启动的程序不会被 docker run 命令行指定的参数所覆盖,而且这些命令行参数内容会被当作参数传递给 ENTRYPOINT 指定指定的程序。

ENTRYPOINT ["/start.sh", "start"]
ENTRYPOINT /start.sh start

VOLUME

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

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。避免重要的数据,因容器重启而丢失,避免容器不断变大。

VOLUME ["/data1","/data2"]

EXPOSE

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

仅仅只是声明端口,作用是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射,在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

ONBUILD

ONBUILD <其它指令>

这个命令只对当前镜像的子镜像生效,即,当前镜像被其他镜像的 FROM 引用时执行。

STOPSIGNAL

STOPSIGNAL signal

STOPSIGNAL 指令设置将发送到容器的系统调用信号以退出。此信号可以是与内核的系统调用表中的位置匹配的有效无符号数,例如 9,或 SIGNAME 格式的信号名,例如 SIGKILL。

HEALTHCHECK

HEALTHCHECK [OPTIONS] CMD command
HEALTHCHECK NONE

容器健康状况检查命令,第一个的功能是在容器内部运行一个命令来检查容器的健康状况,第二个的功能是在基础镜像中取消健康检查命令。

[OPTIONS]的选项支持以下三中选项:

--interval=DURATION 两次检查默认的时间间隔为30秒

--timeout=DURATION 健康检查命令运行超时时长,默认30秒

--retries=N 当连续失败指定次数后,则容器被认为是不健康的,状态为unhealthy,默认次数是3

CMD后边的命令的返回值决定了本次健康检查是否成功,具体的返回值如下:

0: success - 表示容器是健康的

1: unhealthy - 表示容器已经不能工作了

2: reserved - 保留值

HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1

二、构建和运行

  1. 使用 Dockerfile 构建镜像

    docker build -f Dockerfile文件 -t 镜像name:镜像tag .
    
  2. 镜像的导出、删除和导入

    # 镜像导出
    docker save imageId > openjdk.tar 镜像name:镜像tag .
    
    # 删除镜像
    docker rmi imageId
    
    # 镜像导入
    docker load < openjdk.tar
    
  3. 启动容器

    docker run imageId -d