Dockerize your Rails app with MongoDB:
1. Create a Dockerfile
in your project root for Ruby setup.
2. Define services (database and web app) in compose.yml
.
3. Build Docker images.
4. Update mongoid.yml
for database configuration.
5. Start containers with docker compose up
.
6. Access your app at localhost:3000
.
Initial challenge
A few weeks ago, I was tasked with “dockerizing” a Rails app that uses MongoDB. I quickly realized there aren’t many guides available for this specific setup. There is ample documentation for integrating Postgres, but tutorials for non-relational databases are scarce. That’s why I decided to write this simple guide…
… but first, let’s do a brief overview to Docker.
Introduction to Docker
Docker is an open-source platform that automates the deployment, scaling, and management of applications. It uses containerization technology to encapsulate them and their dependencies into self-contained units that can run uniformly on any system with Docker installed.
First, go to the Docker page and download the Desktop tool. This will install several tools that you could install separately, but for the purpose of this post, we recommend using the installer.
Docker’s file
Once you have installed the Desktop tool, navigate to your project’s root directory and create a file named Dockerfile
without any extension.
Add the following code to it:
FROM ruby:3.2-bullseye as base
RUN apt-get update -qq && apt-get install -y build-essential apt-utils libpq-dev nodejs
WORKDIR /docker/app
COPY Gemfile* ./
RUN bundle install
ADD . /docker/app
We will explain what that configuration does, going over it line by line:
-
FROM ruby:3.2-bullseye as base: Specifies the base image for subsequent instructions, which is Ruby 3.2 on the Debian “bullseye” release.
-
RUN apt-get update -qq && apt-get install -y build-essential apt-utils libpq-dev nodejs: Updates the package lists for upgrades and new installations, then installs essential packages for the Rails application. While not strictly necessary, it’s beneficial to start with the latest versions.
-
WORKDIR /docker/app: Sets the working directory of the project to
/docker/app
in the Docker container. All subsequent commands will be run from this directory. -
COPY Gemfile* ./: Copies the
Gemfile
andGemfile.lock
from your project to the current directory in the Docker container. -
RUN bundle install: Installs the Ruby dependencies specified in the
Gemfile
. -
ADD . /docker/app: Copies the entire current directory (your Rails application) into the
/docker/app
directory in the Docker container.
At this stage, we have a Docker container configured with the Rails web app. Now, we need to set up the MongoDB database to get it fully operational. According to the documentation, to have MongoDB working, you need to create another container and connect it to the Rails container via a Docker Network.
In order to avoid manual set up, we will create a second configuration file.
The composite
A Dockerfile
defines the environment for a single Docker container, but it doesn’t manage the orchestration of multiple containers. In a typical application, you might have several services running in separate containers that need to interact with each other. This is where Docker Compose comes in.
Create a new file named compose.yml
at the root of your project, similar to the Dockerfile
. This file describes the services that make up your app, in this case, a MongoDB database and a Rails web app.
The compose.yml
file specifies how to obtain each service’s Docker image: the database uses a pre-made MongoDB image, and the web app is built from the current directory. It also outlines the configuration needed to link these services together.
With Docker Compose, each service joins a default network, making them reachable and discoverable by other services on it. This means your Rails and MongoDB services can interact without manually creating a network.
Your new file will look like this:
services:
db:
container_name: my_database_container
image: mongo:6.0
restart: always
ports:
- "27017:27017"
web:
container_name: my_web_container
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 responds to the service name, not the container's name.
Build your project
To build your project using the previous configuration, run:
./my_project: $ docker compose build
This command builds all the services defined in your compose.yml
file that have a build context specified (if you use the -f
flag you can specify another file, but we won’t talk about it in this post). For each of these services, Docker performs the following steps:
Use the specified
Dockerfile
to build each image. In our case, Docker will use theDockerfile
we created previously to build theweb
service.Builds a new image according to the instructions in the
Dockerfile
.Tags the new image with the name specified in the
compose.yml
file, if provided.
The result is a Docker image for each service that you can then start with the command docker compose up
. If the images were already built and no changes were made to the Dockerfile
or the build context, the existing images will be used.
Configure your database
If we were to run the web app in its current state, it would break immediately because the database configuration would be incorrect—it needs to point to the MongoDB container.
To access our database, we must establish a new host for all Rails environments in the mongoid.yml
file.
Below is the code snippet where we set up the host for the development environment by specifying the name of the database service defined in the Docker Compose file:
development:
clients:
default:
database: app_development
hosts:
- db:27017 # "db" is the name of MongoDB service in `compose.yml` we created in the previous section.
options:
server_selection_timeout: 1
Run your application
We have successfully configured our Ruby on Rails and MongoDB services within Docker containers, and corrected the MongoDB configuration inside the Rails app.
First, rebuild the containers using the build
command mentioned earlier.
Next, to start the web service and its associated database service, execute the following command in your terminal:
./my_project: $ docker compose up
This will start both the web and database services. Once they are up, you can access your application at localhost:3000
in your browser.
All in all..
Dockerizing a Rails application with MongoDB can significantly streamline your development and deployment processes. By following the steps outlined in this guide, you can create a Dockerfile
and a compose.yml
file to define and manage your application’s services. This approach ensures consistency across different environments and simplifies the setup process for new team members.
With Docker, you can build, ship, and run your application anywhere, making your workflow more efficient and reliable. Dockerization facilitates better scalability, portability, and dependency management for your Rails and MongoDB applications.
Ready to Dockerize your Rails app with MongoDB? Contact us for guidance and support!