每次Gemfile更新后都重新构建docker-compose吗?

5 ruby-on-rails docker dockerfile docker-compose docker-machine

我将解释什么首先起作用:

我从这篇文档中使用Docker创建了一个新的Rails App 。运行后,docker-compose up我的rails应用程序将在http:// docker-ip:port上运行

然后在一个新的终端中,当我运行这样的脚手架时

docker-compose run --rm app bundle exec rails g scaffold note title body:text

然后

docker-compose run --rm app bundle exec rake db:migrate

迁移到数据库。然后,当我转到http:// docker-ip:port- >我的新脚手架工作时。但是脚手架不需要Rails服务器启动。

不起作用的东西:

所以现在说我需要一个设计宝石,我更新Gemfile本地崇高文字,然后运行

docker-compose run --rm app bundle install

这将按预期安装新的devise gem。但是当我跑步时

docker-compose run --rm app bundle exec rails g devise:install

我收到错误消息:

Could not find bcrypt-3.1.11 in any of the sources Run bundle install to install missing gems.
因此,基本上,在将设计添加到Gemfile后,我必须再次运行,docker-compose build这将花费很长时间,因为bundle install它将从头开始安装所有必需的gem。

那么我可以在不重新构建docker-compose的情况下更新Gemfile吗?

还是我错在哪里?

Mak*_*kov 11

首先,关于docker exec. 这不是修改容器状态的好方法。如果您需要再运行一个应用容器实例怎么办?exec 不会进行任何更改。你必须再次在那里安装 gems,或者重建镜像。当您需要运行多个容器时,这种情况并不少见。例如,您用于docker-compose up运行 dev 环境,并docker-compose run --rm web bash在附近的终端中在第二个应用程序容器中运行 shell 并使用它来运行测试、迁移、生成器或使用rails console不停止由 docker-compose up 启动的容器。

现在关于解决方案。运行时docker-compose run --rm app bundle install,您创建新容器,将新的 gem 安装到其中(此操作更新Gemfile.lock,您会看到此更改,因为您的项目目录已安装到容器),然后退出。由于--rm标志,容器被移除。在容器中所做的更改不会影响图像。

为了避免在每次安装 gem 时重建映像,您可以添加一个服务来存储 gem。这里是docker-compose.yml根据docs 修改的

version: '3'
services:
  db:
    image: postgres
  web:
    build: .
    command: bash -c "bundle install && bundle exec rails s -p 3000 -b 0.0.0.0"
    volumes:
      - .:/myapp
      - bundle_cache:/bundle_cache
    ports:
      - "3000:3000"
    depends_on:
      - db
    environment:
      - BUNDLE_PATH=/bundle_cache
  bundle_cache:
    image: busybox
    volumes:
      - bundle_cache:/bundle_cache

volumes:
  bundle_cache:
Run Code Online (Sandbox Code Playgroud)

当您使用为所有应用程序容器存储 gem 的容器时,在您运行docker-compose down删除所有容器(实际上很少需要)或直到您自己删除 bundle_cache 容器之前,您根本不需要因为添加新 gem 而重建映像。当然,您不需要为bundle exec要安装新 gem 的每个容器使用。所以它更容易和节省时间。

但是,这需要bundle install在 initial 之后额外添加docker-compose build,因为在创建和第一次/bundle_cache使用应用程序安装到容器时,它将是空的。但是在那之后,您的 gem 将存储在单独的容器中,并且该存储将可用于每个启动的应用程序容器。