docker-在每次 Gemfile 更新后重新构建?

docker-compose rebuild after each Gemfile update?

我先解释一下什么是有效的:

我使用 this docs. After I ran docker-compose up my rails app will be running on http://docker-ip:port 中的 Docker 创建了一个新的 rails 应用程序。

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

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 服务器启动。

不工作:

所以现在说我需要一个设计 gem,我在本地 sublime 文本上更新我的 Gemfile 然后 运行

docker-compose run --rm app bundle install

这将按预期安装新设备 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。

那么我可以更新 Gemfile 而无需重新构建 docker-compose 吗?

或者我哪里错了?

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

现在谈谈解决方案。当你 运行 docker-compose run --rm app bundle install,你创建新的容器,安装新的 gems 到它(这个操作更新 Gemfile.lock,你看到这个变化,因为你的项目目录是安装到容器),然后退出。由于 --rm 标志,容器被删除。在容器中所做的更改不会影响图像。

为避免在每次 gem 安装时重建图像,您可以添加一个服务来存储 gems。这是在 docs.

的基础上修改的 docker-compose.yml
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:

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

然而,这需要在初始 docker-compose build 之后额外 bundle install,因为在创建和首次安装 /bundle_cache 到带有应用程序的容器时,它将是空的。但是在那之后你的 gems 将被存储在单独的容器中,并且这个存储将可用于每个启动的应用程序容器。