Configuring a PostgreSQL Database with Docker for a Rails App
Tags: rails, postgres, docker, webdev
Published: 2024-02-12 20:53:11

#### Introduction

[Docker](https://docs.docker.com/get-started/) and [Docker Compose](https://docs.docker.com/compose/gettingstarted/) are indispensable tools in modern development workflows. They simplify the setup and management of development environments, ensuring consistency across various setups. There are a plethora of resources available for understanding Docker and Docker Compose, and their installation guides can be found [here](https://docs.docker.com/get-docker/) and [here](https://docs.docker.com/compose/install/) respectively. Since these topics are well explored, we’ll dive straight into configuring a PostgreSQL database for your Rails project using Docker Compose, emphasizing PostgreSQL version specification and managing separate volumes for different versions.

#### Prerequisites

Before we dive in, ensure you have the following set up:
- Docker and Docker Compose installed on your machine.
- A Rails project set up and ready to be configured with a PostgreSQL database.
- A basic understanding of Rails and PostgreSQL.

#### Step 1: Installing Docker and Docker Compose

If you haven't installed Docker and Docker Compose yet, follow the official guides linked in the introduction. Once installed, verify the installations by running the following commands in your terminal:

```bash
docker --version
docker-compose --version
```

#### Step 2: Defining Volumes

In Docker, volumes are utilized for data persistence across container restarts and sharing data among containers. They are paramount for databases to ensure that data remains intact even when containers are stopped or removed. For our PostgreSQL setup, having separate volumes for different versions of PostgreSQL is beneficial to avoid any data conflicts or corruption when switching between different versions.

```yml
volumes:
  postgres_data_16:
  postgres_data_15:
```

In the snippet above, we define separate volumes for PostgreSQL versions 16, 13, and 12.

#### Step 3: Creating a Docker Compose File

Docker Compose facilitates the management of multi-container Docker applications. We'll create a `docker-compose.yml` file to define our PostgreSQL service, specifying the version and linking the appropriate volume for data storage.

```yml
version: '3'
services:
  db:
    image: postgres:16
    environment:
      POSTGRES_DB: myapp_development
      POSTGRES_USER: myappuser
      POSTGRES_PASSWORD: myapppassword
    volumes:
      - postgres_data_16:/var/lib/postgresql/data
    ports:
      - "5416:5432"
volumes:
  postgres_data_16:
  postgres_data_15:
```

In this configuration, we've specified the PostgreSQL version as 16, defined the database user and password, mounted the `postgres_data_16` volume to the `/var/lib/postgresql/data` directory inside the container, and mapped the container's port 5432 to the host's port 5160.

#### Step 4: Setting up the Procfile.dev

The `Procfile.dev` is a manifest used in Rails projects to define the services required for the development environment. Create a `Procfile.dev` file in the root of your project with the following content:

```Procfile.dev
web: bundle exec rails s
db: docker-compose up db
```

This configuration specifies three services: the Rails server, Sidekiq for background jobs, and our Docker Compose-managed PostgreSQL database.

#### Step 5: Starting Your Development Environment

With all configurations in place, use Foreman to start your development environment:

```bash
foreman start -f Procfile.dev
```

Foreman will launch the services defined in `Procfile.dev`, getting your development environment up and running.

#### Conclusion

We've streamlined the process of configuring a PostgreSQL database for a Rails project using Docker Compose. This setup not only simplifies the database management but also ensures consistency across different development environments. Feel free to adapt this setup to your projects, and explore further customizations to tailor the environment to your needs.