Rails 8.0.2 + Kamal 2生产环境部署setup失败求助
问题现象
执行kamal setup后报错:
ERROR Failed to boot web on [URL]
INFO First web container is unhealthy on [URL], not booting any other roles
部署脚本最终提示:
Finished all in 78.8 seconds
ERROR (SSHKit::Command::Failed): Exception while executing on host [URL]: docker exit status: 1
docker stdout: Nothing written
docker stderr: Error: target failed to become healthy within configured timeout (30s)
服务器上执行docker ps仅看到kamal-proxy容器运行:
docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cc0885bc70ed basecamp/kamal-proxy:v0.9.0 "kamal-proxy run" 4 hours ago Up 4 hours 0.0.0.0:80->80/tcp, [::]:80->80/tcp, 0.0.0.0:443->443/tcp, [::]:443->443/tcp kamal-proxy
已在DigitalOcean配置域名A记录,deploy配置文件如下:
# Name of your application. Used to uniquely configure containers. service: [SERVICE] # Name of the container image. image: [DOCKER USER]/[SERVICE] # Deploy to these servers. servers: web: - [URL] # Enable SSL auto certification via Let's Encrypt and allow for multiple apps on a single web server. # Remove this section when using multiple web servers and ensure you terminate SSL at your load balancer. # # Note: If using Cloudflare, set encryption mode in SSL/TLS setting to "Full" to enable CF-to-app encryption. proxy: ssl: true host: [URL] # Credentials for your image host. registry: # Specify the registry server, if you're not using Docker Hub # server: registry.digitalocean.com / ghcr.io / ... username: [DOCKER USER] # Always use an access token rather than real password when possible. password: - KAMAL_REGISTRY_PASSWORD # Inject ENV variables into containers (secrets come from .kamal/secrets). env: secret: - RAILS_MASTER_KEY - MYSQL_ROOT_PASSWORD clear: # Run the Solid Queue Supervisor inside the web server's Puma process to do jobs. # When you start using multiple servers, you should split out job processing to a dedicated machine. SOLID_QUEUE_IN_PUMA: true DB_HOST: [SERVICE]-db # Log everything from Rails RAILS_LOG_LEVEL: debug # Aliases are triggered with "bin/kamal <alias>". You can overwrite arguments on invocation: # "bin/kamal logs -r job" will tail logs from the first server in the job section. aliases: console: app exec --interactive --reuse "bin/rails console" shell: app exec --interactive --reuse "bash" logs: app logs -f dbc: app exec --interactive --reuse "bin/rails dbconsole" # Use a persistent storage volume for sqlite database files and local Active Storage files. # Recommended to change this to a mounted volume path that is backed up off server. volumes: - "[SERVICE]_storage:/rails/storage" # Bridge fingerprinted assets, like JS and CSS, between versions to avoid # hitting 404 on in-flight requests. Combines all files from new and old # version inside the asset_path. asset_path: /rails/public/assets # Configure the image builder. builder: arch: amd64 # # Build image via remote server (useful for faster amd64 builds on arm64 computers) # remote: ssh://docker@docker-builder-server # # # Pass arguments and secrets to the Docker build process # args: # RUBY_VERSION: ruby-3.4.7 # secrets: # - GITHUB_TOKEN # - RAILS_MASTER_KEY # Use a different ssh user than root # ssh: # user: app # Use accessory services (secrets come from .kamal/secrets). accessories: db: image: mysql:8.0 host: [URL] port: "127.0.0.1:3306:3306" env: clear: MYSQL_ROOT_HOST: '%' secret: - MYSQL_ROOT_PASSWORD files: - db/production.sql:/docker-entrypoint-initdb.d/setup.sql directories: - data:/var/lib/mysql
排查与修复步骤
1. 查看Web容器启动日志
容器可能启动后立即退出,用以下命令查看历史容器日志:
docker logs $(docker ps -aq --filter name=[SERVICE]-web)
重点排查Rails启动错误,比如数据库连接失败、依赖缺失、环境变量未正确加载等。
2. 检查数据库服务状态
确认MySQL容器是否正常运行:
docker ps --filter name=[SERVICE]-db
如果未运行,查看数据库启动日志:
docker logs $(docker ps -aq --filter name=[SERVICE]-db)
常见问题:
db/production.sql文件不存在或权限错误.kamal/secrets中未正确配置MYSQL_ROOT_PASSWORD- SQL初始化脚本存在语法错误
3. 修正环境变量缩进问题
deploy.yml中env.clear部分缩进错误,会导致环境变量无法正确注入:
原错误配置:
clear: # Run the Solid Queue Supervisor inside the web server's Puma process to do jobs. # When you start using multiple servers, you should split out job processing to a dedicated machine. SOLID_QUEUE_IN_PUMA: true DB_HOST: [SERVICE]-db # Log everything from Rails RAILS_LOG_LEVEL: debug
修正后:
clear: # Run the Solid Queue Supervisor inside the web server's Puma process to do jobs. # When you start using multiple servers, you should split out job processing to a dedicated machine. SOLID_QUEUE_IN_PUMA: true DB_HOST: [SERVICE]-db # Log everything from Rails RAILS_LOG_LEVEL: debug
YAML对缩进敏感,错误缩进会导致DB_HOST等变量无法被Rails读取,进而引发数据库连接失败。
4. 延长健康检查超时时间
如果Rails容器启动较慢(比如资产预编译耗时久),可在deploy.yml中延长健康检查超时:
servers: web: - [URL] health_check: timeout: 60 # 延长至60秒
5. 确认SSL配置有效性
开启proxy.ssl: true后需确保:
- 域名A记录已生效(用
nslookup [URL]验证) - 服务器80/443端口未被其他服务占用
- 若使用Cloudflare,SSL模式已设置为"Full"(如有配置)
6. 手动启动容器测试
尝试手动启动Web容器,直接查看实时错误:
kamal app start --debug
内容的提问来源于stack exchange,提问作者willyab

