nickjj / docker-rails-example

A production ready example Rails app that's using Docker and Docker Compose.
MIT License
941 stars 185 forks source link

Fix bundle install running twice when you change your Gemfile #8

Closed nickjj closed 3 years ago

nickjj commented 3 years ago

This stems from having to generate webpacker packs for our test environment which means our webpacker image needs the complete Rails app available since the tests themselves end up running in the webpacker container. That's why it runs twice. Once for that and then again for the regular web image.

I know this kind of stinks because running bundle install takes a long time with Docker since if you change 1 dependency all dependencies need to be re-installed since that's how Docker layers work, and with this current set up we get dinged twice.

If we don't use a multi-stage build then our final Docker image is going to be over double in size since it'll include the entire Node runtime + all of the package.json libraries which isn't good.

Also we would still get hit with other delays, because if everything is in 1 image we have to individually run yarn install and bundle install, which means if you did yarn first it would then invalidate Docker's cache for bundle which means every time we change our package.json file our gems would get re-installed too. So moving to 1 image isn't ideal either.

I'm open for ideas on how to solve this.

smshuja commented 3 years ago

How about copying bundler dependencies from webpacker like you do for public assets?

something like this would work? I mean once its copied, running bundle install again should be pretty fast.

COPY --chown=ruby:ruby --from=webpacker /app/vendor/bundle /vendor

nickjj commented 3 years ago

Hey, that's a good idea.

I don't think we would even need to run it again if we copy over /usr/local/bundle. Do you see a reason why we would have to?

I tested it here and the COPY step took a second to copy the files and afterwards the project was able to be upped successfully and the tests are passing.

I ran both a run bundle:install and run bundle:update. Also manually upped the project and ran run cmd bundle install which finished very quickly. In all cases the correct thing happened and it was fast.

smshuja commented 3 years ago

Thats great. On our project though (not using docker yet), when I restore the bundler dependencies in semaphoreci, it doesn't seem to work without running the command again, must be some other issue.

nickjj commented 3 years ago

I wonder if that's because they're using a different CPU architecture or distro where it's not as simple as copying files over and new files need to be created from scratch but most of it works so it's still fast?

I just pushed it (without running it twice), let's see what happens. If it turns out to be broken in some case it can always be patched to add in the 2nd run. If you want to test out the master branch that would be much appreciated.

Here is the commit: https://github.com/nickjj/docker-rails-example/commit/7b08daf943a6810b84fc040c9943d5bd59aee685