Using Docker on a new Rails app
As covered in previous articles, Docker is a paradigm shift that allows for developers to share images and develop without as much attention to dependencies.
Now how do we actually use it for a new application? In this article, I will cover a quick start of Docker use in a rails app.
Dockerfile
Any Dockerized app begins with the Docker file. Here is a simple template Dockerfile used to bootstrap a Dockerized Rails app.
FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp
# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]
You can change the ruby version to your preferred version, and you can also rename the directories as needed. Please just remember to change all the directories to be uniform, in this dockerfile as well as any future files.
Creating the starter files
As you can see in the dockerfile, we will be using a Gemfile of some sort as well as an entrypoint.sh file. We can now create those.
#Gemfile
source 'https://rubygems.org'
gem 'rails', '~>5'
This gemfile will quickly be replaced with a Rails gemfile, so don’t worry about it other than this line. Also, please create a Gemfile.lock, which is referenced in the dockerfile as well.
touch Gemfile.lock
Lastly, create an entrypoint file in the directory which will be run every launch.
#entrypoint.sh
#!/bin/bash
set -e
# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid
# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
The last file we will need to create is the docker-compose.yml file.
#docker-compose.yml
version: '3'
services:
db:
image: postgres
volumes:
- ./tmp/db:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: password
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
This file will create two separate containers for your database and web app and link them together using docker networking.
Project Build
With all the files created, you can now use docker commands in order to generate a Rails app skeleton:
docker-compose run web rails new . --force --no-deps --database=postgresql
This will build the image for web and then run the rails new command, which creates a new rails app.
This will update your Gemfile through rails new, so now you can rebuild the image using docker-compose.
docker-compose build
Setting up the Database
Last thing to do will be to point the Rails configuration to the db container that you created for Docker. You can do this by changing the host property in the Docker config/database.yml file.
config/database.yml
default: &default
adapter: postgresql
encoding: unicode
host: db
username: postgres
password: password
pool: 5
development:
<<: *default
database: myapp_development
test:
<<: *default
database: myapp_test
After this, you will be able to launch the app using docker-compose properly:
docker-compose up
Lastly, you can create the database, using this command in another terminal:
docker-compose run web rake db:create
This will now allow you to access the Rails app via your localhost:3000, as detailed in the docker-compose.yml configuration. You can also change the port you want to access by modifying that file.
Recap Basic Commands
docker-compose up
This will launch the docker-compose app in the directory you are in. In this case, it will launch both the database and web applications that you have set up in this guide. You can also add the -d flag to run the application detached, but that will require the next command to exit.
docker-compose down
This is essentially the opposite of the docker-compose up command and will go through the process to quit your app.
docker-compose build
This will rebuild the docker-compose image. This will be needed if you make changes to the gemfile or the compose file to try different configurations. You can also full rebuild using the following command:
docker-compose run web bundle install
Docker-compose run web in general will allow you to run many of the commands you were used to in Rails development. For example, to use ‘rails db:migrate’, you would use this:
docker-compose run web rake db:migrate
Sources
This article is primarily sourced through the following instructions:
I have provided more context and color to the explanations, as well as a recap of the basic commands you will use to interact with the dockerized app.