部署与应用
用 Docker 部署 Node 应用并让它开机自启
把 Node 应用跑在 Docker 里,换来的是环境一致和一条命令迁移。这篇走完整流程:装 Docker、写 Dockerfile、用 compose 编排、配 Nginx 反代、以及最容易漏掉的开机自启——很多人的容器重启机器后就没了,问题都出在这一步。
开始之前
- 一台 VPS,建议 1GB 及以上内存
- 能 SSH 登录并有 sudo / root 权限
- 本地有一个能跑起来的 Node 应用(有 package.json)
- 了解基础的命令行操作
操作步骤
-
第 1 步: 安装 Docker
用官方脚本装最省事:
curl -fsSL https://get.docker.com | bash装完确认:
docker --version docker compose version两条都有输出才算装好。新版 Docker 把 compose 做成了子命令(
docker compose,不带横线),老教程里的docker-compose可能不存在。把当前用户加入 docker 组,避免每次都敲 sudo:
usermod -aG docker $USER需要重新登录才生效。
-
第 2 步: 写 Dockerfile
在应用根目录创建
Dockerfile:FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --omit=dev COPY . . EXPOSE 3000 CMD ["node", "server.js"]几个容易踩的点:
- 先复制 package.json 再复制源码,这样改代码不会让依赖层缓存失效,重建快得多
npm ci比npm install更严格也更可复现,CI 和部署都该用它- 用
alpine镜像体积小,但某些需要编译的原生模块会有兼容问题,遇到编译错误换成node:20-slim
再加一个
.dockerignore,至少排除node_modules和.git,否则镜像会大得离谱。 -
第 3 步: 写 compose 文件并启动
创建
docker-compose.yml:services: app: build: . restart: unless-stopped ports: - "127.0.0.1:3000:3000" environment: - NODE_ENV=production两个关键细节:
restart: unless-stopped是开机自启的核心。没有这一行,容器崩溃不会自动拉起,重启机器后更是直接消失。127.0.0.1:3000:3000只监听本机,不直接暴露到公网。对外一律走 Nginx 反代——这样证书、限流、日志都集中在一处。启动:
docker compose up -d --build看日志确认没有报错:
docker compose logs -f -
第 4 步: 配 Nginx 反向代理
安装 Nginx 后,在
/etc/nginx/conf.d/下建一个配置:server { listen 80; server_name example.com; location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }X-Forwarded-*这几行不要省,否则应用里拿到的客户端 IP 全是 127.0.0.1,日志和限流都会失真。校验并生效:
nginx -t && systemctl reload nginxHTTPS 配置见域名与 SSL 那篇教程。
-
第 5 步: 验证开机自启真的生效
这一步别跳过。 很多部署看起来成功,重启一次机器就露馅。
确认 Docker 服务本身开机启动:
systemctl enable docker systemctl is-enabled docker # 应输出 enabled然后直接重启验证:
reboot重连后检查:
docker ps容器在列表里,才算真的部署完成。如果没起来,用
docker ps -a看退出状态,再docker logs <容器名>看原因。 -
第 6 步: 日常更新怎么发版
代码更新后重建:
git pull docker compose up -d --buildcompose 会重建镜像并替换容器,旧容器自动停止。
注意:容器内不要存持久数据。数据库、上传的文件都挂 volume 或放外部服务,否则一次
up -d --build就全没了。这是新手最常踩的坑。
常见问题与排查
| 现象 | 原因 | 处理方式 |
|---|---|---|
| docker compose 命令不存在 | 装的是旧版 Docker,或 compose 插件未安装 | 用 docker compose version(不带横线)确认。不存在则安装 docker-compose-plugin 包,或升级 Docker 到较新版本 |
| 容器启动后立刻退出,docker ps 看不到 | 应用启动即崩溃,通常是配置缺失或端口冲突 | 用 docker ps -a 找到容器,docker logs <容器名> 看具体错误。多数是环境变量没传、依赖的服务连不上、或端口已被占用 |
| 构建镜像极慢,或 npm install 卡住 | 机器到 npm 源的网络不理想,或 alpine 镜像缺少编译依赖 | 换 npm 镜像源(npm config set registry);原生模块编译失败时改用 node:20-slim 镜像,或在 Dockerfile 里补装构建工具 |
| 重启机器后容器没了 | 没配 restart 策略,且 Docker 服务未设为开机启动 | 在 compose 里加 restart: unless-stopped,并执行 systemctl enable docker。改完后务必重启一次验证 |
| Nginx 反代返回 502 | 容器没在跑,或监听地址不匹配 | 确认容器状态与日志;确认容器内的应用监听的是 0.0.0.0 而不是 127.0.0.1——容器内监听回环的话,宿主机是访问不到的 |
接下来可能要看
本站含联盟链接。你通过这些链接购买,价格不变,我们会获得佣金。 详情