Adam Millerchip

– An Englishman in Japan.

Tech musings, armchair economics, personal finance, etc.

A simple Postgres setup with Docker Compose

Published: 2025-06-20 15:30 JST
Tags: docker postgres tech

In many of my projects, I need a Postgres database. However, installing Postgres is not usually a trivial operation. I have found that using docker compose to manage a local postgres install for each project works well. This allows each project to use its own version of postgres, and keeps the data isolated, avoiding issues with dependencies and also with work on one project affecting the other.

The basic idea is as follows:

  1. Create a compose file to run a postgres server
  2. Configure it to mount a docker volume, which will contain the data.
  3. Expose the port, which will allow our applications to access the database.

Install docker

To use docker compose, we need to have docker installed.

Create a compose file

Here’s a template of the compose file I use. Save it in our working directory to a file called compose.yaml.

services:
  postgres:
    image: postgres:17
    container_name: postgres
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
    volumes:
      - type: volume
        source: data
        target: /var/lib/postgresql/data
    ports:
      - name: postgres
        target: 5432
        published: 5432

volumes:
  data:

Here’s an annotated version, explaining what’s going on:

services:
  # Tell docker compose to create a service called postgres
  postgres:
    # Specify we want version 17 of postgres.
    # This will download it from Docker Hub:
    # https://hub.docker.com/_/postgres
    image: postgres:17
    # Name the container 'postgres'
    container_name: postgres
    # Specify the required environment variables as specified by the
    # Postgres docker documentation. This will create a postgres user with
    # the same password. This is fine for local development, but we wouldn't
    # want to use this for production.
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
    # This creates a docker volume, which will be mounted to the container,
    # and provides a persistent place for the database to store its data,
    # that will survive the container
    # being stopped or removed.
    volumes:
      - type: volume
        source: data
        target: /var/lib/postgresql/data
    # Exposes port 5432 onto our host machine, so we can access it from our
    # application.
    ports:
      - name: postgres
        target: 5432
        published: 5432

# Creates a docker volume called 'data', which we use above
volumes:
  data:

First run

First we download the image, and then start the container.

  1. docker compose pull - this fetches the image
  2. docker compose up - this starts the container

The first time it will initialise the database with the username and password we supplied. In the output, you should see it initialise the database:

running bootstrap script ... ok

It will start the database, perform some setup, shut it down again, and then start it again. At some point we should see:

PostgreSQL init process complete; ready for start up

and finally

database system is ready to accept connections

We can press CTRL+C to stop the container.

Subsequent runs

Now the database has been initialised, we can run it in the background by using --detach:

docker compose up --detach

You can confirm it’s running by typing docker ps:

$ docker ps
CONTAINER ID   IMAGE         COMMAND                  CREATED         STATUS         PORTS                                         NAMES
8a5ff1548b79   postgres:17   "docker-entrypoint.s…"   4 minutes ago   Up 8 seconds   0.0.0.0:5432->5432/tcp, [::]:5432->5432/tcp   postgres

Here we can see there is a container called postgres running, and that port 5432 is being mapped to our host machine.

When we want to stop it, we can run:

docker compose down

And that’s it! We have a simple isolated postgres server that we can start and stop as we wish.

Upgrading postgres

Unfortunately upgrading postgres running on docker is quite an involved process. I wrote a separate post about that.