Adding docker to a Ruby on Rails application might seem like a herculean task at first, but it’s actually not as difficult as it seems. In this article, I will walk you through Docker and how to dockerize a rails application.
What is Docker?
Docker is a tool designed to make it easier to create, deploy, and run applications by using containers. Containers allow a developer to package up an application with all of the parts it needs, such as libraries and other dependencies, and deploy it as one package. Docker is a set of platform-as-a-service products that use OS-level virtualization to deliver software in packages called containers.
To install docker on your computer, click here and select your OS.
Creating a Rails Application
I am using rails 6 to create a new rails application called docker-rails, with Postgres and without running a test.
rails new docker-rails -T --database=postgresql
Dockerizing the Application
Add a file called Dockerfile to the root directory of your application. Notice the file has no extension. Add the following lines of code in that file. I will explain each line later.
FROM ruby:2.7.1
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \ && apt-get install -y nodejs postgresql-client
RUN mkdir /docker-rails
WORKDIR /docker-rails
COPY Gemfile /docker-rails/Gemfile
COPY Gemfile.lock /docker-rails/Gemfile.lock
RUN bundle install –full-index
COPY . /docker-rails
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT [“entrypoint.sh”]
EXPOSE 3000
CMD [“rails”, “server”, “-b”, “0.0.0.0”]
* On line 1 we download Ruby; version 2.7.2 in this case.
* On line 2 we install NodeJS along with all its dependencies and Postgres.
* The code on line 3 creates a directory I called docker-rails
. But you can call yours any name you like.
* Line 4 sets docker-rails
as our working directory that holds all our files.
* Line 5 copies the content of the Gemfile from our directory to docker-rails/Gemfile
in the container.
* Line 6 also copies the content of Gemfile.lock
.
* Line 7 runs bundle install
to install and update our new Gemfile
and Gemfile.lock
.
* Line 8 copies the entire content from the current directory to our working directory in the container docker-rails/
.
* Line 9 copies the content of a file named entrypoint.sh
We will add the file in a bit.
* Line 10 grants access to the file while line number 11 specifies the file to be used as entrypoint.
* Line 12 exposes port 3000 so we can run the rails app on our browser on port 3000.
* Finally, Line 13 contains the command that will be executed to start or run the container.
Add a file named entrypoint.sh
and copy the following to it.
#!/bin/bash
set -e
# If the database exists, migrate. Otherwise setup #(create and migrate)
bundle exec rake db:migrate 2>/dev/null || bundle exec
rake db:create db:migrate echo "Database has been created & migrated!"
# Remove server.pid if it exists
rm -f /docker-rails/tmp/pids/server.pid
# execute container's main process (CMD in docker file) exec "$@"
The above code is executed when entrypoint is called in the Dockerfile. Add a file named docker-compose.yml
. It will contain dependencies of the application. The code that should be in the file is shown below:
version: '3'
services:
db:
image: postgres
environment:
POSTGRES_PASSWORD: 'password1'
PGHOST: "db"
PGUSER: "postgres"
PGDBNAME: "docker-rails"
volumes:
- ./tmp/db:/var/lib/postgresql/data
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/docker-rails
ports: - "3000:3000"
depends_on:
- db
dns:
- 1.1.1.1
- 1.0.0.1
To build our docker container we run docker-compose build
in the project root directory. This will download all required dependencies. After that, run docker-compose up
to start our docker container.
Visit localhost:3000 to see your app running in a docker container.
Phew! You just dockerized your first rails application, not so difficult…was it?