CircleCI构建镜像后ECS Fargate中Ruby on Rails Unicorn启动失败
Rails应用部署ECS Fargate时Unicorn启动失败:bundler无法加载命令
问题现象
本地通过命令 ["bundle", "exec", "unicorn", "-c", "config/unicorn.rb"] 可正常启动Rails服务,但将同一镜像部署到ECS Fargate时,出现如下错误:
2022-07-27 15:46:33bundler: failed to load command: unicorn (/usr/local/bundle/bin/unicorn)
使用的Dockerfile内容如下:
FROM ruby:2.6.7 RUN apt-get update -qq && apt-get install -y nodejs postgresql-client sudo WORKDIR /app ENV RAILS_ENV="staging" ENV NODE_ENV="staging" ENV LANG="en_US.UTF-8" ENV RACK_ENV ="staging" ENV BUNDLE_WITHOUT='development:test' ARG GITHUB_TOKEN RUN gem install bundler -v '2.2.28' RUN bundle config https://github.com/somename/somerepo someuser:"${GITHUB_TOKEN}" COPY . /app RUN rm -rf /app/tmp RUN mkdir -p /app/tmp RUN bundle install RUN bundle exec rails assets:precompile EXPOSE 3000
注:启动CMD在ECS任务定义中配置,未写入Dockerfile。
排查过程
- 拉取CircleCI构建后推送到ECR的镜像到本地测试,复现了相同的启动失败问题
- 进入容器执行
chmod 755 -R /usr/local/bundle/bin/后,重新执行启动命令,Unicorn可正常运行,确认是gem目录权限不足导致 - 尝试在Dockerfile的
bundle install步骤后添加权限修改命令,问题依旧 - 尝试将权限修改逻辑放到入口启动脚本中,容器直接无法启动
解决方案
方案1:bundle install时指定权限相关参数
执行bundle install时,直接指定binstubs路径和权限,避免后续修改无效:
RUN bundle install --path vendor/bundle --binstubs vendor/bundle/bin --jobs 4 --retry 3
同时调整ECS任务定义中的启动命令为:
["bundle", "exec", "--gemfile", "/app/Gemfile", "unicorn", "-c", "/app/config/unicorn.rb"]
方案2:提前设置目录权限+禁用Docker缓存
在执行bundle install前,先确保目标目录权限正确,同时构建时禁用缓存避免复用旧层:
RUN mkdir -p /usr/local/bundle && chmod -R 755 /usr/local/bundle RUN bundle install
构建命令添加--no-cache参数:
docker build --no-cache -t your-image-tag .
方案3:使用非root用户构建运行
创建专用用户执行安装和启动操作,避免root权限下的权限继承问题:
RUN useradd -m appuser RUN chown -R appuser:appuser /app /usr/local/bundle USER appuser RUN bundle install
Fargate会自动继承Dockerfile中指定的用户身份运行容器。
原因说明
CircleCI构建环境中,bundle install生成的bin文件默认权限可能为700,仅当前用户可执行;而Docker缓存机制可能导致后续添加的chmod命令未实际生效(因为bundle install的缓存层未重新构建),最终导致Fargate运行时无法执行Unicorn命令。
内容的提问来源于stack exchange,提问作者Keimille
相关产品推荐
相关产品推荐

