Prayas Arora
Prayas Arora

Reputation: 63

How to install new gems in a rails docker image without rebuilding it

I am trying to create my rails application in a docker environment. I have used volumes to mount source directories from the host at a targeted path inside the container. The application is in the development phase and I need to continuously add new gems to it. I install a gem from the bash of my running container, it installs the gem and the required dependencies. But when I removed the running containers(docker-compose down) and then again instantiated them(docker-compose up), my rails web image shows errors of missing gems. I know re-building the image will add the gems but IS THERE ANY WAY TO ADD GEMS WITHOUT REBUILDING THE IMAGE?

I Followed docker-compose docs for setting the rails app https://docs.docker.com/compose/rails/#define-the-project

DOCKERFILE

FROM ruby:2.7.1-slim-buster
LABEL MAINTAINER "Prayas Arora" "<[email protected]>"

# Install apt based dependencies required to run Rails as
# well as RubyGems. As the Ruby image itself is based on a
# Debian image, we use apt-get to install those.
RUN apt-get update \
    && apt-get install -qq -y --no-install-recommends \
       build-essential \
       libpq-dev \
       netcat \
       postgresql-client \
       nodejs \
    && rm -rf /var/lib/apt/lists/*


ENV APP_HOME /var/www/repository/repository_api

# Configure the main working directory. This is the base
# directory used in any further RUN, COPY, and ENTRYPOINT
# commands.
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME

# Copy the Gemfile as well as the Gemfile.lock and install
# the RubyGems. This is a separate step so the dependencies
# will be cached unless changes to one of those two files
# are made.
COPY ./repository_api/Gemfile $APP_HOME/Gemfile
COPY ./repository_api/Gemfile.lock $APP_HOME/Gemfile.lock
RUN bundle install

# Copy the main application.
COPY ./repository_api $APP_HOME 

# Add a script to be executed every time the container starts.
COPY ./repository_docker/development/repository_api/entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]

# Expose port 3000 to the Docker host, so we can access it
# from the outside.
EXPOSE 3000

# The main command to run when the container starts. Also
# tell the Rails dev server to bind to all interfaces by
# default.
CMD ["rails","server","-b","0.0.0.0"]

docker-compose.yml

    container_name: repository_api
    build:
      context: ../..
      dockerfile: repository_docker/development/repository_api/Dockerfile
    user: $UID
    env_file: .env
    stdin_open: true
    environment:
      DB_NAME: ${POSTGRES_DB}
      DB_PASSWORD: ${POSTGRES_PASSWORD}
      DB_USER: ${POSTGRES_USER}
      DB_HOST: ${POSTGRES_DB}
    volumes:
      - ../../repository_api:/var/www/repository/repository_api
    networks:
      - proxy
      - internal
    depends_on:
      - repository_db

Upvotes: 4

Views: 6540

Answers (1)

riddhi
riddhi

Reputation: 166

A simple solution is to cache the gems in a docker volume. You can create a volume in docker and attach it to the path to bundle gems. This will maintain a shared state and you will not require to install the gems in every container you spun.

  container_name: repository_api
  build:
    context: ../..
    dockerfile: repository_docker/development/repository_api/Dockerfile
  user: $UID
  env_file: .env
  stdin_open: true
  environment:
    DB_NAME: ${POSTGRES_DB}
    DB_PASSWORD: ${POSTGRES_PASSWORD}
    DB_USER: ${POSTGRES_USER}
    DB_HOST: ${POSTGRES_DB}
  volumes:
    - ../../repository_api:/var/www/repository/repository_api
    - bundle_cache:/usr/local/bundle
  networks:
    - proxy
    - internal
    .
    .
volumes: 
  bundle_cache:

Also, a/c to bundler.io, the official Docker images for Ruby assume that you will use only one application, with one Gemfile, and no other gems or Ruby applications will be installed or run in your container. So once you have added all the gems required in your application development, you can remove this bundle_cache volume and rebuild your image with your final Gemfile.

Upvotes: 7

Related Questions