我会先解释一下有什么作用:
我使用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
将安装从头开始所需的所有宝石。
那么我可以更新Gemfile而无需再次重建docker-compose吗?
或者我错在哪里?
首先,关于docker exec
的解决方法。这不是修改容器状态的好方法。如果您需要再运行一个app容器实例,该怎么办? exec不会做任何更改。您将不得不再次安装宝石,或重建图像。当您需要运行多个容器时,这种情况并不罕见。例如,您使用docker-compose up
运行dev环境,并使用docker-compose run --rm web bash
在near终端中运行shell在第二个应用程序容器中并使用它运行测试,迁移,生成器或使用rails console
而不停止由docker-compose启动的容器。
现在谈谈解决方案。当您运行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:
当您使用容器为所有应用容器存储gem时,您不需要重建图像,因为根本不需要添加新的gem,直到您运行删除所有容器的docker-compose down
(它确实很少需要)或直到您自己删除bundle_cache容器。当然,您不需要为要安装新宝石的每个容器使用bundle exec
。所以它更容易和省时。
然而,这需要在初始bundle install
之后额外的docker-compose build
,因为在创建和首次将/bundle_cache
安装到带有应用的容器时它将是空的。但之后,您的宝石将存储在单独的容器中,并且此存储将可用于每个已启动的应用程序容器。