Ruby on rails docker compose在每次文件更新后重建?

Ruby on rails docker compose在每次文件更新后重建?,ruby-on-rails,docker,docker-compose,dockerfile,docker-machine,Ruby On Rails,Docker,Docker Compose,Dockerfile,Docker Machine,我将首先解释什么起作用: 我从中使用Docker创建了一个新的rails应用程序。运行docker compose up后,我的rails应用程序将在上运行 然后在一个新的候机楼当我运行这样的脚手架时 docker compose run--rm应用程序包exec rails g scaffold注释标题正文:text 而且 docker compose run--rm应用程序包exec rake db:migrate 迁移到数据库。然后当我去->我的新脚手架工程。但是脚手架并不需要rails服

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

我从中使用Docker创建了一个新的rails应用程序。运行
docker compose up
后,我的rails应用程序将在上运行

然后在一个新的候机楼当我运行这样的脚手架时

docker compose run--rm应用程序包exec rails g scaffold注释标题正文:text

而且

docker compose run--rm应用程序包exec rake db:migrate

迁移到数据库。然后当我去->我的新脚手架工程。但是脚手架并不需要rails服务器来启动

不工作的东西:

现在假设我需要一个Desive gem,我在本地sublime文本上更新我的
Gemfile
,然后运行

docker compose运行--rm应用程序包安装

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

docker compose run--rm应用程序包exec rails g designe:install

我得到错误:

在任何源中都找不到bcrypt-3.1.11
运行bundle安装以安装缺少的gems。

因此,基本上,在将Desive添加到Gemfile后,我必须再次运行
docker compose build
,这将花费很长时间,因为
bundle install
将从头开始安装所需的所有gems。

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


或者我错在哪里

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

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

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

当您使用为所有应用程序容器存储gem的容器时,您根本不需要重建图像,因为在您运行删除所有容器的
docker compose down
之前,或者在您自己删除bundle\u缓存容器之前,您根本不需要添加新的gem。当然,对于要安装新gems的每个容器,您不需要使用
bundle exec
。因此,它更容易和节省时间


但是,这需要在初始
docker compose构建之后进行额外的
捆绑安装
,因为在创建并首次将
/bundle\u缓存
装载到带有应用程序的容器时,它将是空的。但在那之后你的宝石将被储存在单独的容器中,每个启动的应用程序容器都可以使用此存储。

我得到的一个临时解决方法是打开一个新的终端并运行
docker exec-it container id bundle install
->这将直接在容器上运行,然后我只需使用
docker compose up
退出终端并再次运行。抱歉!我不理解您在.yml文件
之后的声明,但是,这需要在初始docker compose构建之后安装额外的捆绑包,因为…
。另外,yml文件末尾的这一点有什么作用<代码>卷:捆绑\u缓存:
是否检查了我的?我可以使用
bundle exec
直接在容器上执行命令,当我的项目完成时,或者如果我一天完成了,我可以一次重建所有图像。这难道不是非常简单和省时吗?@AdityaNagla现在介绍附加的
捆绑安装
。首先,在构建映像时要进行
bundle安装
,因为它在
Dockerfile
中有说明。Bundler在某处安装gems(如果您适当地设置$bundle\u路径,甚至可以在
/bundle\u缓存中安装)。然后你做
docker组合
。它运行所有服务并设置环境(
BUNDLE\u PATH=/BUNDLE\u cache
)。但是在这个初始时刻,
/bundle\u cache
中没有任何内容,因为这是第一次发布,您需要在那里安装gems。之后,应用程序容器将只使用那里的gems并在那里安装它们。@AdityaNagla
/bundle\u cache
将仅在移除容器时清除。现在,关于
卷:bundle\u缓存:
在文件末尾。它定义了可从服务的卷引用的命名卷。
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: