我使用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映像,会发生什么情况。
答案 0 :(得分:2)
RUN
将在构建过程中执行命令。 执行容器时,CMD
用作默认命令,而不是构建。如果您在node index.js
指令中运行RUN
,则构建将永远不会完成,并且您将没有与他人共享的容器。
有关更多详细信息,请参阅dockerfile文档:RUN
和CMD
。
该文档的相关内容:
RUN指令将在当前图像顶部的新层中执行所有命令,并提交结果。生成的提交映像将用于Dockerfile中的下一步。
CMD的主要目的是为执行中的容器提供默认值。
编辑:使用OP的index.json
,package.json
和Dockerfile
文件,使用RUN node index.js
时docker镜像构建无法完成,并且可以使用CMD node index.js
时(按预期完成)。
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
答案 1 :(得分:1)
RUN
步骤使用提供的命令执行一个临时容器,等待该命令退出,然后捕获更改为容器文件系统,作为结果图像的另一层。它不存储正在运行的进程,对环境变量的更改或对Shell状态的任何更改,因为这些操作未写入文件系统。由于临时容器是使用映像中定义的卷启动的,因此它也不会捕获对卷的更改,并且对卷的更改不会应用到容器文件系统。这是构建时间的步骤。
CMD
步骤替换了将镜像作为容器运行时docker运行的现有默认命令。只要该命令运行,容器就会存在,并且您只能为该命令指定一个值。如果您第二次定义CMD
,则将替换先前的值。而且,如果您使用覆盖命令启动容器,则CMD
的图像值将被忽略。
因此,您希望将在映像构建时修改文件系统的步骤与将容器分别运行到RUN
和CMD
时执行的步骤分开。
答案 2 :(得分:0)
首先,如果在构建阶段使用RUN
命令启动任何长时间运行的过程,则构建过程将被卡住。
RUN
命令在构建时执行,该命令专用于构建时配置,安装软件包和工具,使用RUN
命令准备Docker映像,例如安装npm模块和其他一些程序在容器中启动时将可用的应用程序依赖项。
CMD
在启动容器时执行,它不会在构建时执行,CMD
应该是一个长时间运行的过程,以保持容器。