[Docker] Docker Node.js project tips
Basic node image
FROM node:12-stretch
COPY index.js index.js
CMD ["node", "index.js"]
Build docker image: docker build -t my-node-app .
--init
docker run my-node-app
, after docker is running, you press CTRL + C
, it doesn't exit node process, to pass down the CTRL + C
to node process as well, we can do:
docker run --init my-node-app
If you want to remove the container after exit:
docker run --init --rm my-node-app
If you want to expose node.js app port (4040) to outside world (3030)
docker run --init --rm --publish 3030:4040 my-node-app
USER node
Node image ship your a USER called node
and a group called node
which you can use to run without your root user
.
# Wrong
FROM node:12-stretch
COPY index.js index.js
USER node
CMD ["node", "index.js"]
If we do like that, it's still wrong. Because COPY index.js index.js
happens before USER node
, so it still use root user
.
# Correct
FROM node:12-stretch
USER node
COPY index.js index.js # --chown=<user>:<group>
CMD ["node", "index.js"]
Rebuild: docker build -t my-node-app .
Rerun: docker run --init --rm --publish 3030:4040 my-node-app whoami
Output: node
COPY
vs ADD
COPY --chown=node:node index.js index.js
and ADD --chown=node:node index.js index.js
, on your local mahcine, it pretty much doing the same thing.
COPY
: do less work than ADD
ADD
: if the file is not in your local machine, it will download from network. If it's a zip file, ADD
will download it and unzip it.
WORKDIR
Currently, it copy the file to the root directory of the container.
FROM node:12-stretch
USER node
WORKDIR /home/node/code # home dir, node user, code folder
COPY index.js index.js
CMD ["node", "index.js"]
Node.js with deps
- First we want to install dependencies inside container
FROM node:12-stretch
USER node
# create a directory for the app code as node user
# to resolve permission issue
RUN mkdir home/node/code
WORKDIR /home/node/code
COPY . .
# install dependencies
RUN npm ci
CMD ["node", "index.js"]
Buiid: docker build -t my-node-app .
Run: docker run --init --rm --publish 3000:3000 my-node-app ls -lsah
Output:
8.0K drwxr-xr-x 1 node node 4.0K Aug 1 06:27 .
8.0K drwxr-xr-x 1 node node 4.0K Aug 1 06:28 ..
4.0K -rw-r--r-- 1 node node 148 Aug 1 06:27 Dockerfile
0 -rw-r--r-- 1 node node 0 Aug 1 06:21 README.md
4.0K -rw-r--r-- 1 node node 554 Aug 1 06:17 index.js
8.0K drwxr-xr-x 1 node node 4.0K Aug 1 06:28 node_modules
56K -rw-r--r-- 1 node node 55K Aug 1 06:19 package-lock.json
4.0K -rw-r--r-- 1 node node 309 Aug 1 06:19 package.json
As you can see, all the files and folders belongs to node
group and user.
One thing to notice that, in the node.js app code:
const server = hapi.server({
host: "0.0.0.0",
port: process.env.PORT || 3000,
});
It uses 0.0.0.0
as host, you cannot change it to localhost
. This will not allow it to escape the container when you run it on localhost. It's a hard loop back that it cannot escape itself. Bind it to 0.0.0.0
, allow you to escape outside the container.
EXPOSE
You can add EXPOSE 3000
as documentation.
FROM node:12-stretch
USER node
# create a directory for the app code as node user
# to resolve permission issue
RUN mkdir home/node/code
WORKDIR /home/node/code
COPY . .
# install dependencies
RUN npm ci
EXPOSE 3000
CMD ["node", "index.js"]
Layers
Each line in Docker file has its own layer. For example COPY --chown=node:node . .
has it's own layer, Docker will check whether the layer output different from cache or not, if it is, then Docker will re-calcaulte.
The problem here for the current docker file is that, if we change our source code, then COPY --chown=node:node . .
is changed, we need to re-install packages again and again.
So the improved version:
FROM node:12-stretch
USER node
# create a directory for the app code as node user
# to resolve permission issue
RUN mkdir home/node/code
WORKDIR /home/node/code
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]
.dockerignore
Every project should have .dockerignore
file
node_modules/
.git/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2022-08-01 [Typescript] Class - Param properties
2018-08-01 [Mini Programe] Upload Images
2018-08-01 [JavaEE] Data Validation
2016-08-01 [React Native] Build a Github Repositories component
2014-08-01 [Backbone]5. Model & View, toggle between Models and Views -- 2
2014-08-01 [Backbone]4. Model & View, toggle between Model and View. -- 1
2014-08-01 [Backbone]3. More detail on View