每个Gemfile更新后docker-compose rebuild?

时间:2018-02-28 14:41:52

标签: ruby-on-rails docker docker-compose dockerfile docker-machine

我将解释首先工作的是什么:

我使用this docs中的Docker创建了一个新的rails应用程序。运行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 - >我的新脚手架有效。但是Scaffolding并不需要启动rails服务器。

不工作:

所以现在说我需要一个设计宝石,我在本地崇高文本上更新我的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将需要很长时间才能安装从头开始所需的所有宝石。

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

或我错在哪里?

1 个答案:

答案 0 :(得分:3)

首先,关于docker exec的解决方法。修改容器状态不是一个好方法。如果您需要再运行一个app容器实例,该怎么办? exec不会做任何更改。您必须再次安装宝石,或重建图像。当您需要运行多个容器时,这种情况并不罕见。例如,您使用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安装时重建图像,您可以添加服务来存储gem。修改后的docker-compose.yml基于docs。{/ p>

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:

当您使用为所有应用容器存储宝石的容器时,您根本不需要重新构建图像,因为您需要添加新的宝石,直到您运行删除所有容器的docker-compose down(&#39} ; s真的很少需要)或者直到你自己删除bundle_cache容器。当然,您不需要为要安装新宝石的每个容器使用bundle exec。因此,它更容易,更省时。

但是,在初始bundle install之后,这需要额外的docker-compose build,因为在创建并首次将/bundle_cache挂载到带有应用程序的容器时,它将为空。但之后,您的宝石将存储在单独的容器中,并且此存储将可用于每个已启动的应用程序容器。