繁体   English   中英

Dockerfile CMD exec 表单如何定位二进制文​​件

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM