【问题标题】:What happens if I write RUN node index.js instead of CMD node index.js in a dockerfile?如果我在 dockerfile 中写入 RUN node index.js 而不是 CMD node index.js 会发生什么?
【发布时间】:2020-04-06 00:59:34
【问题描述】:

我用 dockerfile 做了一个简单的 hello world node.js 应用程序

FROM node:10
WORKDIR /usr/src/app
COPY package*.json ./

RUN npm install
COPY . .
EXPOSE 8080
CMD node index.js

如果我在 dockerfile 中将 CMD 更改为 RUN,它仍然可以工作。 在 dockerfile 中记录了使用 CMD,因为它将在容器运行时启动节点服务器。

我想知道如果我使用 RUN cmd 而不是 CMD 会发生什么。 基本上,如果我制作一个本身处于运行状态的 docker 映像会发生什么。

【问题讨论】:

标签: node.js docker dockerfile docker-image docker-run


【解决方案1】:

RUN 将在构建过程中执行命令。 CMD执行容器时用作默认命令,而不是构建。如果您在 RUN 指令中运行 node index.js,您的构建将永远不会完成,并且您没有可与他人共享的容器。

有关更多详细信息,请参阅 dockerfile 文档:RUNCMD

该文档中的相关内容:

RUN 指令将在当前图像之上的新层中执行任何命令并提交结果。生成的提交图像将用于 Dockerfile 中的下一步。

CMD 的主要目的是为正在执行的容器提供默认值。


编辑:使用 OP 的 index.jsonpackage.jsonDockerfile 文件,使用 RUN node index.js 时 docker 映像构建未完成,使用 @ 时完成(如预期) 987654337@.

index.js的内容:

//Load express module with `require` directive
var express = require('express')
var app = express()

//Define request response in root URL (/)
app.get('/', function (req, res) {
  res.send('Hello World!')
})

//Launch listening server on port 8081
app.listen(8080, function () {
  console.log('app listening on port 8080!')
})

package.json的内容:

{
  "name": "dummy_nodejs_app",
  "version": "1.0.0",
  "description": "Node.js on Docker",
  "author": "Debojit",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.16.1"
  }
}

使用Dockerfile时如下:

FROM node:10
WORKDIR /usr/src/app
COPY package*.json ./

RUN npm install
COPY . .
EXPOSE 8080
RUN node index.js

然后构建挂起。这是输出:

jakub@dash:/tmp/test-node$ docker build -t test .
Sending build context to Docker daemon  4.096kB
Step 1/7 : FROM node:10
 ---> d5680e53a228
Step 2/7 : WORKDIR /usr/src/app
 ---> Using cache
 ---> a4b4547833e5
Step 3/7 : COPY package*.json ./
 ---> Using cache
 ---> 2b19cc3e48a3
Step 4/7 : RUN npm install
 ---> Using cache
 ---> fe1f1e72d17d
Step 5/7 : COPY . .
 ---> eb6fe0e3d1a7
Step 6/7 : EXPOSE 8080
 ---> Running in e573b923fcb2
Removing intermediate container e573b923fcb2
 ---> b3590153eed7
Step 7/7 : RUN node index.js
 ---> Running in 08b408e6e6f3
app listening on port 8080!

这会无限期挂起。

使用 Dockerfile 时

FROM node:10
WORKDIR /usr/src/app
COPY package*.json ./

RUN npm install
COPY . .
EXPOSE 8080
CMD node index.js

构建输出是:

jakub@dash:/tmp/test-node$ docker build -t test .
Sending build context to Docker daemon  4.096kB
Step 1/7 : FROM node:10
 ---> d5680e53a228
Step 2/7 : WORKDIR /usr/src/app
 ---> Using cache
 ---> a4b4547833e5
Step 3/7 : COPY package*.json ./
 ---> Using cache
 ---> 2b19cc3e48a3
Step 4/7 : RUN npm install
 ---> Using cache
 ---> fe1f1e72d17d
Step 5/7 : COPY . .
 ---> Using cache
 ---> fc036f428e34
Step 6/7 : EXPOSE 8080
 ---> Using cache
 ---> d1ede7276d34
Step 7/7 : CMD node index.js
 ---> Using cache
 ---> cf051929395b
Successfully built cf051929395b
Successfully tagged test:latest

【讨论】:

  • 我尝试在使用 RUN 命令后构建映像,它确实创建了一个映像。此外,在构建映像之后,我什至可以运行容器并监听我的本地主机。这是我不清楚的地方。
  • 你是说你使用了RUN node index.js,构建完成,你可以运行容器了吗?如果你这样做了,那就是滥用RUNnode index.js 应该在容器运行时执行,所以它应该在CMD(或者可能是ENTRYPOINT)指令中
  • 是的,我做到了。我知道这违反了文档,但我想知道这是否会产生任何影响。我可能会因此面临哪些问题?
  • 我尝试使用来自hereindex.js 文件重现您的行为,但构建未通过RUN nodex index.js,因为它正在运行服务器。要获得更好的答案,您必须分享minimal, reproducible example
  • 我的 index.js 是:pastebin.com/u9qhDJvU,package.json 文件是:pastebin.com/cURsvj0w & 上面提到了 Dockerfile。
【解决方案2】:

首先,如果您在构建阶段使用RUN 命令启动任何长时间运行的进程,您的构建过程将被卡住。

RUN 命令在构建时执行,它专为构建时配置和安装包和工具而设计,使用 RUN 命令准备 Docker 映像,例如安装 npm 模块和一些其他应用程序依赖项当进程在容器中启动时可用。

CMD 在启动容器时执行,它不会在构建时执行,CMD 应该是一个长时间运行的过程来保留您的容器。

【讨论】:

    【解决方案3】:

    RUN 步骤使用提供的命令执行一个临时容器,等待该命令退出,然后捕获对容器文件系统的更改作为结果映像的另一层。它不存储正在运行的进程、对环境变量的更改或对 shell 状态的任何更改,因为这些都没有写入文件系统。它也不会捕获对卷的更改,因为临时容器是使用映像中定义的卷启动的,并且对卷的更改不会应用于容器文件系统。这是一个构建时间步。

    CMD 步骤替换了当镜像作为容器运行时 docker 运行的现有默认命令。只要此命令正在运行,容器就会存在,并且您只能为该命令设置一个值。如果您再次定义CMD,则会替换之前的值。如果您使用覆盖的命令启动容器,CMD 的图像值将被忽略。

    因此,您希望将在映像构建时修改文件系统的步骤与容器运行到 RUNCMD 时执行的步骤分开。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-15
      • 2021-03-26
      • 1970-01-01
      • 1970-01-01
      • 2017-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多