跳到正文

用 Docker 部署 Node 应用并让它开机自启

把 Node 应用跑在 Docker 里,换来的是环境一致和一条命令迁移。这篇走完整流程:装 Docker、写 Dockerfile、用 compose 编排、配 Nginx 反代、以及最容易漏掉的开机自启——很多人的容器重启机器后就没了,问题都出在这一步。

40 分钟 难度:中等 6 个步骤更新于 2026-09-13

开始之前

  • 一台 VPS,建议 1GB 及以上内存
  • 能 SSH 登录并有 sudo / root 权限
  • 本地有一个能跑起来的 Node 应用(有 package.json)
  • 了解基础的命令行操作

操作步骤

  1. 第 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. 第 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 cinpm install 更严格也更可复现,CI 和部署都该用它
    • alpine 镜像体积小,但某些需要编译的原生模块会有兼容问题,遇到编译错误换成 node:20-slim

    再加一个 .dockerignore,至少排除 node_modules.git,否则镜像会大得离谱。

  3. 第 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. 第 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 nginx

    HTTPS 配置见域名与 SSL 那篇教程。

  5. 第 5 步: 验证开机自启真的生效

    这一步别跳过。 很多部署看起来成功,重启一次机器就露馅。

    确认 Docker 服务本身开机启动:

    systemctl enable docker
    systemctl is-enabled docker    # 应输出 enabled

    然后直接重启验证:

    reboot

    重连后检查:

    docker ps

    容器在列表里,才算真的部署完成。如果没起来,用 docker ps -a 看退出状态,再 docker logs <容器名> 看原因。

  6. 第 6 步: 日常更新怎么发版

    代码更新后重建:

    git pull
    docker compose up -d --build

    compose 会重建镜像并替换容器,旧容器自动停止。

    注意:容器内不要存持久数据。数据库、上传的文件都挂 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——容器内监听回环的话,宿主机是访问不到的

需要一台机器来练手?

入门套餐折算月成本最低,30 天内可全额退款,适合用来把流程走通一遍。

本站含联盟链接。你通过这些链接购买,价格不变,我们会获得佣金。 详情