Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bundler cache feature #48

Merged
merged 1 commit into from
Sep 30, 2024

Conversation

patriciomacadden
Copy link
Contributor

Hello!

I've been using docker and docker compose for years to run my rails apps in development. The way I used docker + docker compose was to run a single process and remove the container after it's done (eg docker compose run --rm ..., or just docker compose up and them removing the container, etc). And when you're adding gems, trying things out, etc. it's super useful to have a volume for the installed gems so you can run docker compose run web bundle and have the new gems available rather than having to rebuild the image over and over.

Devcontainers approach, ie developing inside of the container, is really interesting but there's something that slows down the whole thing of bringing the container up and that is to install gems every time (if you remove containers after a period of time obviously, if you don't you're fine).

This feature could've been in its own repo but I thought this is a good place to be as people like me might find useful.

This feature just creates a volume that gets mounted in /bundle and adds the BUNDLE_PATH env var to /vendor/bundle. This way you might remove the container and when you bring it up again it will use the gems you already have installed, making the whole process faster. The reason why there's a postCreateCommand is that the mounted volume needs to be owned by the vscode user, as the devcontainer doesn't run as root. I couldn't find a different way editing the compose.yaml or devcontainer.json. Apologies if there's another way!

@andrewn617
Copy link
Collaborator

Hi @patriciomacadden Thanks for the PR! This is actually a feature I have had in mind as well and played with a bit but didn't come up with an implementation I liked, and I have been meaning to come back to it. At first glance this looks good. I want to do some testing with it on my end but I probably won't have time to get to that until sometime next week. I will get back to you once I have had time to take a closer look =)

@patriciomacadden
Copy link
Contributor Author

hey @andrewn617 awesome. Let me know if you think we can improve it!

"description": "Creates a volume for persisting the installed gems across different containers",
"containerEnv": {
"BUNDLE_PATH": "/bundle/vendor"
},
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps also add this?

Suggested change
},
},
"installsAfter": [
"ghcr.io/rails/devcontainer/features/ruby"
],

I'm not sure if it makes sense though

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's necessary. The ruby feature should not install any gems.

"name": "Bundler cache",
"description": "Creates a volume for persisting the installed gems across different containers",
"containerEnv": {
"BUNDLE_PATH": "/bundle/vendor"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that once you're in the container, if you run rails c (or any other executable in your Gemfile) you'll get a "command not found" error.

to solve this, we can add these env vars:

Suggested change
"BUNDLE_PATH": "/bundle/vendor"
"BUNDLE_PATH": "/bundle/vendor",
"BUNDLE_BIN": "/bundle/bin",
"PATH": "/bundle/bin:$PATH"

BUNDLE_BIN tells bundler to install the bins in the specified dir, and then we'll prepend this dir in the PATH.

By default, the BUNDLE_BIN would be something like /bundle/vendor/ruby/COMPATIBILITY_VERSION/bin. And compatibility version is not always the same ruby version you're running (for example i'm testing with 3.3.4 and the compat version is 3.3.0 - This is not trivial to get, so changing the BUNDLE_BIN makes sense..

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should add the bundle bin to the path like that. Instead people should do bundle exec rails c or bin/rails c. I expect global gems to be in the path but not bundled gems.

Copy link
Collaborator

@andrewn617 andrewn617 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@patriciomacadden Sorry it took me a bit of time to get to testing this. This looks good and is working for me. Thank you for the contribution =)

@andrewn617 andrewn617 merged commit 0e92227 into rails:main Sep 30, 2024
@patriciomacadden
Copy link
Contributor Author

hey @andrewn617, don't worry about it. Thanks for merging! Looking forward to contribute a bit more!

viktorianer added a commit to viktorianer/rails8-devcontainer-enhancements that referenced this pull request Oct 1, 2024
…lled Ruby dependencies.

Cache the installed Ruby dependencies into a docker volume, making the `devcontainer up` and `docker compose up` process faster.

Before:

```bash
== Installing dependencies ==
https://github.com/rails/rails.git (at main@99a6365) is not yet checked out. Run `bundle install` first.
Bundler 2.5.11 is running, but your lockfile was generated with 2.5.17. Installing Bundler 2.5.17 and restarting using that version.
Fetching gem metadata from https://rubygems.org/.
Fetching bundler 2.5.17
Installing bundler 2.5.17
Fetching https://github.com/rails/rails.git
Fetching gem metadata from https://rubygems.org/..........
Fetching rake 13.2.1
```

After:

```bash
== Installing dependencies ==
The Gemfile's dependencies are satisfied
```

See also feature rails/devcontainer#48, which will not work with `docker compose`.
viktorianer added a commit to viktorianer/rails8-devcontainer-enhancements that referenced this pull request Oct 2, 2024
…lled Ruby dependencies.

Cache the installed Ruby dependencies into a docker volume, making the `devcontainer up` and `docker compose up` process faster.

Before:

```bash
== Installing dependencies ==
https://github.com/rails/rails.git (at main@99a6365) is not yet checked out. Run `bundle install` first.
Bundler 2.5.11 is running, but your lockfile was generated with 2.5.17. Installing Bundler 2.5.17 and restarting using that version.
Fetching gem metadata from https://rubygems.org/.
Fetching bundler 2.5.17
Installing bundler 2.5.17
Fetching https://github.com/rails/rails.git
Fetching gem metadata from https://rubygems.org/..........
Fetching rake 13.2.1
```

After:

```bash
== Installing dependencies ==
The Gemfile's dependencies are satisfied
```

See also feature rails/devcontainer#48, which will not work with `docker compose`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants