Logo

使用 Kamal 2 部署 Rails 应用实践指南

avatar jayce 22 Nov 2024

使用 Kamal 2 部署 Rails 应用实践指南

前言

Kamal 2 是一个用于部署 Rails 应用的工具,但目前相关文档比较分散且不够完整。本文将分享笔者在使用 Kamal 2 部署过程中的实践经验,希望能给大家一些参考。

完整配置示例

# config/deploy.staging.yml

# puma 服务名
service: ai-hub-server-staging
# 命名空间 / 镜像名
image: jayce9210/ai-hub-server-staging

servers:
  web:
    hosts:
      - your-host
  sidekiq:
    cmd: bundle exec sidekiq
    hosts:
      - your-host

proxy:
  ssl: true
  host: ai-hub-kamal.beansmile-dev.com
  # kamal-proxy connects to your container over port 80, use `app_port` to specify a different port.
  app_port: 3000

registry:
  # 你的 Docker Hub 用户名和密码
  # 使用阿里云服务
  server: crpi-9ja5ymdca5joh9vj.cn-shenzhen.personal.cr.aliyuncs.com
  username: 396803555@qq.com
  password:
    - AI_HUB_KAMAL_REGISTRY_PASSWORD

builder:
  arch: amd64
  # 指定 Dockerfile 路径
  dockerfile: Dockerfile.staging

# 日志配置
logging:
  options:
    max-size: 100m

env:
  clear:
    HOST: http://ai-hub-kamal.beansmile-dev.com
    DB_HOST: ai-hub-server-staging-db
    REDIS_HOST: redis://ai-hub-server-staging-redis:6379/0
  secret:
    - RAILS_MASTER_KEY
    # 需要在这里声明,不然 database.yml 没法获取到
    # connection to server at "172.17.1.2", port 5432 failed: fe_sendauth: no password supplied
    - AI_HUB_KAMAL_POSTGRES_PASSWORD

accessories:
  db:
    image: postgres:15
    host: your-host # 你的服务器 IP
    env:
      clear:
        POSTGRES_USER: deploy
        POSTGRES_DB: ai-hub-server-staging
        POSTGRES_PASSWORD: AI_HUB_KAMAL_POSTGRES_PASSWORD
    volumes:
      - /var/lib/postgresql/data:/var/lib/postgresql/data
  redis:
    image: redis:7
    host: your-host # 你的服务器 IP

aliases:
  console: app exec --reuse -i "bin/rails console"

数据库配置示例:

# database.yml.example
staging:
  <<: *default
  database: ai_hub_server_staging
  username: deploy
  password: <%= ENV['AI_HUB_KAMAL_POSTGRES_PASSWORD'] %>

Docker 网络说明

Kamal 2 会创建一个名为 kamal 的 Docker 网络,并将所有容器加入其中。因此:

  • 不能使用 IP 或 localhost
  • Redis 地址应该是 redis://ai-hub-server-staging-redis:6379/0
  • 数据库地址应该是 ai-hub-server-staging-db

例如项目中使用 redis,进入服务器上docker ps 找到 name ai-hub-server-staging-redis
那 REDIS_HOST 就应该是redis:/ai-hub-server-staging-redis:6379/0

env:
  clear:
    HOST: http://ai-hub-kamal.beansmile-dev.com
    DB_HOST: ai-hub-server-staging-db
    REDIS_HOST: redis://ai-hub-server-staging-redis:6379/0

部署步骤

1. 初始化 Kamal

kamal init

2. 配置 deploy.yml 和 Dockerfile

3. 运行 setup 命令

kamal setup -c "config/deploy.staging.yml"

如果有 accessories 此时比如 pg, redis 等容器会启动好,可以看到容器名称。

4. 调整 Redis 配置

env:
  clear:
    HOST: http://ai-hub-kamal.beansmile-dev.com
    DB_HOST: ai-hub-server-staging-db
    REDIS_HOST: redis://ai-hub-server-staging-redis:6379/0

5. 部署应用

kamal deploy -c "config/deploy.staging.yml"

需要留意的是每次部署都是拿本地最后一次 commit 的代码部署的。 所以修改后要记得提交。

常见问题及解决方案

1. Docker Hub 访问慢

解决方案:

  • 使用阿里云镜像服务
  • 或在 Docker Daemon 配置代理:

即使使用了阿里云镜像,部署最后还是无法 pull kamal-proxy 镜像。挂代理解决

# /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:10801"
Environment="HTTPS_PROXY=http://127.0.0.1:10801"

2. .kamal/secrets 环境变量问题

需要在系统环境变量中配置:

# bash.rc / zshrc

export AI_HUB_KAMAL_REGISTRY_PASSWORD=
export AI_HUB_KAMAL_POSTGRES_PASSWORD=
# .kamal/secrets
AI_HUB_KAMAL_REGISTRY_PASSWORD=$AI_HUB_KAMAL_REGISTRY_PASSWORD
AI_HUB_KAMAL_POSTGRES_PASSWORD=$AI_HUB_KAMAL_POSTGRES_PASSWORD

3. Rails 日志无法输出到 Docker

在 config/environments/staging.rb 中添加:

config.logger = ActiveSupport::Logger.new(STDOUT)
  .tap  { |logger| logger.formatter = ::Logger::Formatter.new }
  .then { |logger| ActiveSupport::TaggedLogging.new(logger) }

确认 docker 日志格式:

> docker inspect --format='{{.HostConfig.LogConfig.Type}}' 9b0b24c16554
json-file

kamal 相关配置项

logging:
	# 默认就是这个
  driver: json-file
  options:
    max-size: 100m

4. SSL 配置

Kamal-proxy 支持通过 Let’s Encrypt 自动配置 HTTPS:

proxy:
  ssl: true
  host: ai-hub-kamal.beansmile-dev.com
  # kamal-proxy connects to your container over port 80, use `app_port` to specify a different port.
  app_port: 3000

常用命令

进入容器查看详情

docker exec -it CONTAINER_ID bash

解除部署锁

kamal lock release
# 或
kamal lock release -c "config/deploy.staging.yml"

Rails Console

# deploy.staging.yml
# 配置别名
aliases:
  console: app exec --reuse -i "bin/rails console"

# 命令行使用
kamal console -c "config/deploy.staging.yml"

查看远程日志

kamal app logs  -c "config/deploy.staging.yml"

实用配置参数

Rails 服务端口映射

servers:
  web:
    hosts:
      - your-host
    options:
      publish:
        - "4022:3000"

禁用 Kamal Proxy

servers:
  web:
    hosts:
      - your-host
    proxy: false

总结

Kamal 2 是一个基于 Docker 的 Rails 应用部署工具。相比传统的 Capistrano 部署方案,它有以下优势和不足:

Kamal 2 的优势

  1. 容器化部署

    • 应用环境完全隔离,避免系统依赖冲突
    • 保证开发环境和生产环境的一致性
    • 便于横向扩展和迁移
  2. 配置简单

    • 单一 YAML 配置文件
    • 内置 SSL 支持,自动申请和续期证书
    • 开箱即用的健康检查和零停机部署
  3. 运维友好

    • 内置日志管理和容量限制
    • 支持一键回滚
    • 提供便捷的远程调试工具

Capistrano 的优势

  1. 成熟稳定

    • 使用历史长,社区资源丰富
    • 问题解决方案完善
    • 大量现成的部署脚本可用
  2. 资源占用小

    • 不需要运行容器,系统开销更小
    • 适合资源受限的小型服务器
  3. 灵活性高

    • 可以精细控制部署流程的每个步骤
    • 支持复杂的自定义部署逻辑
    • 与现有系统集成更容易

Kamal 2 代表了容器化时代的部署趋势,但这并不意味着它适合所有场景。选择部署工具时,需要根据项目规模、团队情况、服务器资源等因素综合考虑。无论选择哪种工具,确保它能满足你的部署需求才是最重要的。

Tags
rails
部署
Kamal
Kamal 2
Puma