Andrés
•
20 October 2023
You probably already know the advantages of using Docker, we’ve already heard about it or evidenced it in projects. Here I will show you how to bring that to your Ruby on Rails application. To do what is proposed you need a Rails application, Docker installed on your computer and/or your server and motivation for a couple of trial and error.
This is a general explanation and not a step by step guide. Some definitions may need more work depending on your project.
You will need a Dockerfile
file in the root of your project with the following content:
FROM ruby:3.2.2
RUN apt-get update && apt-get install -y libsodium-dev
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN gem install bundler && bundle install
COPY . .
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
Step-by-step explanation:
ruby:3.2.2
image because my project uses that version of Ruby.RUN apt-get update && apt-get install -y libsodium-dev
For example, if your application uses libvips for image processing, then you will have to add the corresponding command to install it here. You can check if the image you choose contains the package you need on the page of the image.
ENTRYPOINT
.Why an entrypoint? Basically, because there are commands that must run at the moment of lifting a container with our image and not at the moment of the image construction. A clear example of this is the db:migrate
command.
Then we will need another file in the root of our project called entrypoint.sh
with the following content:
/bin/bash
if [ -f tmp/pids/server.pid ]; then
rm tmp/pids/server.pid
fi
RAILS_ENV=$RAILS_ENV bundle exec rails db:migrate
RAILS_ENV=$RAILS_ENV bundle exec rails s -b 0.0.0.0.0
Step by step explanation:
**You may need to create different entrypoints depending on your needs. Let’s imagine the case that you are using whenever. Your entrypoint should update the crontab every time it runs, but you also don’t want all your containers to run the cronjobs at the same time. So that’s when you need one container to run your web service and another one to run your cronjobs. That is, two different entrypoints for the same project.
To solve that case you can create a folder in your project with the name entrypoints
and leave your different entrypoints there. Your Dockerfile is left with one entrypoint by “default” and when you need to overwrite it (https://docs.docker.com/engine/reference/builder/#entrypoint) when running a container with the --entrypoint
flag.
Depending on the environment in which we are running our project, it is important to add some ENVs to the container:
credentials.yml.enc
file.If you want to test your image you can build it locally with the following command:
docker build -t rubyapp .
Then you can run a container from your image:
docker run -p 3000:3000 -e DATABASE_URL={YOUR_DATABASE_URL_HERE} rubyapp
Note: This is where you will need to add the environment variables, at least the database.
Our Dockerfile can become more complex according to our needs, but as long as you understand how it works, it will not be difficult to adapt it and make modifications. I hope these indications are useful, and if you consider that some important topic is missing, don’t hesitate to leave me a comment about it.
enjoy programming.