devcontainers / templates

Repository for Dev Container Templates that are managed by Dev Container spec maintainers. See https://github.com/devcontainers/template-starter to create your own!
https://containers.dev/templates
MIT License
873 stars 230 forks source link

Ruby on Rails & Postgres Devcontainer Template is not configured for immediate running #188

Closed ThomasOwens closed 9 months ago

ThomasOwens commented 1 year ago

When I create a new set of devcontainer configuration files using the default Ruby on Rails & Postgres configuration, I would expect to be able to launch the container and execute rails new . -d postgresql without errors. The Rails project files are laid out properly, but one of the steps in instantiating a new Rails project is to install the relevant gems. This step fails.

Many errors of the following nature come up:

Retrying download gem from https://rubygems.org/ due to error (2/4): Bundler::PermissionError There was an error while trying to write to /usr/local/rvm/gems/default/cache/bindex-0.8.1.gem. It is likely that you need to grant write permissions for that path.

This also prevents the default postCreateCommand from running, if that is uncommented, since that command runs bundle install.

The general solution is to set the bundle directory to be something within the workspace. One specific solution is to set the BUNDLE_PATH environment variable to something in the workspace within the devcontainer.json file:

"containerEnv": {
        "BUNDLE_APP_CONFIG": "/workspaces/${localWorkspaceFolderBasename}/.bundle",
        "BUNDLE_PATH": "/workspaces/${localWorkspaceFolderBasename}/vendor/bundler"
}

There may be better solutions, though, that are more generic.

ThomasOwens commented 1 year ago

I thought of something else. It's not clear to me why RVM is being installed and used in Ruby containers. Not sure what container picks this up, but it seems like the use of containers would mitigate the need for most uses for RVM. If you need a particular Ruby version for your application, put that application in a container of its own. I don't think you'd be running multiple distinct applications within the same container anyway.

bamurtaugh commented 11 months ago

Thanks for opening!

@samruddhikhandale any thoughts hereon why we're using rvm?

samruddhikhandale commented 11 months ago

Historically, we have been installing rvm on top of the ruby image as a good measure. It helps provide flexibility to switch ruby versions.

If you need a particular Ruby version for your application, put that application in a container of its own. I don't think you'd be running multiple distinct applications within the same container anyway.

I understand this point and I think it makes complete sense. Also, with the help of Ruby Feature, one can quickly and easily install some another version (if needed).

From https://github.com/devcontainers/images/issues/572,

We should update the Ruby Feature, and add two new Feature options which controls rvm and rbenv installation. (eg: installRVM, installRbenv)

This issue ^ is another helpful use case for adding installRVM, and installRbenv Feature options 👍

ThomasOwens commented 11 months ago

@samruddhikhandale Looking through those linked issues, I think the approach you described in devcontainers/features#603 is the correct one.

The base Ruby (and the Ruby on Rails & Postgres) contains should install the specified version of Ruby as an OS package without a Ruby version manager. I would suspect that most new applications would take this route, and it's the one I'd suggest. However, if someone is working with a legacy application (perhaps with existing scripts or configurations that rely on a version manager) or otherwise has a need, they could optionally install a version manager through Features or by updating the Dockerfiles as needed.

nevans commented 11 months ago

The main use case I have for a version manager inside a devcontainer is when I'm actively working on compatibility between multiple versions, e.g: an application that that is actively being upgraded or a gem (or application) that supports multiple versions. It's very convenient to be able to be able to rapidly switch versions e.g: with a bash one-liner:

export RBENV_VERSION
for RBENV_VERSION in 2.7.8 3.0.6 3.1.4 3.2.2; do declare -p RBENV_VERSION; bundle && bin/rake; done

Using multiple devcontainers for these scenarios is a huge hassle and unnecessary. FWIW, I primarily use devcontainers from the CLI or with gh codespace ssh and not via VS Code, so I may be missing out on some UI that simplifies this and y'all probably know ways to reduce that hassle that I'm ignorant of. But are any of them as simple and convenient as a bash for loop? 🙂

That said, most of the time I'm working on an app that only supports one version and I'm not actively upgrading it, and I don't need (or want) to use a version manager at all. I support @ThomasOwens's suggestion of installing no version manager by default. At the very least, if any version manager is installed by default then it should not break the default "system" install (which is why I prefer rbenv over rvm).

bolte-17 commented 10 months ago

For what it's worth, I'm having some suspicions that the Ruby and Ruby-LSP extensions, as configured by default, are assuming some things about rbenv being around and controlling the installed ruby version.

Might need to configure those extensions specifically for the devcontainer, but as I haven't gotten it working yet, couldn't tell you exactly how.

So far only success has been adding ruby-lsp into the project's own gemfile and setting the ruby-lsp version manager configuration value to none, but would prefer a solution that doesn't require mucking about with an existing project that much.

ThomasOwens commented 10 months ago

@bolte-17 That's not it at all. It seems like it has nothing to do with ruby-lsp and more to do with how the devcontainer is set up. See https://github.com/Shopify/ruby-lsp/issues/1745 for more details, but in the Ruby on Rails & Postgres container, gems are installed as root. That's preventing the vscode user from installing and using other gems, including ruby-lsp.

@samruddhikhandale or @bamurtaugh Is there any news here? It seems like the problem is a bit worse than originally described since the way the Ruby on Rails & Postgres devcontainer is built makes it impossible to install and use some intended features (I noticed it in the ruby-lsp VS Code extension, but there may be others I haven't noticed yet). I don't know if removing rvm would solve this problem, but gems are being installed as root in the Ruby on Rails and Postgres devcontainer, but not in the Ruby container. At this point, I think I need to stop using this container and go to the Ruby container and manually add what I need (if not the Alpine container and build it from scratch). Perhaps that's a better solution anyway. It still leaves open the question about the use of RVM as a mandatory feature in the Ruby container (I don't think it should be there)

bamurtaugh commented 10 months ago

Thanks for the continued discussion! We discussed further and agree refactoring here makes sense. The spec maintainers don't currently have capacity to pick this up, so we'd definitely welcome a community PR(s) with changes being discussed here!

ThomasOwens commented 10 months ago

@bamurtaugh Sure. I can try.

Although I guess I'm also rethinking if I really want to use this Ruby on Rails & Postgres container at all. There's already a Ruby container that doesn't appear to have the problems that I'm finding with this one, Rails can very easily be installed as a gem in that container, and other dependencies can be installed or included in a compose file with ease.

If it comes down to a maintenance issue, I'm wondering if it makes sense to even support this devcontainer. I almost wonder if the better pull request wouldn't be the discussion above - to move rvm to a feature (or to a configurable part of the ruby feature and allow for installation of ruby without a version manager or for a specific version manager and default ruby version). It could also be beneficial to add database clients (including Postgres and MySQL, among others) as features to make it easier to build Ruby applications that require clients to be installed for native gems to be built.

I need to do some more experimenting to understand the implications, but if there is any guidance for what would or wouldn't be accepted, I would appreciate that.

bamurtaugh commented 10 months ago

Thanks @ThomasOwens! As you experiment, we'd love to learn what you observe and would be happy to discuss your proposed path forward via a PR(s).

ThomasOwens commented 10 months ago

I opened a draft PR that appears to address this https://github.com/devcontainers/templates/pull/202 but I still have work to do. I'll continue the discussion in that PR.

samruddhikhandale commented 10 months ago

@ThomasOwens thank you so much, let me know when you are ready. I can help review it!

ThomasOwens commented 9 months ago

This has been resolved in Shopify/vscode-ruby-lsp#202. As part of those changes, I confirmed by making a new project, using the proposed changes to the devcontainer, and then going through the process of creating a new Rails app without errors.