Skip to content

API 端部署

本文档说明如何将 todo_api(Rails 8 JSON API)打包为 Docker 镜像并部署运行。

镜像基于官方 Dockerfile(多阶段构建:Ruby 3.4 + Thruster + Puma),最终镜像默认监听 容器 80 端口,对外通过 -p 映射。


1. 前置依赖

组件版本要求说明
PostgreSQL14+主数据库,需可网络访问
Docker20.10+运行容器
RAILS_MASTER_KEY生产环境读取加密凭据所需(见 §5)

默认 SOLID_QUEUE_IN_PUMA: true,后台任务(Solid Queue)随 Web 进程一起运行,无需独立 Redis / Valkey


2. 构建镜像

方式 A:本地构建

bash
cd todo_api
docker build -t itodo-api:latest .

方式 B:通过 CNB Cloud Native Build 自动构建

仓库根目录 .cnb.yml 已配置在 main 分支 push 时自动构建并推送两个镜像:

  • docker.cnb.cool/<组织>/<项目>/api:latest
  • docker.cnb.cool/<组织>/<项目>/web:latest

(web 端镜像用法见 Web 端部署。)

只需 git pushmain,CNB 会自动完成构建与推送,无需本地构建。


3. 环境变量

启动容器时通过 -e.env 文件注入:

变量必填默认值说明
RAILS_MASTER_KEY是*解密 config/credentials/production.yml.enc
DB_HOSTlocalhostPostgreSQL 主机地址
DB_PORT5432PostgreSQL 端口
DB_USERNAMEpostgres数据库用户名
DB_PASSWORD数据库密码
DB_NAMEtodo_api_production数据库名
RAILS_ENVproduction容器内已固化,无需覆盖
SOLID_QUEUE_IN_PUMAtrue在 Puma 内运行任务队列
DEEPSEEK_API_KEYAI 助手(DeepSeek)Key
DEEPSEEK_BASE_URLhttps://api.deepseek.comAI 接口地址
DEEPSEEK_MODELdeepseek-v4-flashAI 模型

* 若生产凭据文件不存在或无需加密凭据,可省略;但 Rails 8 生产模式默认读取 production credentials,缺失会启动失败,建议始终提供。


4. 部署方式

方式一:docker run(已有外部 PostgreSQL)

bash
docker run -d --name itodo-api \
  -p 3000:80 \
  -e RAILS_MASTER_KEY=你的master_key \
  -e DB_HOST=你的pg主机 \
  -e DB_PORT=5432 \
  -e DB_USERNAME=postgres \
  -e DB_PASSWORD=你的密码 \
  -e DB_NAME=todo_api_production \
  itodo-api:latest

容器启动时 entrypoint 会自动执行 rails db:prepare(建库 + 执行迁移),首次启动稍慢属正常。

方式二:docker-compose 一键部署(含 PostgreSQL)

新建 docker-compose.yml

yaml
services:
  db:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: your_db_password
      POSTGRES_DB: todo_api_production
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 10

  api:
    image: itodo-api:latest   # 或 CNB 镜像地址 docker.cnb.cool/<组织>/<项目>/api:latest
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "3000:80"
    environment:
      RAILS_MASTER_KEY: your_master_key
      DB_HOST: db
      DB_PORT: 5432
      DB_USERNAME: postgres
      DB_PASSWORD: your_db_password
      DB_NAME: todo_api_production
      SOLID_QUEUE_IN_PUMA: "true"

volumes:
  pgdata:

启动:

bash
docker compose up -d

方式三:Kamal 部署(已有 config/deploy.yml

项目已内置 Kamal 配置,适合多机/生产环境发布:

bash
cd todo_api
# 在 .kamal/secrets 中配置 REGISTRY_PASSWORD、RAILS_MASTER_KEY 等
kamal setup        # 首次:创建容器、拉镜像、迁移数据库
kamal deploy       # 后续发布
kamal logs -f      # 查看日志

Kamal 会按 config/deploy.yml 将镜像推到 registry.server 并管理容器生命周期。


5. 关于 RAILS_MASTER_KEY

Rails 生产环境通过 master key 解密 config/credentials/production.yml.enc

  • 若你本地有 config/credentials/production.key,其内容即为 master key 的值;
  • 将其作为环境变量 RAILS_MASTER_KEY 传入容器即可;
  • 若项目未使用加密凭据,可临时用 bin/rails credentials:edit --environment production 生成,或确保生产环境不依赖加密 secrets。

6. 健康检查与验证

容器暴露 GET /api/health,部署后验证:

bash
curl http://localhost:3000/api/health

预期返回包含服务状态的 JSON(如 {"status":"ok"} 或类似结构)。

其他可用接口(详见 README.md):

  • GET/POST/PUT/DELETE /api/tasks — 任务 CRUD
  • GET/POST/PUT/DELETE /api/task_lists/api/tags
  • POST /api/mcp — MCP 接口
  • GET/PUT /api/ai/settingsPOST /api/ai/chat — AI 助手

7. 与 Web 前端联调

Web 端默认访问 http://localhost:3000/api。两种方式:

  1. 独立部署 Web 静态站:在浏览器端「个人中心 - 服务端配置」手动填写 http://<api主机>:3000/api
  2. CNB 构建的 Web 镜像:Nginx 已内置 /api 反代(默认指向 http://todo_api:80),同一 docker 网络下可直接用容器名 todo_api 互通;也可用环境变量 API_PROXY_PASS 覆盖目标地址。

示例(同网络联调):

bash
docker network create itodo-net
docker run -d --network itodo-net --name todo_api -e RAILS_MASTER_KEY=... -e DB_HOST=db ... itodo-api:latest
docker run -d --network itodo-net --name todo_web -p 8080:80 \
  -e API_PROXY_PASS=http://todo_api:80 \
  docker.cnb.cool/<>/<>/web:latest

8. 常见问题

现象原因 / 解决
启动报 Missing RAILS_MASTER_KEY生产环境需要解密凭据,传入 RAILS_MASTER_KEY
数据库连不上检查 DB_HOST/DB_PORT/DB_USERNAME/DB_PASSWORD,确认网络可达、PG 已就绪
首次启动慢entrypoint 正在 db:prepare(建库+迁移),等待即可
跨域 CORS 报错生产环境在 config/initializers/cors.rb 配置允许的 origins
推送镜像 403镜像仓库路径/权限问题,确认 CNB 仓库存在且 CI 凭证有写权限

9. 数据备份

PostgreSQL 数据持久化在 pgdata 卷(方式二)或你自建的数据库。备份示例:

bash
docker exec -t <pg容> pg_dump -U postgres todo_api_production > backup.sql

基于 VitePress 构建