单台 VPS 部署 API(上):环境准备与 Docker Hub 镜像发布

单台 VPS 部署 API(上):环境准备与 Docker Hub 镜像发布

这套部署方式很直接:在 Mac + OrbStack 上开发和构建镜像,把带版本号的镜像推送到 Docker Hub,最后由 Ubuntu VPS 通过 Docker Compose 运行。VPS 上只放部署文件、环境变量、Nginx 配置和数据卷,不需要上传 Git 仓库或 src 目录。

注意:多阶段构建不能绝对保护源码。最终镜像里可以不包含 TypeScript 文件,但编译后的 JavaScript 仍能被分析。密码、令牌和私钥不要写进镜像。


一、环境说明

本地需要安装 OrbStack、Node.js LTS、npm 和 Git,并准备一个 Docker Hub 账号。下文在 macOS 上操作,PostgreSQL 跑在 OrbStack 容器里。

VPS 可以从下面的配置起步:

  • 系统:Ubuntu 24.04 LTS(或仍受支持的 LTS)
  • 配置:2 vCPU、4 GB RAM、40 GB 以上 SSD/NVMe
  • 网络:公网 IPv4,开放 TCP 80/443
  • 安全:SSH 仅对可信 IP 开放

1 GB 内存也能用来试验,不过 API、PostgreSQL 和 Docker 跑在一起时,余量会很小。


二、本地 PostgreSQL

创建 compose.dev.yml

services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_USER: app_user
      POSTGRES_PASSWORD: change-this-local-password
      POSTGRES_DB: app_db
    ports:
      - "127.0.0.1:5432:5432"
    volumes:
      - postgres_dev_data:/var/lib/postgresql/data
volumes:
  postgres_dev_data:

启动并验证:

docker compose -f compose.dev.yml up -d
docker compose -f compose.dev.yml exec postgres psql -U app_user -d app_db

本机运行 API 时的数据库连接字符串:

DATABASE_URL=postgresql://app_user:***@localhost:5432/app_db

端口绑定到 127.0.0.1 后,数据库只接受来自本机的连接。


三、构建生产 Docker 镜像

假设 npm run build 输出 dist,入口为 dist/server.js

FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY tsconfig*.json ./
COPY src ./src
RUN npm run build

FROM node:22-alpine AS production
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev && npm cache clean --force
COPY --from=build /app/dist ./dist
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]

创建 .dockerignore

node_modules
dist
.git
.env
.env.*
npm-debug.log*
compose*.yml

本地验证构建与运行:

docker build -t YOUR_DOCKERHUB_USER/backend-api:1.0.0 .
docker run --rm -p 3000:3000 YOUR_DOCKERHUB_USER/backend-api:1.0.0

如果项目使用 Prisma 或原生模块,构建镜像时可能还要补充生成或编译步骤,具体取决于项目依赖。


四、Docker Hub 如何选择

Docker Hub 的镜像地址格式是 docker.io/<用户名>/<镜像名>:<标签>,例如 docker.io/alice/backend-api:1.0.0。它的使用门槛不高,也很常见。业务 API 一般放在私有仓库中。

各容器仓库选型对比:

仓库 适用场景
Docker Hub 配置简单、使用广泛;业务镜像建议设为私有
GHCR 项目和 CI 都在 GitHub 时比较顺手
GitLab Container Registry 项目使用 GitLab CI 时省去额外集成
云厂商仓库 服务长期部署在同一家云厂商时可优先考虑

私有仓库和拉取额度会变化,以各平台官网当前政策为准。


五、推送镜像

先在 Docker Hub 创建名为 backend-api 的私有仓库,再用 Personal Access Token 登录:

docker login
docker build -t YOUR_DOCKERHUB_USER/backend-api:1.0.0 .
docker push YOUR_DOCKERHUB_USER/backend-api:1.0.0

如果需要,也可以附加 latest 标签:

docker tag YOUR_DOCKERHUB_USER/backend-api:1.0.0 YOUR_DOCKERHUB_USER/backend-api:latest
docker push YOUR_DOCKERHUB_USER/backend-api:latest

发布前检查这几项:

  • API 能连接本地 PostgreSQL,关键测试已经通过
  • 已提供 GET /health 健康检查端点
  • 镜像中没有密码、令牌等机密
  • 本次发布使用了新的版本标签

生产 Compose 应固定使用 1.0.0 之类的明确版本,便于回滚。


总结

到这里,本地环境和 PostgreSQL 已经可以运行,生产镜像也推送到了 Docker Hub。下一篇转到 Ubuntu VPS:拉取镜像、配置 Nginx,再申请并自动续期 HTTPS 证书。