Bundle with docker-compose installs gems from scratch - ruby-on-rails

I'm trying to cache bundle install on Docker build.
I've tried recommendations from several blog posts and I ended up in something like this:
Dockerfile:
FROM ruby:2.5.0-alpine
RUN apk update && apk add build-base postgresql-dev nodejs git tzdata
ENV APP_HOME /panabus-api
RUN mkdir $APP_HOME
WORKDIR $APP_HOME
COPY Gemfile Gemfile.lock ./
ENV BUNDLE_PATH /gems
ENV GEM_PATH /gems
ENV GEM_HOME /gems
RUN bundle check || bundle install
COPY . $APP_HOME
ENV RAILS_ENV=production
RUN bundle exec rake RAILS_ENV=production assets:precompile apipie:cache
LABEL maintainer="Hari Carreras PĂ©rez <hc#abtion.com>"
CMD bundle exec puma -C config/puma.rb
docker-compose.yml
version: '3'
services:
box:
image: busybox
volumes:
- gem_cache:/gems
postgres:
image: postgres:10.3-alpine
ports:
- 5432:5432
volumes:
- postgres:/var/lib/postgresql/data
restart: always
web:
build: .
image: panabus-api-web
command: bundle exec puma -C config/puma.rb -p 3000
depends_on:
- postgres
- box
volumes:
- .:/panabus-api
- gem_cache:/gems
ports:
- "3000:3000"
restart: always
environment:
- RAILS_ENV=development
tty: true
stdin_open: true
setup:
build: .
depends_on:
- postgres
- box
environment:
- RAILS_ENV=development
volumes:
- .:/panabus-api
- gem_cache:/gems
command: "bin/rails db:create db:migrate"
volumes:
postgres:
gem_cache:
This doesn't update the gems if the Gemfile hasn't changed. Unfortunately, if it has changed, it install all gems from scratch, not using the cache.
Is there any way to cache the gems on build?
I'd like to keep bundle in the Dockerfile since Heroku uses the same Dockerfile.

You need to add a tag to your bundle check where you have cached the installed gems
bundle check || bundle install --binstubs="$BUNDLE_BIN"
and cache the bundle with a specific path like so
ENV BUNDLE_PATH=/bundle \
BUNDLE_BIN=/bundle/bin \
GEM_HOME=/bundle
ENV PATH="${BUNDLE_BIN}:${PATH}"

Related

Could not locate Gemfile or .bundle/ directory

I am trying to use docker on with a rails apps. This setup works on other developers machines, but not mine. I can get the mysql to "up" but not the rails app. I've been at it for 2 days now.
I'm on windows 10 home using the Docker Quickstart Terminal. I was able to run this about a year ago on the same machine.
Here is my Dockerfile:
FROM ruby:2.5.3
ARG workdir=/bundle-api
RUN apt-get update -qq && apt-get install -y build-essential netcat graphviz
RUN mkdir -p ${workdir}
WORKDIR ${workdir}
ADD Gemfile ${workdir}/Gemfile
ADD Gemfile.lock ${workdir}/Gemfile.lock
RUN bundle install
ADD . ${workdir}
Here is my docker-compose file:
version: '2'
services:
db:
image: mysql:5.7
container_name: bundle-mysql
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: bundle_api_pwd
MYSQL_DATABASE: bundle_api_dev
MYSQL_USER: bundle_api
MYSQL_PASSWORD: bundle_api_pwd
ports:
- "3306:3306"
web:
build: .
container_name: bundle-rails
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/bundle-api:cached
- bundle_cache:/bundle_cache
ports:
- "3100:3000"
environment:
DB_HOST: db
DB_USERNAME: root
DB_PASSWORD: bundle_api_pwd
BUNDLE_PATH: /bundle_cache
GEM_HOME: /bundle_cache
GEM_PATH: /bundle_cache
depends_on:
- db
stdin_open: true
tty: true
bundle_cache:
image: busybox
volumes:
- bundle_cache:/bundle_cache
volumes:
db_data:
bundle_cache:
To start fresh I run this:
docker-compose build --no-cache
Everything seems to work fine. I can see all the gems install.
Once it runs, I run: docker-compose up and get this error.
bundle-rails | Could not locate Gemfile or .bundle/ directory
bundle-rails exited with code 10
Name Command State Ports
------------------------------------------------------------------------------------------------------------
bundle-backend_bundle_cache_1 sh Exit 0
bundle-mysql docker-entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp, 33060/tcp
bundle-rails bundle exec rails s -p 300 ... Exit 10
Looks like you are setting BUNDLE_PATH in the docker-compose.yml but you don't set it in the Dockerfile. That means you gems will be installed to /usr/local/bundle but then when you start the container ruby looks in /bundle-cache for the gems.

Could not locate Gemfile or .bundle/ directory when starting rails container on Windows 10 host

I am having trouble with a rails container in a docker-compose network. I have not touched it in a few months, and when I attempted to start it this week it fails.
When I attempt to start the container with docker-compose up service the startup fails with:
service_1 | Could not locate Gemfile or .bundle/ directory
support_portal_service_1 exited with code 10
Both files are present, the host is a Windows 10 machine.
Bundle install completes succesfully:
Bundle complete! 19 Gemfile dependencies, 83 gems now installed.
Bundled gems are installed into `/usr/local/bundle`
What I have tried:
Added ruby and ruby-all-dev to apt-get install in case missing requirements were the issue
Changed ADD Gemfile /app/Gemfile to COPY Gemfile /app/Gemfile
Tried commenting out Gemfile.lock /app/Gemfile.lock
Ran bundle install on the Windows 10 host
Rebuild the container without cache
Insuring docker has access to the drive/directory
Here is my Dockerfile:
FROM ruby:2.5.3
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs default-libmysqlclient-dev ruby ruby-all-dev
RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
#COPY Gemfile.lock /app/Gemfile.lock
WORKDIR /app
RUN bundle install
ADD . /app
And my docker-compose.yml:
version: '2'
services:
# Structured database
sqldb:
image: mysql:5.7
volumes:
- sql:/var/lib/mysql
env_file:
- .env
environment:
- MYSQL_USER=web
- MYSQL_ROOT_PASSWORD=${PORTAL_DATABASE_PASSWORD}
- MYSQL_PASSWORD=${PORTAL_DATABASE_PASSWORD}
ports:
- "3306:3306"
# Application server
service:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/app
env_file:
- .env
expose:
- "3000"
depends_on:
- sqldb
# Front end proxy
web:
image: nginx
build:
context: .
dockerfile: Dockerfile-web
depends_on:
- service
ports:
- "80:80"
- "144:144"
# Persistence
volumes:
sql:

error running db migrate with docker for rails

I'm trying to set up an dev environment for Vue.js and rails API following a tutorial.
Eventually I hit a hurdle when trying to run the following command:
docker-compose run backend rails db:create
Here is the error:
$ docker-compose run backend rails db:create
Starting am-full-stack_db_1_b7f6ee37d2e4 ... done
Error response from daemon: OCI runtime create failed:
container_linux.go:348: starting container process caused "exec:
\"rails\": executable file not found in $PATH": unknown
Here is my file tree
App
autheg-backend
autheg-frontend
docker-compose.yml
Here is my docker-compose.yml
version: '3'
services:
db:
image: postgres
ports:
- "5432"
backend:
build:
context: autheg-backend
args:
UID: ${UID:-1001}
volumes:
- ./autheg-backend:/usr/src/app
ports:
- "8080:8080"
depends_on:
- db
user: rails
frontend:
build:
context: autheg-frontend
args:
UID: ${UID:-1001}
volumes:
- ./autheg-frontend:/usr/src/app
ports:
- "3000:3000"
user: frontend
Result of 'docker-compose run backend env'
PATH=/usr/local/bundle/bin:/usr/local/bundle/gems/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=c88e0c72c584
TERM=xterm
RUBY_MAJOR=2.5
RUBY_VERSION=2.5.3
RUBY_DOWNLOAD_SHA256=1cc9d0359a8ea35fc6111ec830d12e60168f3b9b305a3c2578357d360fcf306f
RUBYGEMS_VERSION=2.7.8
BUNDLER_VERSION=1.17.1
GEM_HOME=/usr/local/bundle
BUNDLE_PATH=/usr/local/bundle
BUNDLE_SILENCE_ROOT_WARNING=1
BUNDLE_APP_CONFIG=/usr/local/bundle
APP=/usr/src/app
HOME=/home/rails
Thanks!
to do db migration use:
docker-compose run backend bin/rails db:create
# or
docker-compose run backend bundle exec rails db:create
/backend/Dockerfile
FROM ruby:2.5
ARG UID
RUN adduser rails --uid $UID --disabled-password --gecos ""
ENV APP /usr/src/app
RUN mkdir $APP
WORKDIR $APP
COPY Gemfile* $APP/
RUN bundle install -j3 --path vendor/bundle
COPY . $APP/
# Setting env up
ENV RAILS_ENV='development'
ENV RACK_ENV='development'
CMD [ "bundle", "exec", "rails", "server", "-p", "8080", "-b", "0.0.0.0"]
./docker-compose.yml
version: '3'
services:
db:
image: postgres
ports:
- "5432"
backend:
build:
context: autheg-backend
args:
UID: ${UID:-1001}
command: bundle exec rails s -p 8080 -b '0.0.0.0'
volumes:
- ./autheg-backend:/usr/src/app
ports:
- "8080:8080"
depends_on:
- db
user: rails
frontend:
build:
context: autheg-frontend
args:
UID: ${UID:-1001}
volumes:
- ./autheg-frontend:/usr/src/app
ports:
- "3000:3000"
user: frontend
Then
docker-compose up
Now you should be able to see the rails site using:
localhost:8080 (instead of 3000)
Hope that helps you get started
Where is your backened dockerfile for rails development like this example:-
# Base image:
FROM ruby:2.5
# Install dependencies
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
# create application directory
RUN mkdir /myapp
# Set our working directory inside the image
WORKDIR /myapp
# Setting env up
ENV RAILS_ENV='development'
ENV RACK_ENV='development'
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ADD . /myapp
EXPOSE 3000
CMD [ "bundle", "exec", "puma", "-C", "config/puma.rb" ]
This is caused because the path is not set in the Docker container, it's set on your development/local machine. Use the following command:
docker-compose run backend bundle exec rails db:create

Docker-compose rails image won't start after reboot

It ran just before I rebooted my machine, and suddenly I get Could not locate Gemfile or .bundle/ directory when starting the container.
During build, which completes without issue, I can see the contents of /app are correct, but on startup, /app only contains a .bundle directory and nothing else.
UPDATE: Turns out the volume ./documents_api:/app is what isn't working. Environment is docker for windows 17.09.1 running as administrator
Here is my folder structure:
./
.env
docker-compose.yml
documents_api/
<typical rails directory contents>
Dockerfile
.env just contains RAILS_ENV=development
the dockerfile contains:
FROM ruby:2.3.3
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /app
WORKDIR /app
ADD Gemfile /app/Gemfile
ADD Gemfile.lock /app/Gemfile.lock
RUN bundle install
ADD . /app
docker-compose.yml contains:
version: '3'
services:
database:
image: mongo
volumes:
- mongo:/var/lib/mongo
env_file:
- .env
ports:
- "27017:27017"
documents:
build: ./documents_api
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- ./documents_api:/app
env_file:
- .env
expose:
- "3000"
depends_on:
- database
frontend:
image: nginx
build: ./web
depends_on:
- documents
ports:
- "80:80"
- "144:144"
# Persistence
volumes:
mongo:
Turns out I needed to remap my shared drives in the settings. It had lost the credentials after the reboot and was silently failing to map the volume.

Precompiled assets absent in the docker image

I am trying to run simple Rails app using docker.
Source code taken from data container 'app'. The 'app' data container also used by nginx to server precompiled assets and static files.
But no precompiled assets found after running 'bundle exec rake assets:precompile'.
I am using docker on Mac OS X with VirtualBox (Docker version 1.10.1, build 9e83765).
docker-compose.yml
version: '2'
services:
web:
build: .
command: bundle exec puma
env_file: .env
environment:
- RACK_ENV=production
- RAILS_ENV=production
volumes_from:
- app
ports:
- "3000:3000"
links:
- db
nginx:
image: nginx
ports:
- "80:80"
volumes_from:
- app
volumes:
- /app/public:/usr/share/nginx/html:ro
- /app/config/deploy/nginx.conf:/etc/nginx/conf.d/default.conf
db:
image: postgres
env_file: .env
volumes_from:
- data
app:
image: busybox
volumes:
- /myapp/app:/app:rw
data:
image: busybox
volumes:
- /myapp/data:/var/lib/postgresql/data
Dockerfile
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
WORKDIR /app
ADD . /app
RUN gem install bundler && bundle install --jobs 20 --retry 5 --without development test && rake assets:precompile
VOLUME /app/public
I tried also without 'VOLUME /app/public'
Please advice what can be the issue.
Thanks.
Volumes are not mounted during a docker build.
Run the rake assets:precompile task post build from a container with the volume mounted.
Also, since Docker 1.9, you no longer require a "data volume container". Volumes can exist on their own.
$ docker volume create --name=app_public
$ docker run -v app_public:/public busybox sh -c "echo hello > /public/file.txt"
$ docker run -v app_public:/public busybox sh -c "cat /public/file.txt"

Resources