Skip to content

Install bundle gem in the same path as the system gems are #53

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

Closed
vovimayhem opened this issue Sep 23, 2015 · 11 comments
Closed

Install bundle gem in the same path as the system gems are #53

vovimayhem opened this issue Sep 23, 2015 · 11 comments

Comments

@vovimayhem
Copy link

I'm having this use case in which I bring up several containers of the same ruby (rails) app with different commands using docker-compose for my development enviroment:

# Obviating some keys to keep the example lean:
web: &app
  image: ruby:2.2.3
  volumes:
    - .:/usr/src/app
  command: rails s -p 3000
jobs:
  <<: *app
  command: sidekiq -c 25 -q default

Using this image will require me to call bundle install on each container... but since is the same app, exactly the same gems will be installed on each container... I could mount a volume from a data-container on the /usr/local/bundle path, so both containers use the same installed gems:

gems:
  image: tianon/true
  volumes:
    - /usr/local/bundle
web: &app
  image: ruby:2.2.3
  volumes:
    - .:/usr/src/app
  volumes_from:
    - gems
  command: rails s -p 3000
jobs:
  <<: *app
  command: sidekiq -c 25 -q default

...but this will wipe out the image's installed bundler, as it's installed precisely on the /usr/local/bundle path.

How about installing bundler BEFORE setting the $GEM_HOME in this image's Dockerfile? Like this:

ENV BUNDLER_VERSION 1.10.6

# some of ruby's build scripts are written in ruby
# we purge this later to make sure our final image uses what we just built
RUN apt-get update \
    && apt-get install -y bison libgdbm-dev ruby \
    && rm -rf /var/lib/apt/lists/* \
    && mkdir -p /usr/src/ruby \
    && curl -fSL -o ruby.tar.gz "http://cache.ruby-lang.org/pub/ruby/$RUBY_MAJOR/ruby-$RUBY_VERSION.tar.gz" \
    && echo "$RUBY_DOWNLOAD_SHA256 *ruby.tar.gz" | sha256sum -c - \
    && tar -xzf ruby.tar.gz -C /usr/src/ruby --strip-components=1 \
    && rm ruby.tar.gz \
    && cd /usr/src/ruby \
    && autoconf \
    && ./configure --disable-install-doc \
    && make -j"$(nproc)" \
    && make install \
    && apt-get purge -y --auto-remove bison libgdbm-dev ruby \
    && gem update --system $RUBYGEMS_VERSION \
    && rm -r /usr/src/ruby \
    && gem install bundler --version "$BUNDLER_VERSION"

# install things globally, for great justice
ENV GEM_HOME /usr/local/bundle
ENV PATH $GEM_HOME/bin:$PATH

RUN  bundle config --global path "$GEM_HOME" \
    && bundle config --global bin "$GEM_HOME/bin"

Any issues with that?

Also, does anybody has a better workflow / technique for development using this image & docker-compose?

@yosifkit
Copy link
Member

yosifkit commented Oct 9, 2015

That seems valid to me.

You could just have them both use a local Dockerfile with build: . in the compose yaml.

FROM ruby:2.2.3
ADD Gemfile* /usr/src/app/
RUN bundle install
ADD . /usr/src/app/

You'll just have to remember to rebuild when you make Gemfile changes. Plus the Dockerfile can be used to create a container to deploy.

@vovimayhem
Copy link
Author

That pretty much works, however I was aiming at a simpler workflow by sparing me from using build . on the docker-compose file.

What I ended using is the same ruby image to create a data-only container, something similar to this:

gems: &app_base
  image: ruby:2.2.3
  volumes: [ ".:/usr/src/app", "/usr/local/bundle" ]
  working_dir: /usr/src/app
jobs: &app
  <<: *app_base
  volumes_from: [ "gems" ]
  entrypoint: /usr/src/app/dev-entrypoint.sh
  command: sidekiq -c 25
web:
  <<: *app
  command: rails s -p 3000
  ports: [ "3000:3000" ]

The entrypoint script runs the bundle install command, within a lock routine to prevent concurrent bundle installs.

It would still be nice if bundler was installed in the same place as the system gems in this official image, tho. Bundler seems to be pretty ubiquitous, and almost everyone expects to be part of a somewhat default install or ruby - I know it is not the case with the official installer, but take a hint at what RVM, Rbenv and ruby-install do.

@dmitrym0
Copy link

Hey @vovimayhem, I'm trying to do something similar. Hope it's ok to jump in. My googling lead me to this post that suggests you can cache bundled gems on a data only volume, but it's not working very well for me. I think I have to build the data volume first, and then mount it in my app image. What do you think?

@vovimayhem
Copy link
Author

@dmitrym0 I came out with this demo some weeks ago, with a workflow extremely close to what I was looking for.

There's no build step involved, as you can see. I'd prefer to use a build step as a last resort if there's the need to add something else to the base image (i.e. another executable, etc), other than the app gems.

@vovimayhem
Copy link
Author

On the other hand, I do use docker build to actually build the app image and upload it to the hub so I can deploy it to a docker host, but that's not related to my current development flow.

@dmitrym0
Copy link

Thanks @vovimayhem, that's very helpful! One question though. Do you feel that this the "Docker way"? When I started looking at docker a little while I was under the impression that it's recommended to make the containers as immutable as possible by providing all prerequisites at the build stage. Your approach relies on bundle installing the gems at container startup which could potentially mean that two containers started from the same image may (in theory) be different. What do you think? Apologies if this is a stupid question, I'm a docker newbie.

@vovimayhem
Copy link
Author

@dmitrym0 The recommendation of making containers as immutable as possible is spot-on... for production-like setups, where no further changes will be made to a container in order for the app to run.

But that particular demo was all about spinning up a development environment, in the most fluid and productive way possible... That's why I use the official images, and install gems with the entry point.

While developing, I can assure you that nothing is immutable, so I wanted to avoid that build step, sparing me from filling my docker images list with mostly temporary images... and maybe spare me from problems with images not having the latest code.

@mhenrixon
Copy link

👍

@jonathanstiansen
Copy link

Any further ideas on this? Still doing it with Docker-compose up? It'd be wonderful if it could work without it.

@tianon
Copy link
Member

tianon commented Aug 22, 2016

I believe that this should be fixed, as we do gem install bundler before we set GEM_HOME and friends:

@tianon
Copy link
Member

tianon commented Aug 22, 2016

More specifically, it appears that #68 was the PR which made the switch. 👍

@tianon tianon closed this as completed Aug 22, 2016
chrissolanilla pushed a commit to chrissolanilla/CSolanillaBio that referenced this issue May 16, 2024
…into 'master'


Issue/multiple add more missing people and misc fixes

* Moves Francisca to L&ST section
* Updates most titles
* removes Matthew from past page
* Adds Tom Carrol to past
* Adds Jared Lang to past
* Adds Shelly Cavanaugh to past
* Adds Chet Bortz to past
* Adds Brent Shaw to past
* Adds Austin Florez to past
* removes Brandon Stull from past


Fixes docker-library#54 docker-library#53 docker-library#52 

See merge request !30
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

No branches or pull requests

6 participants