Docker Compose启动Rails+Sidekiq容器报错排查求助
问题排查与修复方案
1. 处理 rm: can't remove '/graph/tmp/pids/server.pid': No such file or directory 错误
这个错误是因为你的entrypoint.sh中直接执行了删除server.pid的命令,但该文件不存在时rm会抛出异常。修改方式:
- 将
rm /graph/tmp/pids/server.pid替换为rm -f /graph/tmp/pids/server.pid(-f参数会忽略不存在的文件,不报错) - 或者用条件判断确保文件存在再删除:
if [ -f /graph/tmp/pids/server.pid ]; then rm /graph/tmp/pids/server.pid fi
2. 处理 Errno::EPERM 权限错误(Bootsnap 缓存问题)
这个错误是由于Rails和Sidekiq容器对共享目录的权限不一致,导致Bootsnap无法修改缓存文件。修复步骤:
- 统一容器运行用户:在Dockerfile中创建并指定固定用户,避免使用root运行:
RUN adduser --disabled-password --gecos "" appuser RUN chown -R appuser:appuser /graph USER appuser - 避免共享Bootsnap缓存目录:如果docker-compose中挂载了
tmp目录到主机,可考虑给Sidekiq单独设置缓存路径,或者不共享tmp/bootsnap目录 - 临时禁用Bootsnap的ISEQ缓存:在
config/boot.rb中修改Bootsnap配置(不推荐长期使用,会影响性能):Bootsnap.setup do |setup| setup.compile_cache_iseq = false end
3. 解决Rails与Sidekiq的竞态条件
竞态条件通常是因为两个容器同时初始化,争抢资源(如数据库连接、文件写入)导致的,可通过以下方式解决:
- 添加服务等待逻辑:在
entrypoint.sh中加入等待PostgreSQL和Redis就绪的脚本:# 等待PostgreSQL就绪 until pg_isready -h db -p 5432 -U postgres; do echo "Waiting for PostgreSQL..." sleep 2 done # 等待Redis就绪 until redis-cli -h redis ping | grep -q "PONG"; do echo "Waiting for Redis..." sleep 2 done - 配置Docker Compose健康检查与启动依赖:给数据库和Redis服务添加健康检查,确保Rails和Sidekiq在依赖服务就绪后再启动:
services: db: image: postgres:15 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 redis: image: redis:7 healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 5s retries: 5 web: build: . depends_on: db: condition: service_healthy redis: condition: service_healthy sidekiq: build: . depends_on: db: condition: service_healthy redis: condition: service_healthy - 隔离容器的临时文件:如果不需要共享
tmp目录,不要在docker-compose中挂载tmp,让每个容器拥有独立的临时文件空间,避免文件读写冲突。
内容的提问来源于stack exchange,提问作者Dan Rubio
相关产品推荐
相关产品推荐

