在本文中,您将会了解到关于DockerfileRUN,CMD&ENTRYPOINT的新资讯,并给出一些关于dockerRUNCMDENTRYPOINT区别、DockerRUNvsCMDvsENTRYP
在本文中,您将会了解到关于Dockerfile RUN, CMD & ENTRYPOINT的新资讯,并给出一些关于docker RUN CMD ENTRYPOINT 区别、Docker RUN vs CMD vs ENTRYPOINT、Docker | dockerfile构建centos镜像,以及CMD和ENTRYPOINT的区别、Docker 中的 Dockerfile 命令详解 FROM RUN COPY ADD ENTRYPOINT...的实用技巧。
本文目录一览:- Dockerfile RUN, CMD & ENTRYPOINT
- docker RUN CMD ENTRYPOINT 区别
- Docker RUN vs CMD vs ENTRYPOINT
- Docker | dockerfile构建centos镜像,以及CMD和ENTRYPOINT的区别
- Docker 中的 Dockerfile 命令详解 FROM RUN COPY ADD ENTRYPOINT...
Dockerfile RUN, CMD & ENTRYPOINT
在使用 Dockerfile 创建 image 时,有几条指令比较容易混淆,RUN, CMD, ENTRYPOINT.
RUN 是在 building image 时会运行的指令,在 Dockerfile 中可以写多条 RUN 指令.
CMD 和 ENTRYPOINT 则是在运行 container 时会运行的指令,都只能写一条,如果写了多条,则最后一条生效.
CMD 和 ENTRYPOINT 的区别是:
CMD 在运行时会被 command 覆盖,ENTRYPOINT 不会被运行时的 command 覆盖,但是也可以指定.
例如 :
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
--entrypoint="" Overwrite the default entrypoint of the image
docker run postgres:9.3.5 psql
这里的 psql 就是 command, 将覆盖 Dockerfile 的 CMD, 但是不会覆盖 ENTRYPOINT.
如果要覆盖 ENTRYPOINT, 那么可以在 docker run 运行时输入 --entrypoint="....".
CMD 和 ENTRYPOINT 一般用于制作具备后台服务的 image, 例如 apache, database 等。在使用这种 image 启动 container 时,自动启动服务.
这几条指令的详细用法 :
RUN
RUN has 2 forms:
RUN <command>
(the command is run in a shell -/bin/sh -c
- shell form)RUN ["executable", "param1", "param2"]
(exec form)
The RUN
instruction will execute any commands in a new layer on top of the current image and commit the results. The resulting committed image will be used for the next step in the Dockerfile
.
Layering RUN
instructions and generating commits conforms to the core concepts of Docker where commits are cheap and containers can be created from any point in an image''s history, much like source control.
The exec form makes it possible to avoid shell string munging, and to RUN
commands using a base image that does not contain /bin/sh
.
Note: To use a different shell, other than ''/bin/sh'', use the exec form passing in the desired shell. For example,
RUN ["/bin/bash", "-c", "echo hello"]
Note: The exec form is parsed as a JSON array, which means that you must use double-quotes (") around words not single-quotes ('').
Note: Unlike the shell form, the exec form does not invoke a command shell. This means that normal shell processing does not happen. For example,
CMD [ "echo", "$HOME" ]
will not do variable substitution on$HOME
. If you want shell processing then either use the shell form or execute a shell directly, for example:CMD [ "sh", "-c", "echo", "$HOME" ]
.
The cache for RUN
instructions isn''t invalidated automatically during the next build. The cache for an instruction like RUN apt-get dist-upgrade -y
will be reused during the next build. The cache for RUN
instructions can be invalidated by using the --no-cache
flag, for example docker build --no-cache
.
See the Dockerfile
Best Practices guide for more information.
The cache for RUN
instructions can be invalidated by ADD
instructions. See below for details.
Known Issues (RUN)
- Issue 783 is about file permissions problems that can occur when using the AUFS file system. You might notice it during an attempt to
rm
a file, for example. The issue describes a workaround.
CMD
The CMD
instruction has three forms:
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)
There can only be one CMD
instruction in a Dockerfile
. If you list more than one CMD
then only the lastCMD
will take effect.
The main purpose of a CMD
is to provide defaults for an executing container. These defaults can include an executable, or they can omit the executable, in which case you must specify an ENTRYPOINT
instruction as well.
Note: If
CMD
is used to provide default arguments for theENTRYPOINT
instruction, both theCMD
andENTRYPOINT
instructions should be specified with the JSON array format.Note: The exec form is parsed as a JSON array, which means that you must use double-quotes (") around words not single-quotes ('').
Note: Unlike the shell form, the exec form does not invoke a command shell. This means that normal shell processing does not happen. For example,
CMD [ "echo", "$HOME" ]
will not do variable substitution on$HOME
. If you want shell processing then either use the shell form or execute a shell directly, for example:CMD [ "sh", "-c", "echo", "$HOME" ]
.
When used in the shell or exec formats, the CMD
instruction sets the command to be executed when running the image.
If you use the shell form of the CMD
, then the <command>
will execute in /bin/sh -c
:
FROM ubuntu
CMD echo "This is a test." | wc -
If you want to run your <command>
without a shell then you must express the command as a JSON array and give the full path to the executable. This array form is the preferred format of CMD
. Any additional parameters must be individually expressed as strings in the array:
FROM ubuntu
CMD ["/usr/bin/wc","--help"]
If you would like your container to run the same executable every time, then you should consider usingENTRYPOINT
in combination with CMD
. See ENTRYPOINT.
If the user specifies arguments to docker run
then they will override the default specified in CMD
.
Note: don''t confuse
RUN
withCMD
.RUN
actually runs a command and commits the result;CMD
does not execute anything at build time, but specifies the intended command for the image.
ENTRYPOINT
ENTRYPOINT has two forms:
ENTRYPOINT ["executable", "param1", "param2"]
(exec form, the preferred form)ENTRYPOINT command param1 param2
(shell form)
There can only be one ENTRYPOINT
in a Dockerfile
. If you have more than one ENTRYPOINT
, then only the last one in the Dockerfile
will have an effect.
An ENTRYPOINT
helps you to configure a container that you can run as an executable. That is, when you specify an ENTRYPOINT
, then the whole container runs as if it was just that executable.
Unlike the behavior of the CMD
instruction, The ENTRYPOINT
instruction adds an entry command that willnot be overwritten when arguments are passed to docker run
. This allows arguments to be passed to the entry point, i.e. docker run <image> -d
will pass the -d
argument to the entry point.
You can specify parameters either in the ENTRYPOINT
JSON array (as in "like an exec" above), or by using a CMD
instruction. Parameters in the ENTRYPOINT
instruction will not be overridden by the docker run
arguments, but parameters specified via a CMD
instruction will be overridden by docker run
arguments.
Like a CMD
, you can specify a plain string for the ENTRYPOINT
and it will execute in /bin/sh -c
:
FROM ubuntu
ENTRYPOINT ls -l
For example, that Dockerfile
''s image will always take a directory as an input and return a directory listing. If you wanted to make this optional but default, you could use a CMD
instruction:
FROM ubuntu
CMD ["-l"]
ENTRYPOINT ["ls"]
Note: The exec form is parsed as a JSON array, which means that you must use double-quotes (") around words not single-quotes ('').
Note: Unlike the shell form, the exec form does not invoke a command shell. This means that normal shell processing does not happen. For example,
CMD [ "echo", "$HOME" ]
will not do variable substitution on$HOME
. If you want shell processing then either use the shell form or execute a shell directly, for example:CMD [ "sh", "-c", "echo", "$HOME" ]
.Note: It is preferable to use the JSON array format for specifying
ENTRYPOINT
instructions.
docker RUN CMD ENTRYPOINT 区别
原文链接: docker RUN CMD ENTRYPOINT 区别
上一篇: docker 常用命令
下一篇: Dockerfile中ENTRYPOINT 和 CMD的区别
RUN 执行命令并创建新的镜像层,RUN 经常用于安装软件包。
CMD 设置容器启动后默认执行的命令及其参数,但 CMD 能够被 docker run
后面跟的命令行参数替换。
ENTRYPOINT 配置容器启动时运行的命令。
如果在使用docker run
启动容器时使用了命令行参数,那么dockerfile 中的cmd 指令将无效:
通过ENTRYPOINT 指定的命令需要与docker run
启动容器进行搭配,将docker run
指令后面跟的内容当做参数作为ENTRYPOINT指令指定的运行命令的参数,ENTRYPOINT 指定的linux命令一般是不会被覆盖的。
Shell 和 Exec 格式
我们可用两种方式指定 RUN、CMD 和 ENTRYPOINT 要运行的命令:Shell 格式和 Exec 格式,二者在使用上有细微的区别。
Shell 格式
<instruction> <command>
例如:
RUN apt-get install python3
CMD echo "Hello world"
ENTRYPOINT echo "Hello world"
当指令执行时,shell 格式底层会调用 /bin/sh -c <command> 。
例如下面的 Dockerfile 片段:
ENV name Cloud Man
ENTRYPOINT echo "Hello, $name"
执行 docker run <image> 将输出:
Hello, Cloud Man
Exec 格式
<instruction> ["executable", "param1", "param2", ...]
例如:
RUN ["apt-get", "install", "python3"]
CMD ["/bin/echo", "Hello world"]
ENTRYPOINT ["/bin/echo", "Hello world"]
当指令执行时,会直接调用 <command>,不会被 shell 解析。
例如下面的 Dockerfile 片段:
ENV name Cloud Man
ENTRYPOINT ["/bin/echo", "Hello, $name"]
运行容器将输出:
Hello, $name
注意环境变量“name”没有被替换。
如果希望使用环境变量,照如下修改
ENV name Cloud Man
ENTRYPOINT ["/bin/sh", "-c", "echo Hello, $name"]
运行容器将输出:
Hello, Cloud Man
CMD 和 ENTRYPOINT 推荐使用 Exec 格式,因为指令可读性更强,更容易理解。RUN 则两种格式都可以。
RUN
RUN 指令通常用于安装应用和软件包。
RUN 在当前镜像的顶部执行命令,并通过创建新的镜像层。Dockerfile 中常常包含多个 RUN 指令。
RUN 有两种格式:
-
Shell 格式:RUN
-
Exec 格式:RUN ["executable", "param1", "param2"]
下面是使用 RUN 安装多个包的例子:
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversion
注意:apt-get update 和 apt-get install 被放在一个 RUN 指令中执行,这样能够保证每次安装的是最新的包。如果 apt-get install 在单独的 RUN 中执行,则会使用 apt-get update 创建的镜像层,而这一层可能是很久以前缓存的。
CMD
CMD 指令允许用户指定容器的默认执行的命令。
此命令会在容器启动且 docker run 没有指定其他命令时运行。
-
如果 docker run 指定了其他命令,CMD 指定的默认命令将被忽略。
-
如果 Dockerfile 中有多个 CMD 指令,只有最后一个 CMD 有效。
CMD 有三种格式:
-
Exec 格式:CMD ["executable","param1","param2"]
这是 CMD 的推荐格式。 -
CMD ["param1","param2"] 为 ENTRYPOINT 提供额外的参数,此时 ENTRYPOINT 必须使用 Exec 格式。
-
Shell 格式:CMD command param1 param2
Exec 和 Shell 格式前面已经介绍过了。
第二种格式 CMD ["param1","param2"] 要与 Exec 格式 的 ENTRYPOINT 指令配合使用,其用途是为 ENTRYPOINT 设置默认的参数。我们将在后面讨论 ENTRYPOINT 时举例说明。
下面看看 CMD 是如何工作的。Dockerfile 片段如下:
CMD echo "Hello world"
运行容器 docker run -it [image] 将输出:
Hello world
但当后面加上一个命令,比如 docker run -it [image] /bin/bash,CMD 会被忽略掉,命令 bash 将被执行:
root@10a32dc7d3d3:/#
ENTRYPOINT
ENTRYPOINT 指令可让容器以应用程序或者服务的形式运行。
ENTRYPOINT 看上去与 CMD 很像,它们都可以指定要执行的命令及其参数。不同的地方在于 ENTRYPOINT 不会被忽略,一定会被执行,即使运行 docker run 时指定了其他命令。
ENTRYPOINT 有两种格式:
-
Exec 格式:ENTRYPOINT ["executable", "param1", "param2"] 这是 ENTRYPOINT 的推荐格式。
-
Shell 格式:ENTRYPOINT command param1 param2
在为 ENTRYPOINT 选择格式时必须小心,因为这两种格式的效果差别很大。
Exec 格式
ENTRYPOINT 的 Exec 格式用于设置要执行的命令及其参数,同时可通过 CMD 提供额外的参数。
ENTRYPOINT 中的参数始终会被使用,而 CMD 的额外参数可以在容器启动时动态替换掉。
比如下面的 Dockerfile 片段:
ENTRYPOINT ["/bin/echo", "Hello"]
CMD ["world"]
当容器通过 docker run -it [image] 启动时,输出为:
Hello world
而如果通过 docker run -it [image] CloudMan 启动,则输出为:
Hello CloudMan
FROM ubuntu
ENTRYPOINT ["/bin/echo", "Hello"]
CMD ["world"]
Shell 格式
ENTRYPOINT 的 Shell 格式会忽略任何 CMD 或 docker run 提供的参数。
最佳实践
-
使用 RUN 指令安装应用和软件包,构建镜像。
-
如果 Docker 镜像的用途是运行应用程序或服务,比如运行一个 MySQL,应该优先使用 Exec 格式的 ENTRYPOINT 指令。CMD 可为 ENTRYPOINT 提供额外的默认参数,同时可利用 docker run 命令行替换默认参数。
-
如果想为容器设置默认的启动命令,可使用 CMD 指令。用户可在 docker run 命令行中替换此默认命令。
Docker RUN vs CMD vs ENTRYPOINT
<table><tr>
<td><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
总结
以上是小编为你收集整理的Docker RUN vs CMD vs ENTRYPOINT全部内容。
如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。
Docker | dockerfile构建centos镜像,以及CMD和ENTRYPOINT的区别
构建自己的centos镜像
docker pull centos
下载下来的镜像都是基础版本,缺少很多常用的命令功能,比如:ll
、vim
等等,
下面介绍制作一个功能较全的自己的centos镜像。
步骤
1、编写dockerfile文件
FROM centos
MAINTAINER xiao<example@163.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim # vim命令
RUN yum -y install net-tools # ifconfig命令
EXPOSE 80
CMD echo $MYPATH
CMD echo "---end--"
CMD /bin/bash
2、构建镜像
- -f file 指定dockerfile文件的路径
- -t tag 指定name:tag
docker build -f ./mydockerfile -t mycentos:0.1 .
Successfully built e7527f97f78a
Successfully tagged mycentos:0.1
3、测试运行
docker images
docker run -it mycentos:0.1
可以看到进入容器之后,直接就是在 /usr/local
目录下,是因为dockerfile
配置的WORKDIR
这时,ifconfig
、vim
命令都可以使用了
4、查看镜像构建历史记录
docker history imageID
CMD和ENTRYPOINT的区别
编写CMD测试dockerfile文件
- 编写dockerfile文件
FROM centos
CMD ["ls", "-a"]
- 构建镜像
docker build -f ./dockerfile -t cmd-test .
- 启动镜像
docker run imageID/iamgeName
测试发现,启动镜像时追加的命令替换了CMD
命令,如下图所示:
编写ENTRYPOINT测试dockerfile文件
每个Dockerfile
只能有一个ENTRYPOINT
,如果指定了多个,只有最后一个被执行,而且一定会被执行
FROM centos
ENTRYPOINT ["ls", "-a"]
# nginx 镜像
ENTRYPOINT [ "/usr/sbin/nginx", "-g", "daemon off;" ]
总结
CMD
命令会被启动容器时追加的命令替换执行,
2.ENTRYPOINT
命令不会被启动容器时追加的命令替换,而是合并执行
我是 甜点cc
热爱前端,也喜欢专研各种跟本职工作关系不大的技术,技术、产品兴趣广泛且浓厚,等待着一个创业机会。本号主要致力于分享个人经验总结,希望可以给一小部分人一些微小帮助。
希望能和大家一起努力营造一个良好的学习氛围,为了个人和家庭、为了我国的互联网物联网技术、数字化转型、数字经济发展做一点点贡献。数风流人物还看中国、看今朝、看你我。
Docker 中的 Dockerfile 命令详解 FROM RUN COPY ADD ENTRYPOINT...
Dockerfile 指令
这些建议旨在帮助您创建高效且可维护的 Dockerfile。
FROM
FROM 指令的 Dockerfile 引用
尽可能使用当前的官方图像作为图像的基础。我们推荐 Alpine 图像,因为它是严格控制的并且尺寸小(目前小于 5 MB),同时仍然是完整的 Linux 发行版。
标签
了解对象标签
您可以为图像添加标签,以帮助按项目组织图像,记录许可信息,帮助实现自动化或出于其他原因。对于每个标签,添加 LABEL 以一个或多个键值对开头的行。以下示例显示了不同的可接受格式。内容包括解释性意见。
必须引用带空格的字符串或必须转义空格。内引号字符(")也必须进行转义。
# Set one or more individual labels
LABEL com.example.version="0.0.1-beta"
LABEL vendor1="ACME Incorporated"
LABEL vendor2=ZENITH\ Incorporated
LABEL com.example.release-date="2015-02-12"
LABEL com.example.version.is-production=""
图像可以有多个标签。在 Docker 1.10 之前,建议将所有标签组合到一条 LABEL 指令中,以防止创建额外的层。这不再是必需的,但仍然支持组合标签。
# Set multiple labels on one line
LABEL com.example.version="0.0.1-beta" com.example.release-date="2015-02-12"
以上也可以写成:
# Set multiple labels at once, using line-continuation characters to break long lines
LABEL vendor=ACME\ Incorporated \
com.example.is-beta= \
com.example.is-production="" \
com.example.version="0.0.1-beta" \
com.example.release-date="2015-02-12"
有关可接受的标签键和值的指导,请参阅了解对象标签。有关查询标签的信息,请参阅管理对象标签中与过滤相关的项目。另请参见 Dockerfile 参考中的 LABEL。
RUN
RUN 指令的 Dockerfile 参考
RUN 在使用反斜杠分隔的多行上拆分长或复杂语句,以使您 Dockerfile 更具可读性,可理解性和可维护性。
APT-GET 的
可能最常见的用例 RUN 是应用程序 apt-get。因为它安装了包,所以该 RUN apt-get 命令有几个需要注意的问题。
避免 RUN apt-get upgrade 和 dist-upgrade,因为父图像中的许多 “基本” 包无法在非特权容器内升级 。如果父图像中包含的包已过期,请与其维护人员联系。如果您知道有特定包,foo 需要更新,请使用 apt-get install -y foo 自动更新。
始终在同一 声明中结合 RUN apt-get update 使用。例如:apt-get installRUN
RUN apt-get update && apt-get install -y \
package-bar \
package-baz \
package-foo
apt-get update 在 RUN 语句中单独使用会导致缓存问题,并且后续 apt-get install 指令会失败。例如,假设你有一个 Dockerfile:
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install -y curl
构建映像后,所有层都在 Docker 缓存中。假设您稍后 apt-get install 通过添加额外包修改:
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install -y curl nginx
Docker 将初始和修改的指令视为相同,并重用前面步骤中的缓存。其结果是,apt-get update 在不执行,因为编译使用缓存的版本。因为 apt-get update 没有运行,您的构建有可能得到的一个过时的版本 curl 和 nginx 包。
使用 RUN apt-get update && apt-get install -y 确保您的 Dockerfile 安装最新的软件包版本,无需进一步编码或手动干预。这种技术被称为 “缓存破坏”。您还可以通过指定包版本来实现缓存清除。这称为版本固定,例如:
RUN apt-get update && apt-get install -y \
package-bar \
package-baz \
package-foo=1.3.*
版本固定强制构建以检索特定版本,而不管缓存中的内容是什么。此技术还可以减少由于所需包中意外更改而导致的故障。
下面是一个结构良好的 RUN 说明,演示了所有 apt-get 建议。
RUN apt-get update && apt-get install -y \
aufs-tools \
automake \
build-essential \
curl \
dpkg-sig \
libcap-dev \
libsqlite3-dev \
mercurial \
reprepro \
ruby1.9.1 \
ruby1.9.1-dev \
s3cmd=1.1.* \
&& rm -rf /var/lib/apt/lists/*
该 s3cmd 参数指定一个版本 1.1.*。如果映像以前使用的是旧版本,则指定新版本会导致缓存破坏,apt-get update 并确保安装新版本。列出每行的包也可以防止包重复中的错误。
此外,当您通过删除 /var/lib/apt/lists 它来清理 apt 缓存时会减小图像大小,因为 apt 缓存不存储在图层中。由于 RUN 语句以#开头 apt-get update,因此包缓存始终在刷新之前刷新 apt-get install。
官方 Debian 和 Ubuntu 映像自动运行 apt-get clean,因此不需要显式调用。
使用管道
某些 RUN 命令依赖于使用管道符(|)将一个命令的输出传递到另一个命令的能力,如下例所示:
RUN wget -O - https://some.site | wc -l > /number
Docker 使用 /bin/sh -c 解释器执行这些命令,解释器仅评估管道中最后一个操作的退出代码以确定成功。在上面的示例中,只要 wc -l 命令成功,即使 wget 命令失败,此构建步骤也会成功并生成新映像。
如果您希望命令因管道中任何阶段的错误而失败,请预先 set -o pipefail && 确定意外错误,以防止构建无意中成功。例如:
RUN set -o pipefail && wget -O - https://some.site | wc -l > /number
并非所有 shell 都支持该 -o pipefail 选项。
在诸如 dash 基于 Debian 的映像上的 shell 的情况下,考虑使用 exec 形式 RUN 明确选择支持该 pipefail 选项的 shell 。例如:
RUN ["/bin/bash", "-c", "set -o pipefail && wget -O - https://some.site | wc -l > /number"]
CMD
CMD 指令的 Dockerfile 参考
该 CMD 指令应用于运行图像包含的软件以及任何参数。CMD 应该几乎总是以形式使用 CMD ["executable", "param1", "param2"…]。因此,如果图像是用于服务的,例如 Apache 和 Rails,那么你可以运行类似的东西 CMD ["apache2","-DFOREGROUND"]。实际上,建议将这种形式的指令用于任何基于服务的图像。
在大多数其他情况下,CMD 应该给出一个交互式 shell,例如 bash,python 和 perl。例如,CMD ["perl", "-de0"],CMD ["python"],或 CMD ["php", "-a"]。使用此表单意味着当您执行类似的操作时 docker run -it python,您将被放入可用的 shell 中,随时可以使用。 CMD 应该很少的方式使用 CMD ["param", "param"] 会同 ENTRYPOINT,除非你和你预期的用户已经非常熟悉如何 ENTRYPOINT 工作的。
EXPOSE
EXPOSE 指令的 Dockerfile 参考
该 EXPOSE 指令指示容器侦听连接的端口。因此,您应该为您的应用程序使用通用的传统端口。例如,包含 Apache Web 服务器 EXPOSE 80 的图像将使用,而包含 MongoDB 的图像将使用 EXPOSE 27017,依此类推。
对于外部访问,您的用户可以 docker run 使用一个标志来执行,该标志指示如何将指定端口映射到他们选择的端口。对于容器链接,Docker 为从接收容器返回源的路径提供环境变量(即 MYSQL_PORT_3306_TCP)。
ENV
ENV 指令的 Dockerfile 参考
要使新软件更易于运行,您可以使用 ENV 更新 PATH 容器安装的软件的 环境变量。例如,ENV PATH /usr/local/nginx/bin:$PATH 确保 CMD ["nginx"] 正常工作。
该 ENV 指令对于提供特定于您希望容纳的服务的必需环境变量也很有用,例如 Postgres PGDATA。
最后,ENV 还可以用于设置常用的版本号,以便更容易维护版本颠簸,如以下示例所示:
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
与在程序中使用常量变量(与硬编码值相对)类似,此方法允许您更改单个 ENV 指令以自动神奇地破坏容器中的软件版本。
每 ENV 行创建一个新的中间层,就像 RUN 命令一样。这意味着即使您在将来的图层中取消设置环境变量,它仍然会在此图层中保留,并且可以转储其值。您可以通过创建如下所示的 Dockerfile 来测试它,然后构建它。
FROM alpine
ENV ADMIN_USER="mark"
RUN echo $ADMIN_USER > ./mark
RUN unset ADMIN_USER
$ docker run --rm test sh -c ''echo $ADMIN_USER''
mark
要防止这种情况,并且确实取消设置环境变量,请使用 RUN 带有 shell 命令的命令,在单个图层中设置,使用和取消设置变量 all。您可以使用;或分隔命令 &&。如果您使用第二种方法,并且其中一个命令失败,则 docker build 也会失败。这通常是一个好主意。使用 \Linux Dockerfiles 作为行继续符可以提高可读性。您还可以将所有命令放入 shell 脚本中,并让 RUN 命令运行该 shell 脚本。
FROM alpine
RUN export ADMIN_USER="mark" \
&& echo $ADMIN_USER > ./mark \
&& unset ADMIN_USER
CMD sh
$ docker run --rm test sh -c ''echo $ADMIN_USER''
ADD COPY
- ADD 指令的 Dockerfile 参考
- COPY 指令的 Dockerfile 参考
一般而言,虽然 ADD 并且 COPY 在功能上类似,但是 COPY 是优选的。那是因为它更透明 ADD。COPY 仅支持将本地文件基本复制到容器中,同时 ADD 具有一些功能(如仅限本地的 tar 提取和远程 URL 支持),这些功能并不是很明显。因此,最好的用途 ADD 是将本地 tar 文件自动提取到图像中,如 ADD rootfs.tar.xz/。
如果您有多个 Dockerfile 步骤使用上下文中的不同文件,则 COPY 它们是单独的,而不是一次性完成。这可确保每个步骤的构建缓存仅在特定所需文件更改时失效(强制重新执行该步骤)。
例如:
COPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt
COPY . /tmp/
导致 RUN 步骤的缓存失效次数少于放置 COPY . /tmp/ 之前的缓存失效次数。
由于图像大小很重要,ADD 因此强烈建议不要使用从远程 URL 获取包。你应该使用 curl 或 wget 代替。这样,您可以删除提取后不再需要的文件,也不必在图像中添加其他图层。例如,你应该避免做以下事情:
ADD http://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C /usr/src/things all
而是做一些像:
RUN mkdir -p /usr/src/things \
&& curl -SL http://example.com/big.tar.xz \
| tar -xJC /usr/src/things \
&& make -C /usr/src/things all
对于不需要 ADDtar 自动提取功能的其他项目(文件,目录),您应该始终使用 COPY。
ENTRYPOINT
ENTRYPOINT 指令的 Dockerfile 参考
最好的用法 ENTRYPOINT 是设置图像的主命令,允许该图像像该命令一样运行(然后 CMD 用作默认标志)。
让我们从命令行工具的图像示例开始 s3cmd:
ENTRYPOINT ["s3cmd"]
CMD ["--help"]
现在可以像这样运行图像来显示命令的帮助:
$ docker run s3cmd
或使用正确的参数执行命令:
$ docker run s3cmd ls s3://mybucket
这很有用,因为图像名称可以兼作二进制文件的引用,如上面的命令所示。
该 ENTRYPOINT 指令还可以与辅助脚本结合使用,允许它以与上述命令类似的方式运行,即使启动该工具可能需要多个步骤。
例如,Postgres 官方图像 使用以下脚本作为其 ENTRYPOINT:
#!/bin/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 "$@"
将 app 配置为 PID 1
此脚本使用的 execbash 命令 ,以使最终运行的应用程序成为容器的 PID 1. 这允许应用程序接收发送到所述容器任何 Unix 信号。如需更多信息,请参阅 ENTRYPOINT 参考。
帮助程序脚本被复制到容器中并通过 ENTRYPOINT 容器启动运行:
COPY ./docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["postgres"]
该脚本允许用户以多种方式与 Postgres 交互。
它可以简单地启动 Postgres:
$ docker run postgres
或者,它可用于运行 Postgres 并将参数传递给服务器:
$ docker run postgres postgres --help
最后,它还可以用来启动一个完全不同的工具,比如 Bash:
$ docker run --rm -it postgres bash
VOLUME
VOLUME 指令的 Dockerfile 参考
该 VOLUME 指令应用于公开由 docker 容器创建的任何数据库存储区域,配置存储或文件 / 文件夹。强烈建议您使用图像 VOLUME 的任何可变和 / 或用户可维修部分。
USER
USER 指令的 Dockerfile 参考
如果服务可以在没有权限的情况下运行,请使用 USER 更改为非 root 用户。首先在 Dockerfile 类似的东西中创建用户和组 RUN groupadd -r postgres && useradd --no-log-init -r -g postgres postgres。
考虑一个显式的 UID / GID
图像中的用户和组被分配了非确定性 UID / GID,因为无论图像重建如何,都会分配 “下一个” UID / GID。因此,如果它很重要,您应该分配一个显式的 UID / GID。
由于 Go 存档 /tar 包处理稀疏文件时未解决的错误,尝试在 Docker 容器内创建具有非常大的 UID 的用户可能导致磁盘耗尽,因为 /var/log/faillog 容器层中填充了 NULL(\ 0)字符。解决方法是将 --no-log-init 标志传递给 useradd。Debian / Ubuntu adduser 包装器不支持此标志。
避免安装或使用,sudo 因为它具有可能导致问题的不可预测的 TTY 和信号转发行为。如果您绝对需要类似的功能 sudo,例如将守护程序初始化 root 为非运行它 root,请考虑使用 “gosu”。
最后,为了减少层次和复杂性,避免 USER 频繁地来回切换。
WORKDIR
WORKDIR 指令的 Dockerfile 参考
为了清晰和可靠,您应该始终使用绝对路径 WORKDIR。此外,您应该使用难以阅读,排除故障和维护 WORKDIR 的扩散指令 RUN cd … && do-something。
ONBUILD
ONBUILD 指令的 Dockerfile 参考
一个 ONBUILD 命令将当前执行后 Dockerfile 构建完成。ONBUILD 在任何导出 FROM 当前图像的子图像中执行。将该 ONBUILD 命令视为父母 Dockerfile 给孩子的指令 Dockerfile。
Docker 构建 ONBUILD 在子代中的任何命令之前执行命令 Dockerfile。
ONBUILD 对于将要构建 FROM 给定图像的图像非常有用。例如,您将使用 ONBUILD 一个语言堆栈映像来构建在该语言中编写的任意用户软件 Dockerfile,正如您在 Ruby 的 ONBUILD 变体中所看到的那样。
构建的图像 ONBUILD 应该获得单独的标记,例如:ruby:1.9-onbuild 或 ruby:2.0-onbuild。
把时要小心,ADD 或 COPY 在 ONBUILD。如果新构建的上下文缺少正在添加的资源,则 “onbuild” 映像将发生灾难性故障。如上所述,添加单独的标记有助于通过允许 Dockerfile 作者做出选择来缓解这种情况。
关于Dockerfile RUN, CMD & ENTRYPOINT的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于docker RUN CMD ENTRYPOINT 区别、Docker RUN vs CMD vs ENTRYPOINT、Docker | dockerfile构建centos镜像,以及CMD和ENTRYPOINT的区别、Docker 中的 Dockerfile 命令详解 FROM RUN COPY ADD ENTRYPOINT...等相关知识的信息别忘了在本站进行查找喔。
本文标签: