爱名网(22科技集团)

SSR 项目 Docker 化部署

2026-07-21 13:51老强


SSR 项目上线,最怕两件事:本地能跑,服务器上环境不一样;构建命令太多,时间一长没人记得该跑哪几个。

所以我更倾向于把它收进 Docker 里:构建怎么跑、服务怎么启动、端口怎么暴露,都写进项目。服务器只负责执行一条命令。

一、先看项目怎么跑

不要一上来就写 Dockerfile。先看项目自己的脚本。

{
  "scripts": {
    "build:vike": "vite build --ssr",
    "build:dist": "vite build",
    "serve:ssr": "node server.js"
  }
}
构建阶段:安装依赖,生成 SSR 和前端静态产物
运行阶段:只带生产依赖和构建产物,启动 Node 服务

二、Dockerfile 用多阶段

SSR 项目通常需要构建产物,镜像里没必要留下完整源码和开发依赖。

ARG NODE_IMAGE=node:22-alpine

FROM ${NODE_IMAGE} AS build

WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .
RUN npm run build:vike
RUN npm run build:dist

FROM ${NODE_IMAGE} AS runtime

WORKDIR /app
ENV NODE_ENV=production
ENV PORT=50023

COPY package*.json ./
RUN npm ci --omit=dev

COPY --from=build /app/server.js ./server.js
COPY --from=build /app/server ./server
COPY --from=build /app/dist ./dist
COPY --from=build /app/dist-vike ./dist-vike

EXPOSE 50023

CMD ["npm", "run", "serve:ssr"]

基础镜像用 NODE_IMAGE 做成变量,线上拉不到 Docker Hub 时,可以临时换镜像源,不用改 Dockerfile。

三、Compose 不要太新

本地可能用新版 docker compose,服务器上经常还是旧版 docker-compose。

version: "3.3"

services:
  ssr-app:
    build:
      context: ..
      dockerfile: docker/DockerFile
      args:
        NODE_IMAGE: ${NODE_IMAGE:-node:22-alpine}
    container_name: ssr-app
    restart: unless-stopped
    environment:
      NODE_ENV: production
      PORT: 50023
    ports:
      - "50023:50023"

为了兼容老服务器,可以保留 version。新版 Docker 可能有提示,但一般只是警告。

四、镜像拉不下来怎么办

线上构建时,如果看到下面这种错误,多半是服务器连不上 Docker Hub。

Get https://registry-1.docker.io/v2/: connect: connection refused

前面把基础镜像做成变量,就是为了解这个问题。

NODE_IMAGE=registry.example.com/library/node:22-alpine docker-compose up -d --build

五、README 要写短

Docker 配好后,在 docker/README.md 里放几条够用的命令就行。

# 构建并启动
docker-compose up -d --build

# 查看状态
docker-compose ps

# 查看日志
docker-compose logs -f ssr-app

# 停止服务
docker-compose down

六、先本地验证容器

镜像能构建,不代表服务能用。至少请求一次入口页。

docker-compose up -d --build
curl -I http://127.0.0.1:50023/site
镜像能构建
容器能启动
SSR 路由能响应

七、Nginx 怎么接

如果 SSR 只替换 /site,Nginx 可以直接把 /site 代理给容器。

location = /site {
    proxy_redirect off;
    proxy_http_version 1.1;

    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-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;
    proxy_set_header X-Request-Id $request_id;

    proxy_pass http://ssr_backend;
}

location ^~ /site/ {
    proxy_redirect off;
    proxy_http_version 1.1;

    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-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;
    proxy_set_header X-Request-Id $request_id;

    proxy_pass http://ssr_backend;
}

八、最后

SSR 项目 Docker 化,核心不是写一个多漂亮的 Dockerfile,而是把部署动作固定下来。

构建命令固定
运行命令固定
端口固定
镜像源可替换
Compose 兼容旧服务器
Nginx 只接指定路径
上线前 curl 验证

项目上线这件事,少一点凭记忆操作,就已经省很多事了。

曝光406浏览25