You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker托管Rails应用找不到Gemfile,容器创建后秒退求助

Docker容器启动后因Gemfile未找到退出的问题解决

问题描述

GitLab流水线运行成功,但Docker容器创建后几秒就退出。在托管服务器上执行docker container logs eops_staging,输出Gemfile未找到的错误:

$ docker container logs eops_staging
/usr/local/bundle/gems/bundler-1.10.6/lib/bundler/definition.rb:23:in `build': /usr/src/app/Gemfile not found (Bundler::GemfileNotFound)
    from /usr/local/bundle/gems/bundler-1.10.6/lib/bundler.rb:155:in `definition'
    from /usr/local/bundle/gems/bundler-1.10.6/lib/bundler.rb:123:in `setup'
    from /usr/local/bundle/gems/bundler-1.10.6/lib/bundler/setup.rb:18:in `<top (required)>'
    from /usr/local/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:128:in `require'
    from /usr/local/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:128:in `rescue in require'
    from /usr/local/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:39:in `require'
    from /usr/local/bundle/bin/rails:14:in `<main>'

本地开发机使用以下命令可正常启动容器:

$ docker --context dockerapps compose -f docker-compose.staging.yml up -d

解决后的关键文件

Dockerfile.staging

FROM ruby:2.1.6

RUN apt-get update -y && apt-get --force-yes install -y --no-install-recommends \
    build-essential \
    curl \
    git \
    libaio-dev

# 解决bundle install时git clone超时问题
RUN git config --global url."https://".insteadOf git://

# 复制Oracle依赖文件
ADD vendor/oracle /usr/lib/oracle/
ENV LD_LIBRARY_PATH='/usr/lib/oracle/instantclient_21_8'
# 设置Oracle字符集环境变量,避免警告
ENV NLS_LANG='AMERICAN_AMERICA.WE8ISO8859P15'
RUN echo "The ENV variable value is $NLS_LANG"

ARG APP_HOME=/usr/src/app

# 创建应用目录并设置为工作目录
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# 先复制Gemfile相关文件,利用Docker缓存优化构建速度
COPY Gemfile* /usr/src/app/

# 指定bundler的gem安装目录
ENV BUNDLE_PATH /gems

# 安装指定版本的bundler并执行bundle install
ENV BUNDLER_VERSION='1.9.6'
RUN gem install bundler --no-document -v '1.9.6'
RUN bundle install

# 复制整个应用代码到容器
ADD . /usr/src/app

# 调试用:查看当前目录文件
RUN ls -la .

# 设置容器启动命令
CMD ["rails", "s", "-b", "0.0.0.0"]

docker-compose.staging.yml

version: '3'

services:
  app:
    # 指定构建上下文和Dockerfile
    build:
      context: .
      dockerfile: Dockerfile.staging
    image: eops_app:staging
    container_name: eops_staging
    # todo restart: always
    environment:
      RAILS_ENV: staging
      PIDFILE: /tmp/pids/server.pid
    tmpfs:
      # 临时挂载/tmp/pids目录,容器停止后自动清理
      - /tmp/pids/
    env_file:
      - .env/app
    ports:
      - "3001:3000"

gitlab-ci.yml

stages:
  - publish
  - deploy

publish-to-staging:
  image: docker:latest
  stage: publish
  rules:
    - if: $CI_COMMIT_BRANCH == 'docker_dev'
  services:
    - docker:dind
  script:
    - docker image build -f Dockerfile.staging -t registry.example.com/cals-it-acs/hr-eops/docker_app/eops_app:staging .
    - echo $CI_REGISTRY_PASSW | docker login -u $CI_REGISTRY_USER registry.example.com --password-stdin
    - docker push registry.example.com/cals-it-acs/hr-eops/docker_app/eops_app:staging

deploy-to-staging:
  stage: deploy
  rules:
    - if: $CI_COMMIT_BRANCH == 'docker_dev'
  script:
    # 修复SSH私钥权限
    - chmod og= $ID_ECDSA
    # 在托管服务器登录镜像仓库并拉取最新镜像
    - ssh -i $ID_ECDSA -o StrictHostKeyChecking=no deploy@dock.cals.wisc.edu "docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSW registry.example.com"
    - ssh -i $ID_ECDSA -o StrictHostKeyChecking=no deploy@dock.cals.wisc.edu "docker pull registry.example.com/cals-it-acs/hr-eops/docker_app/eops_app:staging"
    # 删除旧容器(如果存在)
    - ssh -i $ID_ECDSA -o StrictHostKeyChecking=no deploy@dock.cals.wisc.edu "docker container rm -f eops_staging || true"
    # 调试命令:查看运行中的容器和网络
    - ssh -i $ID_ECDSA -o StrictHostKeyChecking=no deploy@dock.cals.wisc.edu "docker ps"
    - ssh -i $ID_ECDSA -o StrictHostKeyChecking=no deploy@dock.cals.wisc.edu "docker network list"
    # 复制环境变量文件
    - cp $EOPS_ENV .env/app
    # 启动容器
    - docker --context dockerapps compose -f docker-compose.staging.yml up -d

deploy-to-production:
  stage: deploy
  when: manual
  rules:
    - if: $CI_COMMIT_BRANCH == 'docker_main'
  script:
    - echo "deploying to production . . ."

关键修复说明

  1. Dockerfile路径与顺序优化:

    • 明确设置WORKDIR /usr/src/app,确保后续所有文件操作都基于正确的应用目录
    • 先复制Gemfile*到容器,再执行bundle install,保证bundler能找到Gemfile文件,同时利用Docker缓存减少重复构建时间
    • 最后复制整个应用代码,确保Gemfile和应用文件都存在于容器的指定路径中
  2. CI/CD部署流程修正:

    • 确保在部署阶段先拉取GitCI构建好的镜像,避免在托管服务器上重新构建(若服务器本地无代码会导致构建失败)
    • 修复SSH私钥权限,保证能正常连接托管服务器

内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 10:13:09