关于 kamal-coder
kamal-coder 是用于配置和管理 Kamal 2 部署的技能,面向将容器化应用部署到服务器的团队。内容涵盖部署配置、代理与密钥、多角色服务及日常运维。
主要功能
- 01配置 Kamal 2 部署
- 02设置 Web 与作业角色
- 03配置代理、SSL 和健康检查
- 04管理密钥与环境覆盖项
- 05执行部署、回滚和调试
- 06配置构建器与附属服务
适用场景
- 01设置生产或预发布部署
- 02在服务器上运行 Web 和作业容器
- 03配置 SSL 与健康检查
- 04查看日志或回滚版本
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ majesticlabs-dev/ majestic-marketplace --skill kamal-coder安装后在 Claude Code 中输入/kamal-coder确认已加载。
附带文件references/docker-patterns.mdreferences/request-flow.md
详细介绍
Kamal 2 Coder
服务器需要 Docker、SSH 访问权限,并开放 22/80/443 端口。使用 Ansible 或 cloud-init 进行配置。
配置:config/deploy.yml
最简配置
service: myapp
image: myapp
servers:
web:
- 203.0.113.10
proxy:
ssl: true
host: myapp.com
registry:
username: username
password:
- KAMAL_REGISTRY_PASSWORD
env:
clear:
RAILS_ENV: production
RAILS_LOG_TO_STDOUT: "true"
secret:
- RAILS_MASTER_KEY
多角色配置(Web + 作业 Worker)
service: myapp
image: myapp
servers:
web:
- 203.0.113.10
job:
hosts:
- 203.0.113.10
cmd: bin/jobs start
proxy:
ssl: true
host: myapp.com
registry:
username: username
password:
- KAMAL_REGISTRY_PASSWORD
env:
clear:
RAILS_ENV: production
SOLID_QUEUE_IN_PUMA: false
secret:
- RAILS_MASTER_KEY
作业 Worker 说明:
cmd: bin/jobs start会在单独的容器中运行 Solid Queue- 设置
SOLID_QUEUE_IN_PUMA: false以禁用进程内队列 - 作业角色没有代理 — 只有 Web 角色提供 HTTP 流量服务
使用本地 Registry
避免依赖 Docker Hub、受到速率限制并产生外部费用:
registry:
server: localhost:5555
username: ignored
password:
- KAMAL_REGISTRY_PASSWORD
将 Registry 作为附件服务部署:
accessories:
registry:
image: registry:2
host: 203.0.113.10
port: "5555:5000"
volumes:
- registry_data:/var/lib/registry
使用附件服务
accessories:
db:
image: postgres:16
host: 203.0.113.10
port: 5432
env:
clear:
POSTGRES_DB: myapp_production
secret:
- POSTGRES_PASSWORD
directories:
- data:/var/lib/postgresql/data
options:
shm-size: 256m
redis:
image: redis:7-alpine
host: 203.0.113.10
port: 6379
directories:
- data:/data
cmd: redis-server --appendonly yes
使用 Docker 卷实现持久化
对于 SQLite + ActiveStorage 应用,请挂载一个命名卷:
servers:
web:
hosts:
- 203.0.113.10
volumes:
- myapp_storage:/rails/storage
labels:
docker-volume-backup.stop-during-backup: "true"
job:
hosts:
- 203.0.113.10
cmd: bin/jobs start
volumes:
- myapp_storage:/rails/storage
Web 容器和作业容器共享同一个卷,以便访问数据库。
代理配置(kamal-proxy)
Kamal 2 使用 kamal-proxy(而不是 Traefik)。它负责 SSL 终止、路由和零停机部署。
基本 SSL
proxy:
ssl: true
host: myapp.com
自动配置 Let's Encrypt 证书 — 无需手动管理证书。
自定义端口
proxy:
ssl: true
host: myapp.com
app_port: 3000
多个主机
proxy:
ssl: true
hosts:
- myapp.com
- www.myapp.com
健康检查
proxy:
ssl: true
host: myapp.com
healthcheck:
path: /up
interval: 3
timeout: 3
响应超时
proxy:
ssl: true
host: myapp.com
response_timeout: 30
密钥:.kamal/secrets
Kamal 从 .kamal/secrets(已加入 Git 忽略)读取密钥。
使用 1Password CLI
KAMAL_REGISTRY_PASSWORD=$(op read "op://Infrastructure/DockerHub/password")
RAILS_MASTER_KEY=$(op read "op://MyApp/production/master_key")
DATABASE_URL=$(op read "op://MyApp/production/database_url")
使用环境变量
KAMAL_REGISTRY_PASSWORD=$DOCKERHUB_TOKEN
RAILS_MASTER_KEY=$RAILS_MASTER_KEY
DATABASE_URL=$DATABASE_URL
多环境配置
# config/deploy.yml — base config
service: myapp
# config/deploy.staging.yml — overrides
service: myapp-staging
servers:
web:
- 203.0.113.20
proxy:
host: staging.myapp.com
# .kamal/secrets.staging
RAILS_MASTER_KEY=$(op read "op://MyApp/staging/master_key")
使用以下命令部署:kamal deploy -d staging
常用命令
首次部署
# One-time: installs kamal-proxy, pushes image, deploys
kamal setup
# Subsequent: builds, pushes, rolling restart
kamal deploy
日常操作
kamal deploy # Deploy latest
kamal deploy --version=abc123 # Deploy specific version
kamal deploy -d staging # Deploy to staging
kamal redeploy # Redeploy without building
回滚
kamal app containers # List available versions
kamal rollback <version> # Rollback to specific version
调试
kamal app exec --interactive bash # Shell into container
kamal app logs -f # Tail logs
kamal app exec --interactive "bin/rails console" # Rails console
kamal app exec "bin/rails db:migrate" # Run migrations
附件服务
kamal accessory boot all # Start all accessories
kamal accessory reboot db # Restart specific accessory
kamal accessory exec db --interactive "psql -U postgres"
kamal accessory logs litestream # View accessory logs
Builder 配置
原生构建
builder:
arch: amd64
多架构构建
builder:
multiarch: true
远程 Builder
builder:
remote:
arch: amd64
host: ssh://builder@build-server
构建参数
builder:
args:
RUBY_VERSION: "3.3.0"
钩子
部署前
# .kamal/hooks/pre-deploy
#!/bin/sh
echo "Running pre-deploy checks..."
部署后
# .kamal/hooks/post-deploy
#!/bin/sh
echo "Deploy complete: $(date)"
curl -s https://notify.example.com/deploy
配置工作流
Ansible + Kamal 流水线
# 1. Ansible: Configure server
ansible-playbook -i hosts.ini playbook.yml
# 2. Kamal: Bootstrap and deploy
kamal setup
Ansible 应配置的内容
| 任务 | 用途 |
|---|---|
| 安装 Docker | 容器运行时 |
| 配置 fail2ban | 防止 SSH 入侵 |
| 设置 UFW | 防火墙(22、80、443) |
| 启用 NTP | 时间同步 |
| 创建交换空间 | 防止内存溢出 |
| 强化 SSH 安全 | 禁用密码身份验证和 root 登录 |
| 无人值守升级 | 自动安装安全补丁 |
Litestream 备份附件服务
对于 SQLite 应用,可将 Litestream 添加为附件服务(完整配置请参阅 litestream-coder):
accessories:
litestream:
image: litestream/litestream:0.3
host: 203.0.113.10
cmd: replicate
volumes:
- myapp_storage:/rails/storage:ro
files:
- config/litestream.yml:/etc/litestream.yml
env:
secret:
- LITESTREAM_ACCESS_KEY_ID
- LITESTREAM_SECRET_ACCESS_KEY
将存储挂载为只读(:ro)— Litestream 只会读取 WAL 文件。
目录结构
myapp/
├── config/
│ ├── deploy.yml # Main Kamal config
│ └── deploy.staging.yml # Staging overrides
├── .kamal/
│ ├── secrets # Production secrets (git-ignored)
│ ├── secrets.staging # Staging secrets (git-ignored)
│ └── hooks/
│ ├── pre-deploy
│ └── post-deploy
├── Dockerfile # Application container
└── docker-entrypoint.sh # Entrypoint script
故障排除
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 连接被拒绝 | Docker 未运行 | 运行 kamal setup 或检查 Docker 服务 |
| 权限被拒绝 | SSH 密钥未获授权 | 检查服务器的 authorized_keys |
| 健康检查失败 | 应用未启动 | 检查 kamal app logs |
| Registry 身份验证失败 | 凭据错误 | 检查 .kamal/secrets |
| 502 Bad Gateway | 容器未通过健康检查 | 延长健康检查超时时间 |
| 未签发 SSL 证书 | DNS 未指向服务器 | 检查 DNS A 记录 |
| 部署后资源返回 404 | 卷未挂载 | 检查 deploy.yml 中的 volumes: |
参考资料
- references/request-flow.md — 请求架构和 Cloudflare 集成
- references/docker-patterns.md — 生产环境 Dockerfile、入口点和卷模式
评论
支持 Markdown