手把手教你容器化一个Node.js应用并部署上云
一、写在前面
上节课我们学习了容器云的基础概念,这次我给自己定了个小目标:把一个本地的Node.js Web应用完整容器化,并部署到云服务器上。
整个过程走下来,踩了不少坑,但也真正打通了“开发→构建→推送→部署”的全链路。这篇博文就是我的实操复盘,核心“一得”是:容器化不是装个Docker就完事,而是一种“应用即镜像”的交付思维,真正实现了开发与运维的一致性。
二、准备一个简单的Node.js应用
先写一个最简单的Web服务,用来演示。
项目结构:
text
myapp/ ├── package.json ├── app.js └── Dockerfile
package.json:
json
{
"name": "myapp",
"version": "1.0.0",
"main": "app.js",
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "^4.18.2"
}
}
app.js:
javascript
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('<h1>🚀 Hello from Container Cloud!</h1>');
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
本地运行 npm install && npm start,访问 http://localhost:3000 确认页面正常。
三、编写Dockerfile:容器化的灵魂
Dockerfile是容器化的核心,它定义了如何把应用打包成镜像。
dockerfile
# 使用官方Node.js轻量镜像作为基础 FROM node:18-alpine # 设置工作目录 WORKDIR /app # 先复制package文件,利用Docker缓存层加速构建 COPY package*.json ./ RUN npm install --production # 复制应用源码 COPY . . # 声明运行时端口 EXPOSE 3000 # 启动命令 CMD ["node", "app.js"]
⚡ 小技巧:
COPY package*.json ./和RUN npm install放在一起,能让依赖安装层被缓存。代码改动时只要依赖不变,就不会重新下载,构建速度飞快。
构建镜像:
bash
docker build -t myapp:v1 .
本地运行测试:
bash
docker run -d -p 3000:3000 --name myapp-container myapp:v1
浏览器访问确认容器内应用正常运行。
✅ 一得:Dockerfile是“基础设施即代码”的起点,它把运行环境、依赖、启动流程全部固化为可复现的脚本,从此告别“环境不一致”的噩梦。
四、推送镜像到容器仓库
要在云服务器上部署,需要把镜像推送到一个可访问的仓库。我用的是阿里云容器镜像服务(ACR),免费个人版完全够用。
1. 登录阿里云Docker Registry:
bash
docker login --username=你的阿里云账号 registry.cn-hangzhou.aliyuncs.com
2. 打标签:
bash
docker tag myapp:v1 registry.cn-hangzhou.aliyuncs.com/你的命名空间/myapp:v1
3. 推送:
bash
docker push registry.cn-hangzhou.aliyuncs.com/你的命名空间/myapp:v1
推送成功后,在阿里云控制台就能看到镜像了。
✅ 一得:镜像仓库是容器化的“分发枢纽”,有了它,任何一台有Docker的机器都能拉取并运行完全相同的应用,实现真正的“一次构建,处处运行”。
五、在云服务器上部署
我用的是一台阿里云ECS(CentOS 7.9),同样安装Docker后执行:
bash
# 登录仓库(如果是私有镜像) docker login --username=你的账号 registry.cn-hangzhou.aliyuncs.com # 拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/你的命名空间/myapp:v1 # 运行 docker run -d -p 80:3000 --name myapp-prod myapp:v1
此时访问云服务器的公网IP,就能看到之前的页面了。
配置开机自启:
bash
docker update --restart=always myapp-prod
这样服务器重启后容器也会自动恢复。
部署架构示意图(文字描述):
text
用户浏览器
↓
云服务器 (ECS)
↓ 端口80 → 容器3000
Docker Engine
↓ 运行
容器实例 (myapp:v1)
六、升级应用:体验滚动更新
假设修改了代码,把问候语改为 "<h1>🎉 Version 2 is LIVE!</h1>"。
1. 构建新版本镜像并推送:
bash
docker build -t myapp:v2 . docker tag myapp:v2 registry.cn-hangzhou.aliyuncs.com/你的命名空间/myapp:v2 docker push registry.cn-hangzhou.aliyuncs.com/你的命名空间/myapp:v2
2. 在服务器上更新:
bash
docker pull registry.cn-hangzhou.aliyuncs.com/你的命名空间/myapp:v2 docker stop myapp-prod && docker rm myapp-prod docker run -d -p 80:3000 --name myapp-prod --restart=always myapp:v2
✅ 一得:版本化镜像让应用升级变得可控、可回滚。如果v2有问题,停掉v2、重新运行v1镜像就能秒级回滚,这是传统部署方式难以做到的。
七、遇到的坑与解决方法
| 问题 | 原因 | 解决方法 |
|---|---|---|
构建时 npm install 报网络错误 |
容器内网络访问国外源慢 | 在Dockerfile中先设置国内镜像源:RUN npm config set registry https://registry.npmmirror.com |
| 容器启动后立刻退出 | app.js有语法错误但没看到日志 | 先用 docker logs myapp-container 查看运行日志,定位错误 |
| 云服务器访问不到 | ECS安全组未开放80端口 | 去阿里云控制台安全组中添加入方向规则,放行TCP 80端口 |
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)