【问题标题】:How do I Run Docker cmds Exactly Like in a Dockerfile我如何像在 Dockerfile 中一样运行 Docker cmds
【发布时间】:2018-01-05 17:34:20
【问题描述】:

Docker 在 Dockerfile 中运行命令的方式与在启动容器后手动运行命令的方式似乎有所不同。这似乎是由于您可以启动的 shell 类型,(我假设)带有 Dockerfile 的非交互式 shell 与运行 docker run -it <some-img-id> 之类的交互式 shell 相比。

如何调试 Docker 容器中正在运行的命令,使其运行方式与从 Dockerfile 中运行的命令完全一样?只需将/bin/bash --noprofile 添加到run cmd 就足够了吗?或者从 Dockerfile 启动时环境还有什么不同?

【问题讨论】:

  • 对此没有通用的答案——我们需要查看您所询问的 specific 命令。 minimal reproducible example 向其他人展示如何自己看到差异也会有所帮助。
  • ...像COPY 这样的命令完全在Docker 内部实现——它们根本不调用shell。 RUN 和 kin 有多种模式——如果你将文字参数列表作为数组传递,那么任何地方都没有 shell。

标签: bash shell docker dockerfile interactive


【解决方案1】:

简答1:

如果 Dockerfile 不使用 USERSHELL 命令,那么:

docker --entrypoint "/bin/sh -c" -u root <image> cmd

简答二:

如果您在构建后不压缩或压缩镜像,Docker 会为每个 Dockerfile 命令创建镜像层。您可以在每个步骤末尾的docker build 的输出中看到它们,---&gt;

Step 2/8 : WORKDIR /usr/src/app
  ---> 5a5964bed25d # <== THIS IS IMAGE ID OF STEP 2
Removing intermediate container b2bc9558e499
Step 3/8 : RUN something
  ---> f6e90f0a06e2 # <== THIS IS IMAGE ID OF STEP 3
Removing intermediate container b2bc9558e499

在您要调试的 RUN 步骤之前查找映像 ID(例如,您要调试上面的第 3 步,获取第 2 步的映像 ID)。然后只需运行该图像中的命令:

docker run -it 5a5964bed25d cmd

长答案 1:

当你运行docker run [image] cmd时,Docker实际上是这样启动cmd的:

  • cmd 作为参数执行图像的默认入口点。入口点存储在通过 Dockerfile 中的ENTRYPOINT 命令构建的映像中。即如果cmdmy-app 并且入口点是/bin/sh -c,它会执行/bin/sh -c my-app
  • 使用映像的默认用户 ID 启动它,该用户 ID 由 Dockerfile 中的最后一个 USER 命令定义
  • 使用来自映像的 Dockerfile commulative 的所有 ENV 命令的环境变量启动它

docker build 运行 Dockerfile RUN 时,它的作用完全一样,只是使用 Dockerfile 的当时(行)存在的值。

确切地说,您必须在 RUN 行之前获取 ENVs 和最后一个 USER 命令的值,并在 docker run 命令中使用这些值。

最常见的图像以/bin/sh -c/bin/bash -c 作为入口点,并且很可能构建以root 用户运行。因此docker --entrypoint "/bin/bash -c" -u root &lt;image&gt; cmd 应该足够了

【讨论】:

    【解决方案2】:

    您正在经历的是由于 shell 的行为。我们大多数人都习惯于使用 bash shell。所以通常我们会尝试以下面的方式运行命令

    对于新容器

    docker run -it <imageid> bash
    

    对于现有容器

    docker exec -it <containerid> bash
    

    但是当我们在 Dockerfile 中使用 RUN 指令指定一些命令时

    RUN echo Testing
    

    那么就相当于运行/bin/sh -c 'echo Testing'。因此,您可以预期某些差异,因为两个外壳都不同。

    在 Docker 1.12 或更高版本中,您有一个名为 SHELL 的 Dockerfile 指令,这允许您覆盖默认的 SHELL

    SHELL ["/bin/bash", "-c"]
    RUN echo Testing
    

    这将使RUN 命令作为bash -c 'echo Testing' 执行。你可以了解更多关于SHELL指令here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-02
      • 2021-09-23
      • 2021-04-26
      • 1970-01-01
      • 2022-12-12
      • 1970-01-01
      • 2022-08-10
      相关资源
      最近更新 更多