![](/img/trans.png)
[英]Dockerfile - exec form of ENTRYPOINT and shell form of CMD
[英]How does Dockerfile CMD exec form locate the binary
如果我有这样的 Dockerfile:
FROM ubuntu
CMD [ "ps", "-ef" ]
如果我构建并运行图像,我会得到
$ docker run -it 156a9f959f43
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 07:12 pts/0 00:00:00 ps -ef
这与文档一致。
问题:当容器运行时,二进制ps
如何首先定位?
exec 语法使用父映像 ( ubuntu:latest
) 中定义的PATH
环境变量。
$ docker image inspect ubuntu:latest
[
{
...
"Config": {
...
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/bash"
],
....
如果你去查看这个基础镜像的Dockerfile ......你实际上会看到 PATH 变量没有在那里定义。 我们可以scratch
但那是一个虚拟图像。
因此,让我们scratch
构建一个图像,看看定义了哪些变量:
$ cat df.scratch
FROM scratch
$ docker build -t test-scratch -f df.scratch .
...
$ docker image inspect test-scratch:latest
[
{
...
"Config": {
...
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
...
所以 PATH 是在scratch
映像中创建的。 这个旧问题和相关的 PR表明 docker 包含一个开箱即用的 PATH。
您如何调整该路径? 您需要使用ENV
线。 如果在RUN
行中设置变量,则在该RUN
行完成后不会保留该变量。 并且如果您附加到容器中的.bashrc
,这不适用于非 bash shell,例如/bin/sh
,任何使用没有 shell 的 exec 语法的东西,以及任何非交互式 bash shell(因为.bashrc
停止处理非交互式外壳的一部分)。 这是具有不同图像/构建的示例:
$ cat df.path
FROM ubuntu
# before state from the base image
RUN [ "env" ]
# attempting to modify the .bashrc
RUN echo "export PATH="$PATH:/my/custom/bin/dir"" >> ~/.bashrc
RUN [ "env" ]
# modifying the image environment variable directly
ENV PATH=${PATH}:/opt/custom/bin
RUN [ "env" ]
$ docker build -t test-path -f df.path .
Sending build context to Docker daemon 31.23kB
Step 1/6 : FROM ubuntu
---> 4e5021d210f6
Step 2/6 : RUN [ "env" ]
---> Running in 5bb72abb386d
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=5bb72abb386d
HOME=/root
Removing intermediate container 5bb72abb386d
---> c438fb269c70
Step 3/6 : RUN echo "export PATH="$PATH:/my/custom/bin/dir"" >> ~/.bashrc
---> Running in 127b10aff046
Removing intermediate container 127b10aff046
---> 4af50595c271
Step 4/6 : RUN [ "env" ]
---> Running in c5ff46ba3b82
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=c5ff46ba3b82
HOME=/root
Removing intermediate container c5ff46ba3b82
---> 455325a5e484
Step 5/6 : ENV PATH=${PATH}:/opt/custom/bin
---> Running in e7960d9ce18a
Removing intermediate container e7960d9ce18a
---> ed532bff78b4
Step 6/6 : RUN [ "env" ]
---> Running in 9c1558a61ab7
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/custom/bin
HOSTNAME=9c1558a61ab7
HOME=/root
Removing intermediate container 9c1558a61ab7
---> f08993f21b97
Successfully built f08993f21b97
Successfully tagged test-path:latest
注意第 2 步路径的原始值,它在第 4 步没有改变,它在第 6 步具有定义的值。
在 docker 容器中(类似于大多数操作系统)有一个$PATH
环境变量,它保存可执行文件所在的目录路径(用:
分隔)。
例如, $PATH
变量可能包含类似/usr/local/bin:/usr/bin:/home/ubuntu/bin
,这意味着当您运行ps
之类的命令时,它将在这些目录中查找可执行文件.
您可以在此处了解有关 $PATH 变量的更多信息https://en.wikipedia.org/wiki/PATH_(variable)
注意: $PATH
变量将因容器而异(因为它们是独立的单元),并且很可能保存 docker 映像使用的基本发行版的默认值。
要在基于 linux 的系统上更改 $PATH 变量,您可以运行export PATH="$PATH:/custom/bin/dir"
并将/custom/bin/dir
附加到变量。 要使此更改永久化,您应该将此命令添加到您的 .bashrc、.profile、.zshrc 或类似文件中(取决于您使用的 shell)
因此,要更新 docker 容器中的变量,您应该将这样的内容添加到 Docker 文件中
FROM ubuntu
RUN echo "export PATH="$PATH:/my/custom/bin/dir"" >> ~/.bashrc
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.