Why use Docker
First of all, why should I use Docker in a development environment when it’s better to build it directly on my local system?
Using Docker in a development environment provides the following benefits.
- Solidify the development environment into a configuration file, which makes it easy for new developers to start.
- Isolating system dependencies across projects to avoid interactions.
- Make the development environment as close to the production environment as possible to avoid potential problems due to system inconsistencies.
The more projects you manage, the more you will appreciate the benefits of containerizing your development environment.
Introduction to Docker Compose
For projects like Rails, in addition to dependencies on the operating system, there are usually external services like PostgreSQL and Redis. A single Docker container is not enough to manage all development dependencies, so Docker Compose is needed.
💡 Docker’s best practice is to run one process per container to easily manage container state and logging.
Docker Compose is a tool that comes with Docker Desktop that defines multiple services needed by an application via YAML configuration files, and then builds and starts them together.
Using Docker Compose is divided into about three steps.
- Write the project’s
Dockerfile
for building the project image. - Write the project’s
docker-compose.yml
configuration, which defines the services needed to start the project. - Start the application with the
docker compose up
command.
The contents of docker-compose.yml
look like this.
As you can see from the above example, the Compose file can define multiple services, each corresponding to a container. service content includes the image to be used, the open ports and the local directory to be mounted, etc. The detailed syntax of docker-compose.yml
can be found in the official documentation.
Build a Rails application development environment
The following shows how to build a Rails development environment with Docker Compose.
💡 Here’s the chicken or the egg question. Our goal is to put all our dependencies in Docker, but how do we create a Rails project if we don’t have Ruby installed on our local system? rails/) provides a bootstrap approach, building an initial image, starting the container to create the project, and then rebuilding the image.
I chose a different approach: first open a temporary Ruby container, create the project inside the container, and later build the image needed for development.
Create a new project
In order to create a Rails project, start a temporary Ruby container first.
|
|
To install the Rails gem inside the container.
|
|
Then create the project.
|
|
The --skip-bundle
argument is used here because this is only a temporary container and the bundle
will be executed later in the development container.
Now that the temporary container has completed its mission, press ctrl-d
or type exit
to exit the container.
Adding a Dockerfile
Add a Dockerfile
file to the project directory and enter the following.
This is a minimalist image of the Rails development environment, and you can use apt-get
to install other system dependencies if needed.
You don’t need to build the image yet, we’ll build it together later with the docker compose
command.
Add docker-compose.yml
Add the docker-compose.yml
file to the project directory and enter the following.
Here web and postgres services are defined. web service builds an image based on the Dockerfile file in the current directory and mounts the current directory to the /app
directory in the container, releasing port 3000 and adding a startup dependency on the postgres servcie. postgres service will use the postgres image and set the initial password via environment variables.
Build the image
Execute the following command.
|
|
Docker Compose will read the configuration in docker-compose.yml
and build the image accordingly.
You have to re-execute this command every time you modify Dockerfile
.
Go to the command line
Execute the following command.
|
|
This will start the web service container and open a bash shell where we can execute the commands we need to execute for local development, such as bundle install
, bin/rails g
, and so on.
Any later operations that need to be performed inside the container will be executed through this shell.
Execute bundle
First execute the following command inside the container.
|
|
This command sets the bundle installation directory to the vendor/bundle
directory under the project. This is because I don’t want to have to rebuild the image every time I update the Gemfile during development.
Then execute bundle
.
|
|
❗️ Remember to add
vendor/bundle
to.gitignore
.
Preparing the database
Before creating the database, you need to modify the database settings of the Rails project, because in the environment built by Docker Compose, PostgreSQL and Rails processes run in different containers, similar to different hosts, and the service name is their respective network name.
Modify database.yml
and add the following to the development
and test
paragraphs.
Then execute the following command.
|
|
After that, the corresponding database will be created.
Start the web service
After the above preparations, it is time to start the web service. Open another terminal and enter the following command.
|
|
Once the launch is complete, request http://localhost:3000/
and you will see the Rails launch page.
Press ctrl-c
to close the servcie.