在Docker系列第三部分的翻译中,我们将继续受到糕点(即百吉饼)的启发。 今天我们的主要主题是使用Dockerfiles。 我们将分析这些文件中使用的说明。
→
第1部分:基础知识→
第2部分:术语和概念→
第3部分:Dockerfile文件→
第4部分:缩小图像尺寸并加快其组装速度→
第5部分:团队→
第6部分:处理数据百吉饼是Dockerfile中的指令。Docker映像
回想一下,Docker容器是栩栩如生的Docker映像。 这是一个独立的操作系统,其中只有最必要的应用程序代码。
Docker映像是构建过程的结果,而Docker容器正在运行映像。 Docker的核心是Dockerfiles。 这样的文件告诉Docker如何组装从中创建容器的映像。
每个Docker映像都有一个名为Dockerfile的文件。 他的名字是这样写的-无需扩展名。 当您运行
docker build
创建新映像时,假定Dockerfile位于当前工作目录中。 如果此文件位于其他位置,则可以使用
-f
标志指定其位置。
正如我们在本系列的第一种材料中发现的那样,容器由层组成。 除最后一层外,其他各层中的每一层都是只读的。 Dockerfile告诉Docker系统将哪些层以及添加到映像的顺序。
实际上,每一层只是一个文件,它描述了图像状态与添加前一层后的状态相比所发生的变化。 顺便说一下,在Unix上,几乎所有东西都是
文件 。
基本图像是要创建的图像的源层。 基本图像也称为父图像。
基本映像是Docker映像的开始位置。将映像从远程存储库下载到本地计算机时,仅物理下载该计算机上不可用的图层。 Docker旨在通过重用现有层来节省空间和时间。
Dockerfile文件
Dockerfile包含用于创建映像的说明。 该文件的行以大写字母开头。 遵循指示是他们的论点。 建立图像时,说明从上到下进行处理。 看起来是这样的:
FROM ubuntu:18.04 COPY . /app
最终图像中的图层仅由
FROM
,
RUN
,
COPY
和
ADD
指令创建。 其他指令设置,描述元数据或告诉Docker您需要在容器执行期间执行某些操作,例如,打开某些端口或运行某些命令。
在这里,我们假设使用基于Unix操作系统的Docker镜像。 当然,在这里您也可以使用基于Windows的映像,但是使用Windows是一种较不常见的做法,使用此类映像更加困难。 因此,如果有机会,请使用Unix。
首先,这里是Dockerfile指令列表和简短注释。
十二个Dockerfile指令
FROM
设置基本(父)图像。LABEL
-描述元数据。 例如,有关谁创建和维护图像的信息。ENV
设置持久性环境变量。RUN
执行命令并创建图像层。 用于将软件包安装在容器中。COPY
文件和文件夹复制到容器中。ADD
文件和文件夹复制到容器中,可以解压缩本地.tar文件。CMD
描述带有启动容器时需要执行的参数的命令。 容器启动时可以覆盖参数。 一个文件只能包含一个CMD
指令。WORKDIR
设置下一条指令的工作目录。ARG
设置变量以在映像构建期间传递Docker。ENTRYPOINT
为命令提供带有在容器执行期间调用的参数的命令。 参数不被覆盖。EXPOSE
表示需要打开端口。VOLUME
创建用于持久存储的安装点。
现在让我们谈谈这些指示。
说明和使用示例
▍简单的Dockerfile
Dockerfile可能非常简单且简短。 例如-这样:
FROM ubuntu:18.04
▍从指导
Dockerfile必须以
FROM
语句开头,或者以
ARG
语句后接
FROM
语句开头。
FROM关键字告诉Docker在构建映像时使用与提供的名称和标记匹配的基本映像。 此外,基本图像也称为
父图像 。
在此示例中,基本映像存储在
ubuntu存储库中。 Ubuntu是官方Docker存储库的名称,该存储库提供了流行的Linux操作系统系列(称为Ubuntu)的基本版本。
请注意,所讨论的Dockerfile包含一个
18.04
标签,用于指定我们需要的基本映像。 构建映像时将加载此映像。 如果指令中未包含该标记,则Docker将从需要存储库中的最新映像的假设出发。 为了更清楚地表达他们的意图,建议Dockerfile作者指出所需的映像。
首次在本地计算机上使用上述Dockerfile生成映像时,Docker将加载
ubuntu
映像定义的层。 可以想象它们彼此重叠。 每个下一层是一个文件,描述了与将上一层添加到图像后的状态相比图像的差异。
创建容器时,可以在其中进行更改的图层会添加到所有其他图层的顶部。 其余层中的数据只能读取。
容器结构(摘自文档 )出于效率考虑,Docker使用写时复制策略。 如果映像中的层位于上一层,并且某层需要从中读取数据,则Docker将使用现有文件。 您无需下载任何内容。
执行图像时,如果需要通过容器修改图层,则将相应的文件复制到最顶层的可变图层。 要了解有关写时复制策略的更多信息,请阅读Docker文档中的该资料。
我们将继续讨论Dockerfile中使用的指令,并给出具有更复杂结构的此类文件的示例。
▍更复杂的dockerfile
尽管我们刚刚回顾的Dockerfile看起来很整洁并且可以理解,但是它太简单了,它仅使用一条指令。 另外,在容器执行期间没有调用任何指令。 看一下另一个收集小图像的文件。 它具有确定在容器执行期间调用的命令的机制。
FROM python:3.7.2-alpine3.8 LABEL maintainer="jeffmshale@gmail.com" ENV ADMIN="jeff" RUN apk update && apk upgrade && apk add bash COPY . ./app ADD https://raw.githubusercontent.com/discdiver/pachy-vid/master/sample_vids/vid1.mp4 \ /my_app_directory RUN ["mkdir", "/a_directory"] CMD ["python", "./my_script.py"]
乍一看,此文件可能看起来很复杂。 因此,让我们对付他。
该图像的基础是带有标签3.7.2-alpine3.8的官方Python图像。 在分析了
这段代码之后,您可以看到该基本映像包括Linux,Python,并且总体而言,它仅限于其组成。 Alpine OS映像在Docker世界中非常流行。 它们体积小,速度快,安全性高。 但是,Alpine映像在常规操作系统通常具有的广泛功能上没有差异。 因此,为了基于这种图像收集有用的东西,图像的创建者需要安装他需要的软件包。
LA说明标签
标签LABEL语句 (标签)允许您将元数据添加到图像。 对于现在正在考虑的文件,它包括图像创建者的联系信息。 声明标签不会减慢图像组装过程或增加其大小。 它们仅包含有关Docker映像的有用信息,因此建议将它们包含在文件中。 可以在
此处找到有关在Dockerfile中使用元数据的详细信息。
▍Inv指令
环境环境ENV指令允许您设置常量环境变量,该变量将在容器执行期间在容器中可用。 在上一个示例中,在创建容器之后,可以使用
ADMIN
变量。
ENV
指令非常适合设置常量。 如果您多次在Dockerfile中使用某个值,例如,当描述在容器中执行的命令时,怀疑您可能有朝一日必须将其更改为另一个值,则可以将其写入类似的常量。
应该注意的是,在Dockerfile文件中,通常有不同的方法来解决相同的问题。 确切使用的是一个问题,该问题的决定取决于遵守Docker环境中采用的工作方法的愿望,以确保解决方案的透明度及其高性能。 例如,
RUN
,
CMD
和
ENTRYPOINT
具有不同的用途,但它们均用于执行命令。
▍RUN指令
RUN指令RUN指令允许您在映像构建过程中创建一个图层。 执行后,将新层添加到图像,其状态是固定的。
RUN
指令通常用于在映像中安装其他软件包。 在前面的示例中,
RUN apk update && apk upgrade
语句告诉Docker系统需要从基本映像更新软件包。 在这两个命令之后是
&& apk add bash
命令,指示需要在映像中安装bash。
团队中的
apk
看起来是
Alpine Linux软件包管理器的缩写。 如果使用的是其他Linux家族操作系统的基础映像,则例如,在使用Ubuntu时,可能需要使用
RUN apt-get
形式的命令来安装软件包。 稍后我们将讨论其他安装软件包的方法。
可以以exec形式或shell形式使用
RUN
指令和类似的指令,例如
CMD
和
ENTRYPOINT
。 exec表单使用的语法类似于JSON数组的描述。 例如,它可能看起来像这样:
RUN ["my_executable", "my_first_param1", "my_second_param2"]
。
在前面的示例中,我们使用了RUN指令的shell形式,如下所示:
RUN apk update && apk upgrade && apk add bash
。
稍后在Dockerfile中,我们以
RUN ["mkdir", "/a_directory"]
的形式使用
RUN
指令的exec形式来创建目录。 同时,使用这种形式的说明,您需要记住需要使用双引号对字符串进行格式化,这是JSON格式中常见的做法。
▍说明书COPY
COPY指令COPY指令在我们的文件中显示如下:
COPY . ./app
COPY . ./app
。 她告诉Docker,她需要从程序集的本地上下文中获取文件和文件夹,并将它们添加到映像的当前工作目录中。 如果目标目录不存在,则此指令将创建它。
▍说明添加
ADD指令使您可以解决与
COPY
相同的问题,但是还有更多用
COPY
与之关联。 因此,使用此说明,您可以将从远程源下载的文件添加到容器中,也可以解压缩本地.tar文件。
在此示例中,使用
ADD
指令将可访问URL的文件复制到
my_app_directory
容器
my_app_directory
。 但是,应注意的是,
Docker文档不建议使用通过URL获得的此类文件,因为它们无法删除,并且会增加映像的大小。
此外,
文档建议尽可能使用
COPY
语句而不是
ADD
语句来使Dockerfile易于理解。 我相信Docker开发团队应该将
ADD
和
COPY
合并为一条指令,这样创建映像的人就不必记住太多指令。
请注意,
ADD
语句包含换行符-
\
。 通过将这些字符分成几行,可以使用它们来提高长命令的可读性。
MD CMD指令
CMD指令CMD指令为Docker提供了一个在容器启动时执行的命令。 该命令的结果不会在组装过程中添加到映像中。 在我们的示例中,此命令在运行时启动
my_script.py
脚本。
您还需要了解有关
CMD
指令的其他信息:
- 一个Dockerfile中只能存在一个
CMD
指令。 如果文件中有多个这样的指令,则系统将忽略除最后一条以外的所有内容。 CMD
指令可能具有exec形式。 如果指令不包含对可执行文件的引用,则ENTRYPOINT
指令必须存在于文件中。 在这种情况下,这两个指令都必须为JSON
。- 传递给
docker run
的命令行参数将覆盖Dockerfile中CMD
语句提供的参数。
▍更复杂的Dockerfile
考虑另一个Dockerfile,其中将使用一些新命令。
FROM python:3.7.2-alpine3.8 LABEL maintainer="jeffmshale@gmail.com" # RUN apk add --update git # WORKDIR /usr/src/my_app_directory # COPY . . # ARG my_var=my_default_value # , ENTRYPOINT ["python", "./app/my_script.py", "my_var"] # EXPOSE 8000 # VOLUME /my_volume
在此示例中,除其他外,您可以看到以
#
字符开头的注释。
Dockerfile的主要功能之一就是安装软件包。 如前所述,有多种使用
RUN
指令安装软件包的方法。
可以使用
apk
安装Alpine Docker映像中的软件包。 为此,我们已经说过,使用了
RUN apk update && apk upgrade && apk add bash
格式的命令。
此外,可以使用
pip ,
wheel和
conda安装映像中的Python软件包。 如果我们不是在谈论Python,而是在谈论其他编程语言,则可以使用其他程序包管理器来准备相应的图像。
同时,为了使安装成为可能,底层必须为软件包管理器提供合适的软件包管理器。 因此,如果在安装软件包时遇到问题,请在尝试使用软件包管理器之前确保已安装了软件包管理器。
例如,您可以在Dockerfile中使用
RUN
语句使用
pip
安装软件包列表。 如果执行此操作,请将所有命令合并为一条指令,并使用
\
字符将其与换行符分隔。 由于采用了这种方法,文件看起来会很整洁,这将导致与使用多个
RUN
指令添加的图层相比,向映像添加的图层更少。
此外,您可以执行其他操作来安装多个软件包。 您可以将它们列出在文件中,然后使用
RUN
将此文件传输到软件包管理器。 通常,这些文件称为
requirements.txt
。
RK WORKDIR说明
工作目录WORKDIR指令允许
您更改容器的工作目录。 该目录下跟随
WORKDIR
的
COPY
,
ADD
,
RUN
,
CMD
和
ENTRYPOINT
。 以下是与此指令相关的一些功能:
- 最好使用
WORKDIR
设置文件夹的绝对路径,而不是使用Dockerfile中的cd
命令浏览文件系统。 - 如果该目录不存在,
WORKDIR
指令会自动创建一个目录。 - 您可以使用一些
WORKDIR
指令。 如果提供了相对于此类指令的说明,则它们各自都会更改当前工作目录。
▍指南ARG
ARG指令允许您设置一个变量,该变量的值可以在汇编期间从命令行传递到映像。 默认变量的值可以在Dockerfile中表示。 例如:
ARG my_var=my_default_value
。
与
ENV
变量不同,
ARG
变量在运行时不可用。 但是,
ARG
变量可用于在映像构建过程中从命令行设置
ENV
变量的默认值。 在容器执行期间,
ENV
变量将已经在容器中可用。 可以在
这里找到有关使用变量的技术的详细信息。
说明ENTRYPOINT
过渡到某个地方ENTRYPOINT语句使
您可以指定带有参数的命令,该命令应在容器启动时执行。 它与
CMD
命令相似,但是如果使用命令行参数启动容器,则
ENTRYPOINT
中指定的参数不会被覆盖。
而是将在
docker run my_image_name
形式的构造中传递的命令行参数添加到
ENTRYPOINT
指定的参数中。 例如,执行了
docker run my_image bash
形式的命令后
docker run my_image bash
参数将添加到
ENTRYPOINT
指定的参数列表的
ENTRYPOINT
。 准备Dockerfile时,请不要忘记
CMD
或
ENTRYPOINT
。
Docker文档中有一些建议,涉及在容器启动时应选择哪种指令
CMD
或
ENTRYPOINT
作为执行命令的工具:
- 如果您每次启动容器都需要运行相同的命令,请使用
ENTRYPOINT
。 - 如果该容器将用作应用程序,请使用
ENTRYPOINT
。 - 如果您知道启动容器时需要向其传递可以覆盖Dockerfile中指定的参数的参数,请使用
CMD
。
在我们的示例中,使用
ENTRYPOINT ["python", "my_script.py", "my_var"]
指令
ENTRYPOINT ["python", "my_script.py", "my_var"]
使容器在启动时以参数
my_var
运行Python脚本
my_script.py
。 然后,可以使用
argparse在脚本中使用
my_var
表示的值。 , Dockerfile
my_var
, ,
ARG
. , , .
Docker exec-
ENTRYPOINT
:
ENTRYPOINT ["executable", "param1", "param2"]
.
▍ EXPOSE
EXPOSEEXPOSE , , . . , , , , , , .
( ) ,
docker run
-p
.
-P
(
P
), ,
EXPOSE
.
▍ VOLUME
VOLUMEVOLUME , . .
总结
, Dockerfile. . , ,
USER
,
ONBUILD
,
STOPSIGNAL
,
SHELL
HEALTHCHECK
.
Dockerfile.
, Dockerfile — Docker, , . , .
亲爱的读者们! Docker , , Docker-.
