【docker知识】DockerFile语法 2:构造指令

1官方文档:Dockerfile reference | Docker Documentation     

   

一、说明

        我们将以HelloWorld案例的方法,由浅入深地理解DockerFile指令,并生成自己的镜像。为了避免冗长的官网文章污染您的视线,这里将重要的,常见的指令应用展现出来。这里不累述更深刻的语句用法,因为篇幅实在太大。

二、镜像制作过程

2.1 编写和制作过程

使用dockerfile制作镜像,简单地说就是以下三步:

  • 编写dockerfie
  • docker build 指令编译
  • run新镜像

2.2 docker build语法

docker build就是制作image的编译过程。

语法是:

docker build [OPTIONS] PATH | URL | -

2.3 官网上的[OPTIONS](参数)表

Name, shorthand

Default

Description

--add-host

Add a custom host-to-IP mapping (host:ip)

--build-arg

Set build-time variables

--cache-from

Images to consider as cache sources

--cgroup-parent

Optional parent cgroup for the container

--compress

Compress the build context using gzip

--cpu-period

Limit the CPU CFS (Completely Fair Scheduler) period

--cpu-quota

Limit the CPU CFS (Completely Fair Scheduler) quota

--cpu-shares , -c

CPU shares (relative weight)

--cpuset-cpus

CPUs in which to allow execution (0-3, 0,1)

--cpuset-mems

MEMs in which to allow execution (0-3, 0,1)

--disable-content-trust

true

Skip image verification

--file , -f

Name of the Dockerfile (Default is PATH/Dockerfile)

--force-rm

Always remove intermediate containers

--iidfile

Write the image ID to the file

--isolation

Container isolation technology

--label

Set metadata for an image

--memory , -m

Memory limit

--memory-swap

Swap limit equal to memory plus swap: -1 to enable unlimited swap

--network

Set the networking mode for the RUN instructions during build

--no-cache

Do not use cache when building the image

--platform

Set platform if server is multi-platform capable

--pull

Always attempt to pull a newer version of the image

--quiet , -q

Suppress the build output and print image ID on success

--rm

true

Remove intermediate containers after a successful build

--security-opt

Security options

--shm-size

Size of /dev/shm

--squash

experimental (daemon)
Squash newly built layers into a single new layer

--tag , -t

Name and optionally a tag in the name:tag format

--target

Set the target build stage to build.

--ulimit

Ulimit options

--help

Print usage

注意,此表格首先掌握-t,-f 就基本够了,其它参数可以用时现学。

三、制作Hello-world镜像实例

        我们先从制作Hello-world镜像实验开始。该案例虽很简单,但足以表明制作过程的必要步骤,剩下的仅仅是制作更复杂的案例。

3.1 环境要求

  • ubuntu或其它linux
  • 已经安装docker
  • 已经安装了gcc

3.2 制作路径过程

先建立工程目录imgmajer:

mkdir -p ~/imgmaker/src ~/imgmaker/build
cd ~/imgmaker
touch  dockerfile

 结构如下:

3.3 建立C语言hello-world程序

cd ~/imgmaker/src
vim hello.c

1)hello-world程序

#include <stdio.h>

int main(int argc, char *argv[])
{
        printf("hello world\n");
        return 0;
}

2)编译

cd ~/imgmaker
gcc  ./src/hello.c -o ./build/hello

 至此,~/imgmaker/build目录下有了hello进程。

3.4 建立dockerfile文件

cd ~/imgmaker
sudo vim dockerfile

将以下文本粘贴进去。

FROM ubuntu:20.04
MAINTAINER smith smith@qq.com
RUN mkdir  /data
COPY ./build/hello /data
ENTRYPOINT ["/data/hello", "smith"]

3.5 编译产生结果镜像

    docker build -t hellome:1.0 .

        编译后生成镜像hellome:1.0,可以通过docker images看到。 

3.6 执行run生成容器

        启动新建镜像:

    docker run hellome:1.0

        至此,基于dockerfile完整地构造出一个新镜像hellome。

四、常见指令简表

        保留字表:

保留字意义重要程度
FROM定义本镜像的基镜像★★★★★
ARG对FORM语句的参数部分定义变量★★★ 
MAINTAINER维护人员名称★★
RUN在构造过程的shell指令前加RUN号★★★★★
WORKDIR指定宿主机工作目录★★★★
ADD拷贝文件,如果是包文件,解压成目录★★★★★
COPY拷贝文件★★★★★
VOLUME数据卷定义★★★
CMD该镜像通过docker run加载成容器时,运行哪个进程★★★★★
ENTERPOINT与CMD相同,可以加参数★★★★★
EXPOSE镜像内守护进程的端口暴露★★★★
USER指定镜像使用的用户权限★★
ENV环境宏变量定义★★★

五、DockerFile指令详述

5.1 FROM语句

5.1.1  概念    

  • FROM是第一构造语句,是定义基镜像的。(相当于:pull镜像+run镜像)
  • 如果dockerfile只构造一个镜像,FROM语句是唯一的。
  • 如果在一个dockerfile构造多个镜像,可以多次出现,每个FROM相当于另起一个dockerfile。
  • 如果前边构造出的镜像是后面构造的基镜像。FROM也可以多次出现。
  •  ARG语句是专门为FROM语句提供参数变量的,是唯一的可以在FROM语句之前出现语句。
  • 在FROM语句之后,基镜像实际上被load成容器了,随后一切操作,实际上是容器操作。

        

2)FROM的语法

FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]

3)可选项说明 

以上两个格式都合法。分别举例如下:

  • FROM ubuntu              此处将ubuntu: latest拉取过来做为基
  • FROM ubuntu:16.04    此处将ubuntu:16.04 拉取过来做为基

自选项目

  •  [--platform=<platform>]  这是如果

        如果 FROM 引用多平台镜像,可选的 --platform 标志可用于指定图像的平台。例如,linux/amd64、linux/arm64 或 windows/amd64。

  • [AS <name>]

        是个阶段可选项,可以通过向FROM指令添加AS名称来为新的构建阶段指定名称。该名称可以在随后的FROM和COPY-FROM=<name>指令中使用,以引用在此阶段中构建的映像。

4)补充事项

  • ARG是Dockerfile中唯一可以在FROM之前的指令。请参阅了解ARG和FROM如何交互。
  • FROM可以在一个Dockerfile中多次出现,以创建多个映像或将一个构建阶段用作另一个构建的依赖项。只需在每个新的FROM指令之前记录提交输出的最后一个镜像ID。
  • 每个FROM指令都会清除先前指令创建的任何状态。

5.2  ARG指令

  • ARG定义一个参量。
  • ARG定义参量为可以用于FROM语句。
  • 通过在docker build语句加 --build-arg <varname>=<value>选项将参量带入Dockerfile中。

5.2.1 ARG语法:

ARG <name>[=<default value>]

        ARG 指令定义了一个变量,用户可以在构建时使用 --build-arg <varname>=<value> 标志使用 docker build 命令将其传递给构建器。在 Dockerfile 中,构建会输出警告。

[Warning] One or more build-args [foo] were not consumed.

        一个 Dockerfile 可能包含一个或多个 ARG 指令。例如,以下是一个有效的 Dockerfile:

FROM busybox
ARG user1
ARG buildno

5.2.2 参考 ARG和FROM 交互

FROM 指令支持由出现在第一个 FROM 之前的任何 ARG 指令声明的变量。

ARG  CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD  /code/run-app

FROM extras:${CODE_VERSION}
CMD  /code/run-extras

        在 FROM 之前声明的 ARG 在构建阶段之外,因此它不能在 FROM 之后的任何指令中使用。构建阶段:

ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version

 5.2.3 参数 ARG和build带入

        通过在docker build语句加 --build-arg <varname>=<value>选项将参量带入后,将刷新dockerfile定义的varname的值。 

示例:编写两句话的dockerfile有

ARG us=sss
RUN echo $us

        采用编译指令:docker build -t myImage:1.0 .

输出sss

         采用编译指令:docker build --build-arg=yyy -t myImage:1.0 .

输出yyy

5.3 MAITAINER

        维护者标记,现已弃用,目前用LABEL替换。LABEL优点是:新制造的镜像中、他的容器中,都可以看到作者。

  • 语法:
MAINTAINER <name>

        MAINTAINER 指令设置生成图像的 Author 字段。LABEL 指令是一个更灵活的版本,您应该使用它,因为它可以设置您需要的任何元数据,并且可以轻松查看,例如使用 docker inspect要设置与 MAINTAINER 字段对应的标签,您可以使用:

LABEL org.opencontainers.image.authors="SvenDowideit@home.org.au"

        这将在 docker inspect 中与其他标签一起可见。

5.4  RUN指令

  • RUN是制作镜像过程中shell指令的执行环节。
  • 指令将在当前镜像之上的新层中执行任何命令并提交结果。也就是每个RUN语句就加一层。

5.4.1 语法格式:

  • RUN <command> (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)
  • RUN ["executable", "param1", "param2"] (exec form)

5.4.2 注意点:

  • exec 形式可以避免 shell 字符串修改,并使用不包含指定 shell 可执行文件的基本映像运行命令。
  • 可以使用 SHELL 命令更改 shell 形式的默认 shell。
  • 在 shell 形式中,您可以使用(反斜杠)将单个 RUN 指令继续到下一行。例如,考虑这两行:
RUN /bin/bash -c 'source $HOME/.bashrc && \
echo $HOME'

        上面可以合并成下列行:

RUN /bin/bash -c 'source $HOME/.bashrc && echo $HOME'

 5.4.3 RUN的exec格式

        要使用除“/bin/sh”之外的其他 shell,请使用传入所需 shell 的 exec 形式。

RUN ["/bin/bash", "-c", "echo hello"]

5.5 ENV 环境参量宏替换

        环境变量(用 ENV 语句声明),可以在某些指令中由 Dockerfile 解释的变量。类似于编译中的宏替换。

        使用环境变量时,在用 $variable_name 或 ${variable_name} ,编译时用值替换之。

        ${variable_name} 语法还支持一些标准的 bash 修饰符,如下所示:

  •         ${variable:-word} :表示如果variable被赋值,那么结果将是哪个值;如果variable未赋值,结果不是空,而是默认值word。
  •         ${variable:+word} 表示如果variable被赋值了,则结果为word,否则如未赋值结果为空字符串。

        在所有情况下,该词可以是任何字符串,包括其他环境变量。

        通过在变量前添加 \ 可以进行转义:例如,\$foo 或 \${foo} 将分别转换为 $foo 和 ${foo} 文字。

        4 示例(解析后的表示形式显示在 # 之后): 

FROM busybox
ENV FOO=/bar
WORKDIR ${FOO}   # WORKDIR /bar
ADD . $FOO       # ADD . /bar
COPY \$FOO /quux # COPY $FOO /quux

5.6 WORKDIR指令

        该指令指出image当前工作目录是哪个(注意不是指宿主机上的路径)。

        WORKDIR 指令为 Dockerfile 中跟在它后面的任何 RUN、CMD、ENTRYPOINT、COPY 和 ADD 指令设置工作目录。

5.6.1 语法:

WORKDIR /path/to/workdir

5.6.2 WORKDIR指令在一个Dockerfile中可以多次使用

如果提供相对路径,则相对于上一条WORKDIR指令的路径。

WORKDIR /a    绝对路径
WORKDIR b     相对路径
WORKDIR c     相对路径
RUN pwd

        此 Dockerfile 中最后一个 pwd 命令的输出将是 /a/b/c。

5.6.3 隐式表示  

        WORKDIR 指令可以解析先前使用 ENV 设置的环境变量。您只能使用在 Dockerfile 中显式设置的环境变量。

ENV DIRPATH=/path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd

        这个 Dockerfile 中最后一个 pwd 命令的输出将是 /path/$DIRNAME

        如果未指定,则默认工作目录为 /。实际上,如果您不是从头开始构建 Dockerfile (FROM scratch),则 WORKDIR 可能由您使用的基础映像设置。

        因此,为避免在未知目录中进行意外操作,最好明确设置您的 WORKDIR。

 5.7 USER指令

  • 设置镜像操作的人员和组。
  • 这和后边的权限管理相关。

5.7.1 语法

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

5.7.2 注意事项 

        USER 指令设置用户名(或 UID)和可选的用户组(或 GID)以用作当前阶段剩余部分的默认用户和组。指定的用户用于 RUN 指令,并在运行时运行相关的 ENTRYPOINT 和 CMD 命令。

请注意,为用户指定群组时,用户将只有指定的群组成员资格。

警告

当用户没有主要组时,镜像(或下一条指令)将与根组一起运行。在 Windows 上,如果用户不是内置帐户,则必须先创建它。

FROM microsoft/windowsservercore
# Create Windows user in the container
RUN net user /add patrick
# Set it for subsequent commands
USER patrick

5.8 COPY指令

        是指文件从宿主机拷贝到制作中容器的过程。

5.8.1 COPY 的两种格式 

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

5.8.2 COPY 的解释

  • COPY 指令从 <src> 复制新文件或目录,并将它们添加到容器的文件系统路径 <dest> 中。
  • 采用两种格式的原因是:有些路径是在win10是有空格的,包含空格的路径需要后一种形式。
  • [--chown=<user>:<group>]是对操作追加操作权限。
  • --chown 仅在用于构建 Linux 容器的 Dockerfile 上受支持,在 Windows 容器上不起作用。将用户名和组名转换为 ID 限制此功能仅适用于基于 Linux 操作系统的容器。
  • 可以指定多个 <src> 资源,但文件和目录的路径将被解释为相对于构建上下文的源。
  • 每个 <src> 可能包含通配符。

5.8.3 通配符举例

  •  添加以“hom”开头的所有文件:
    COPY hom* /mydir/
  • 在下面的示例中,? 被替换为任何单个字符,例如“home.txt”。
    COPY hom?.txt /mydir/
  • <dest> 是绝对路径,或相对于 WORKDIR 的路径,源将被复制到目标容器内。
  • 下面的示例使用相对路径,并将“test.txt”添加到 <WORKDIR>/relativeDir/:
COPY test.txt relativeDir/

        而此示例使用绝对路径,并将“test.txt”添加到 /absoluteDir/

COPY test.txt /absoluteDir/

        当复制包含特殊字符(如[和])的文件或目录时,需要按照Golang规则对那些路径进行转义,防止它们被当作匹配模式。.txt,使用如下;

COPY arr[[]0].txt /mydir/

        所有新文件和目录都使用 0 的 UID 和 GID 创建,除非可选的 --chown 标志指定给定的用户名、组名或 UID/GID 组合以请求复制内容的特定所有权。标志允许用户名和组名字符串或直接整数 UID 和 GID 的任意组合。提供不带组名的用户名或不带 GID 的 UID 将使用与 GID 相同的数字 UID。/etc/passwd 和 /etc/group 文件将用于从名称执行转换分别为整数 UID 或 GID。

5.8.4 权限举例

COPY --chown=55:mygroup files* /somedir/
COPY --chown=bin files* /somedir/
COPY --chown=1 files* /somedir/
COPY --chown=10:11 files* /somedir/

        如果容器根文件系统不包含 /etc/passwd 或 /etc/group 文件,并且在 --chown 标志中使用了用户名或组名,则构建将在 COPY 操作中失败。

5.9 ADD指令

  •  ADD基本实现COPY指令。
  • ADD不仅拷贝文件,而且将.tar等文件解压成镜像内目录和文件。
  •  ADD 指令从 <src> 复制新文件、目录或远程文件 URL,并将它们添加到镜像的文件系统路径 <dest> 中。

5.9.1 ADD有两个格式 

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

( 包含空格的路径需要后一种形式)

注意

--chown 仅在用于构建 Linux 容器的 Dockerfile 上受支持,在 Windows 容器上不起作用。将用户名和组名转换为 ID 限制此功能仅适用于基于 Linux 操作系统的容器。

        可以指定多个 <src> 资源,但如果它们是文件或目录,它们的路径将被解释为相对于构建上下文的源。

5.9.2 通配符使用

添加以“hom”开头的所有文件:

ADD hom* /mydir/

在下面的示例中,? 被替换为任何单个字符,例如“home.txt”。

ADD hom?.txt /mydir/

5.9.3 关于路径

         <dest> 是绝对路径,或相对于 WORKDIR 的路径,源将被复制到目标容器内。下面的示例使用相对路径,并将“test.txt”添加到 <WORKDIR>/relativeDir/:

ADD test.txt relativeDir/

        而此示例使用绝对路径,并将“test.txt”添加到 /absoluteDir/

ADD test.txt /absoluteDir/

        在添加包含特殊字符(如[和])的文件或目录时,需要按照Golang规则对这些路径进行转义,防止它们被视为匹配模式。例如添加名为arr[0]的文件.txt,使用以下内容;

ADD arr[[]0].txt /mydir/

5.9.4 关于带权限追加文件、目录

        所有新文件和目录都使用 0 的 UID 和 GID 创建,除非可选的 --chown 标志指定给定的用户名、组名或 UID/GID 组合以请求添加内容的特定所有权。标志允许用户名和组名字符串或直接整数 UID 和 GID 的任意组合。提供不带组名的用户名或不带 GID 的 UID 将使用与 GID 相同的数字 UID。/etc/passwd 和 /etc/group 文件将用于从名称执行转换分别为整数 UID 或 GID。

ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/

        如果容器根文件系统不包含 /etc/passwd 或 /etc/group 文件,并且在 --chown 标志中使用了用户名或组名,则构建将在 ADD 操作上失败。使用数字 ID 不需要查找和将不依赖于容器根文件系统内容。

5.10 EXPOSE语句

  • 是专门对网络访问提供端口暴露。
  • EXPOSE指令通知Docker容器在运行时监听指定的网络端口,可以指定端口监听TCP还是UDP,不指定协议默认为TCP。

5.10.1 语法 

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

5.10.2 端口发布       

        EXPOSE 指令实际上并没有发布端口。它的作用是构建镜像的人和运行容器的人之间的一种文档,关于哪些端口打算发布。在 docker run 上使用 -pflag 来发布并映射一个或多个端口,或 -P 标志以发布所有暴露的端口并将它们映射到高阶端口。

        默认情况下,EXPOSE 假定 TCP。

EXPOSE 80/udp

要在 TCP 和 UDP 上公开,请包括两行:

EXPOSE 80/tcp
EXPOSE 80/udp

        在这种情况下,如果您将 -P 与 docker run 一起使用,端口将为 TCP 公开一次,为 UDP 公开一次。请记住,-P 在主机上使用临时高阶主机端口,因此端口不会相同用于 TCP 和 UDP。

        无论 EXPOSE 设置如何,您都可以在运行时使用 -p 标志覆盖它们。

$ docker run -p 80:80/tcp -p 80:80/udp ...

        要在主机系统上设置端口重定向,请参阅使用 -P 标志。docker network 命令支持为容器之间的通信创建网络,而无需公开或发布特定端口,因为连接到网络的容器可以相互通信通过任何端口。有关详细信息,请参阅此功能的概述。

5.11 CMD指令

5.11.1 CMD指令的三个格式:

  • CMD ["executable","param1","param2"] (exec form, this is the preferred form)
  • CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
  • CMD command param1 param2 (shell form)

        一个Dockerfile中只能有一条CMD指令,如果列出多个CMD则只有最后一条CMD生效。CMD 的主要目的是为正在执行的容器提供默认值。

        如果使用 CMD 为 ENTRYPOINT 指令提供默认参数,则 CMD 和 ENTRYPOINT 指令都应使用 JSON 数组格式指定。

Note

exec 格式被解析为 JSON 数组,这意味着您必须在单词周围使用双引号 (“) 而不是单引号 (‘)。

        与 shell 形式不同,exec 形式不调用命令 shell。这意味着正常的 shell 处理不会发生。例如,CMD [ "echo", "$HOME" ] 不会对 $HOME 进行变量替换。want shell处理然后使用shell形式或直接执行shell,例如:CMD [“sh”,“-c”,“echo $HOME”]。对于shell形式,是shell在做环境变量扩展,而不是 docker。

5.11.2 CMD指令举例

        当以 shell 或 exec 格式使用时,CMD 指令设置运行图像时要执行的命令。如果您使用 CMD 的 shell 形式,那么 <command> 将在 /bin/sh -c 中执行:

FROM ubuntu
CMD echo "This is a test." | wc -

        如果你想在没有 shell 的情况下运行你的 <command> 那么你必须将命令表示为 JSON 数组并给出可执行文件的完整路径。这种数组形式是 CMD 的首选格式。任何附加参数必须单独表示为字符串在数组中:

FROM ubuntu
CMD ["/usr/bin/wc","--help"]

        如果您希望您的容器每次都运行相同的可执行文件,那么您应该考虑将 ENTRYPOINT 与 CMD 结合使用。

        如果用户为 docker run 指定参数,那么他们将覆盖 CMD 中指定的默认值。

Note

        不要将 RUN 与 CMD 混淆。RUN 实际上运行一个命令并提交结果;CMD 在构建时不执行任何操作,而是为图像指定预期的命令。

5.12 VOLUME语句

        VOLUME 指令创建一个具有指定名称的挂载点,并将其标记为持有来自本机主机或其他容器的外部挂载卷。

5.12.1 语法格式

VOLUME ["/data"]

       多个参数,例如 VOLUME /var/log 或 VOLUME /var/log /var/db。有关更多信息/示例和通过 Docker 客户端安装说明,请参阅通过卷文档共享目录。

        docker run 命令使用基础映像中指定位置存在的任何数据初始化新创建的卷。例如,考虑以下 Dockerfile 片段:

FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol

        这个 Dockerfile 生成一个镜像像,使 docker run 在 /myvol 上创建一个新的挂载点,并将greeting文件复制到新创建的卷中。

5.12.2 关于指定卷的注意事项

        请记住以下有关 Dockerfile 中的卷的事项。

  • 基于 Windows 的容器上的卷:使用基于 Windows 的容器时,容器内卷的目的地必须是以下之一:
  • 一个不存在的或空的目录
  • C 以外的驱动器:
  • 从 Dockerfile 中更改卷:如果任何构建步骤在声明卷后更改卷中的数据,这些更改将被丢弃。
  • JSON 格式:列表被解析为 JSON 数组。您必须用双引号 (") 而不是单引号 (') 将单词括起来。
  • 主机目录在容器运行时声明:主机目录(挂载点)本质上是依赖于主机的。这是为了保持镜像的可移植性,因为给定的主机目录不能保证在所有平台上都可用因此,您不能从 Dockerfile 中挂载主机目录。VOLUME 指令不支持指定主机目录参数。
PS E:\myproject> docker build -t cmd .

Sending build context to Docker daemon 3.072 kB
Step 1/2 : FROM microsoft/nanoserver
 ---> 22738ff49c6d
Step 2/2 : COPY testfile.txt c:\RUN dir c:
GetFileAttributesEx c:RUN: The system cannot find the file specified.
PS E:\myproject>

5.13 ENTRYPOINT指令

  • ENTRYPOINT和CMD有共同点,那就是都为镜像所派生的容器指定首个执行进程。
  • ENTRYPOINT 允许您配置将作为可执行文件运行的容器。
  • 只有 Dockerfile 中的最后一条 ENTRYPOINT 指令才会起作用。

5.13.1 ENTRYPOINT的两种格式:

1)exec 格式:

ENTRYPOINT ["executable", "param1", "param2"]

2)shell 格式:

ENTRYPOINT command param1 param2


5.13.2 举例说明

例如,下面以默认内容启动 nginx,监听端口 80:

$ docker run -i -t --rm -p 80:80 nginx

        docker run <image> 的命令行参数将附加在 exec 表单 ENTRYPOINT 中的所有元素之后,并将覆盖使用 CMD 指定的所有元素。这允许将参数传递到入口点,即 docker run <image> -d会将 -d 参数传递给入口点。

        您可以使用 docker run --entrypoint 标志覆盖 ENTRYPOINT 指令。

        shell 形式阻止使用任何 CMD 或运行命令行参数,但缺点是您的 ENTRYPOINT 将作为 /bin/sh -c 的子命令启动,它不传递信号。容器的 PID 1 - 并且不会接收 Unix 信号 - 因此您的可执行文件不会从 docker stop <container> 接收 SIGTERM。

5.13.3 举例说明

        Exec形式的 ENTRYPOINT 示例

        您可以使用 ENTRYPOINT 的 exec 形式设置相当稳定的默认命令和参数,然后使用任一形式的 CMD 设置更可能更改的其他默认值。

FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]

        当您运行容器时,您可以看到 top 是唯一的进程:

$ docker run -it --rm --name test  top -H

top - 08:25:00 up  7:27,  0 users,  load average: 0.00, 0.01, 0.05
Threads:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.1 us,  0.1 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:   2056668 total,  1616832 used,   439836 free,    99352 buffers
KiB Swap:  1441840 total,        0 used,  1441840 free.  1324440 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
    1 root      20   0   19744   2336   2080 R  0.0  0.1   0:00.04 top

要进一步检查结果,您可以使用 docker exec:

$ docker exec -it test ps aux

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  2.6  0.1  19752  2352 ?        Ss+  08:24   0:00 top -b -H
root         7  0.0  0.1  15572  2164 ?        R+   08:25   0:00 ps aux

您可以使用 docker stop test 优雅地请求 top 关闭。

以下 Dockerfile 显示使用 ENTRYPOINT 在前台运行 Apache(即作为 PID 1):

FROM debian:stable
RUN apt-get update && apt-get install -y --force-yes apache2
EXPOSE 80 443
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

        如果您需要为单个可执行文件编写启动脚本,您可以使用 exec 和 gosu 命令确保最终可执行文件接收 Unix 信号:

#!/usr/bin/env bash
set -e

if [ "$1" = 'postgres' ]; then
    chown -R postgres "$PGDATA"

    if [ -z "$(ls -A "$PGDATA")" ]; then
        gosu postgres initdb
    fi

    exec gosu postgres "$@"
fi

exec "$@"

        最后,如果您需要在关闭时做一些额外的清理(或与其他容器通信),或者协调多个可执行文件,您可能需要确保 ENTRYPOINT 脚本接收 Unix 信号,传递它们,然后做更多的工作:

#!/bin/sh
# Note: I've written this using sh so it works in the busybox container too

# USE the trap if you need to also do manual cleanup after the service is stopped,
#     or need to start multiple services in the one container
trap "echo TRAPed signal" HUP INT QUIT TERM

# start service in background here
/usr/sbin/apachectl start

echo "[hit enter key to exit] or run 'docker stop <container>'"
read

# stop service and clean up here
echo "stopping apache"
/usr/sbin/apachectl stop

echo "exited $0"

5.14  关于.dockerignore 文件

        在 docker CLI 将上下文发送到 docker 守护程序之前,它会在上下文的根目录中查找名为 .dockerignore 的文件。如果此文件存在,CLI 会修改上下文以排除与其中的模式匹配的文件和目录。帮助以避免不必要地向守护进程发送大的或敏感的文件和目录,并可能使用 ADD 或 COPY 将它们添加到图像中。

        CLI 将 .dockerignore 文件解释为以换行符分隔的模式列表,类似于 Unix shell 的文件 glob。为了匹配的目的,上下文的根被认为是工作目录和根目录。例如,模式 /foo/bar 和 foo/barboth 都排除了 PATH 的 foo 子目录或位于 URL 的 git 存储库的根目录中名为 bar 的文件或目录。两者都不排除任何其他内容。

        如果 .dockerignore 文件中的一行在第 1 列中以# 开头,则该行将被视为注释并在被 CLI 解释之前被忽略。

        这是一个示例 .dockerignore 文件:

# comment
*/temp*
*/*/temp*
temp?

        此文件导致以下构建行为:

RuleBehavior
# comment忽略.

*/temp*

排除根的任何直接子目录中名称以 temp 开头的文件和目录。例如,排除普通文件 /somedir/temporary.txt,目录 /somedir/temp。

*/*/temp*

从根以下两级的任何子目录中排除以 temp 开头的文件和目录。

temp?

排除根目录中名称为 temp 一个字符扩展名的文件和目录。

六、后记

        本篇对官方文档进行一次瘦身,对于一般的Image生成已经足够。但是对于更“大腕”级别的应用,恐怕依然需要参考官网。本文的另一个特色,是首先给出hello-world的制作过程,后边指令都可以在hello-world基础上实验。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无水先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值