跳转到内容

适配 Compose 项目

Tarsail 部署 Docker Compose 项目。它不会替代 Compose,也不会隐藏 Compose 的行为。

适配项目时,最稳妥的做法是让 Compose 文件足够明确:镜像标签、运行时环境文件、持久化 volume、健康检查和对外端口都应该在引入 Tarsail 前清楚可见。

每个服务在 docker compose config 解析后都必须有 image: 值。

services:
web:
build:
context: .
dockerfile: Dockerfile
image: my-app-web:${TARSAIL_RELEASE_ID:-local}

这样做的好处:

  • 本地开发可以使用 my-app-web:local
  • Tarsail 部署时会设置 TARSAIL_RELEASE_ID=<release-id>
  • 远端 Compose 使用的镜像标签正好是发布包里加载的标签。

引入 Tarsail 前,项目应该能用普通 Compose 构建:

Terminal window
docker compose -f compose.yaml config
docker compose -f compose.yaml build
docker compose -f compose.yaml up -d
docker compose -f compose.yaml ps

Tarsail 调用的是同一个 Docker Compose CLI。如果 Compose 本身不能在本地构建或运行,Tarsail 不会修复这个问题。

很多项目需要单独的生产配置:

compose.yaml
compose.production.yaml
tarsail.production.yml
.deploy/
production.env

这种情况下,让 Tarsail 指向生产 Compose 文件:

compose:
file: compose.production.yaml
env_file:
source: .deploy/production.env
target: shared/.env

运行:

Terminal window
tarsail --config tarsail.production.yml deploy

不要把密钥写死在 Compose 文件里

Section titled “不要把密钥写死在 Compose 文件里”

不要这样写:

services:
web:
environment:
DATABASE_URL: postgres://real-user:[email protected]:5432/app

改用环境变量:

services:
web:
environment:
DATABASE_URL: ${DATABASE_URL}
SESSION_SECRET: ${SESSION_SECRET}

把真实值放到被忽略的文件中,例如 .deploy/production.env,然后配置 compose.env_file

Tarsail 不配置 TLS、DNS、Nginx、Caddy、防火墙或云服务商规则。

直接 HTTP 服务:

services:
web:
image: my-app-web:${TARSAIL_RELEASE_ID:-local}
ports:
- "80:8080"

使用反向代理服务:

services:
reverse-proxy:
image: nginx:1.27-alpine
ports:
- "443:443"
volumes:
- ./shared/certs:/etc/nginx/certs:ro
- ./files/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
web:
condition: service_healthy
web:
image: my-app-web:${TARSAIL_RELEASE_ID:-local}
expose:
- "8080"

在 Tarsail 发布中,current/shared 指向远端 shared/ 目录,current/files 是当前激活发布的一部分。Tarsail 运行 Compose 时从目标路径执行:

Terminal window
docker compose -p my-app --env-file current/.tarsail.env --env-file shared/.env -f current/compose.yaml up -d

推荐使用从该命令看起来清晰的路径。例如:

volumes:
- ./current/files/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
- ./shared/certs:/etc/nginx/certs:ro

也可以把配置直接烘进镜像,避免主机路径挂载发布文件。

健康检查会让 docker compose ps 更有价值:

services:
web:
healthcheck:
test: ["CMD", "wget", "-q", "-O", "-", "http://127.0.0.1:8080/healthz"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s

Tarsail 目前不会在 docker compose up -d 后等待应用级健康状态;它会输出 Compose 状态。你的 Compose 文件应该暴露有意义的健康信息。

要显式表达持久化状态:

services:
db:
image: postgres:17-alpine
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:

Tarsail 回滚不会恢复 db-data

如果应用在部署时执行迁移,请让迁移行为在 Compose 文件里可见:

services:
migrate:
image: my-app-web:${TARSAIL_RELEASE_ID:-local}
command: ["my-app-migrate"]
restart: "no"
web:
image: my-app-web:${TARSAIL_RELEASE_ID:-local}
depends_on:
migrate:
condition: service_completed_successfully

Tarsail 可以打包多个 Compose 服务镜像:

services:
api:
build: ./api
image: my-app-api:${TARSAIL_RELEASE_ID:-local}
worker:
build: ./worker
image: my-app-worker:${TARSAIL_RELEASE_ID:-local}
web:
build: ./web
image: my-app-web:${TARSAIL_RELEASE_ID:-local}

每个服务名会成为 images/ 下的镜像 tar 文件名。服务名可以使用字母、数字、点、下划线和连字符。

创建发布包时,Tarsail 要求每个镜像都已存在于本地 Docker。

没有 build: 的服务需要提前在本地拉取或构建:

Terminal window
docker pull nginx:1.27-alpine
tarsail deploy

如果打包时本地缺少镜像,Tarsail 会在上传前失败。

使用 files 配置非密钥发布文件:

files:
- source: deploy/nginx
target: files/nginx

本地 source 可以是文件或目录,但不能是符号链接。目录中也不能包含符号链接。

target 必须位于 files/ 下。

my-app/
Dockerfile
compose.yaml
tarsail.yml
.deploy/
production.env
app.key
deploy/
nginx/
default.conf

可以提交:

  • Dockerfile
  • compose.yaml
  • 不包含私有基础设施信息的 tarsail.yml
  • deploy/ 下安全的文件;
  • .deploy/.gitignore.env.example 占位文件。

不要提交:

  • 真实 .deploy/*.env
  • 私钥;
  • 生产证书;
  • 数据库密码;
  • token;
  • 私有服务器清单。