DEV Community

kavin.dev
kavin.dev

Posted on

Setting Up PostgreSQL in Docker with Adminer

PostgreSQL in Docker

A clean local PostgreSQL setup using Docker Compose—with environment variables, persistent storage, health checks, and Adminer included.

Stack: PostgreSQL 17 • Docker Compose • Adminer • Alpine Linux


Why Docker for PostgreSQL?

Installing PostgreSQL directly on your machine works—but it also means managing versions, cleaning up installations, and configuring everything manually.

With Docker Compose, you get:

  • A fresh PostgreSQL instance in seconds

  • Isolated development environment

  • Persistent data using volumes

  • Easy reset whenever needed

  • Adminer for database management in the browser

Let's build it.


Project Structure


your-project/

├── .env

├── compose.yaml

└── data/

    └── db/

Enter fullscreen mode Exit fullscreen mode

Important: Keep .env and compose.yaml in the same directory. Docker Compose automatically loads .env only when both files are located together.


Step 1 — Create the .env file

Create a file named .env.


DB_NAME=postgres

DB_USER=your_username

DB_PASSWORD=your_password

DB_PORT=5432

Enter fullscreen mode Exit fullscreen mode

Keeping credentials here makes your Compose file cleaner and easier to reuse.

Tip: Add .env to .gitignore. Even for local projects, credentials should never be committed.


Step 2 — Create compose.yaml

We'll run two containers:

  • PostgreSQL

  • Adminer


services:

  db:

    image: postgres:17-alpine

    container_name: postgres

    restart: always

    environment:

      POSTGRES_DB: ${DB_NAME}

      POSTGRES_USER: ${DB_USER}

      POSTGRES_PASSWORD: ${DB_PASSWORD}

    ports:

      - ${DB_PORT}:5432

    healthcheck:

      test: ["CMD-SHELL", "pg_isready -d $${DB_NAME} -U $${DB_USER}"]

      interval: 10s

      timeout: 30s

      retries: 5

    volumes:

      - ./data/db:/var/lib/postgresql/data

    attach: false

  database-ui:

    image: adminer

    restart: always

   ports:

      - 8080:8080

    depends_on:

      db:

        condition: service_healthy

Enter fullscreen mode Exit fullscreen mode

Understanding the Compose File

Environment Variables


environment:

  POSTGRES_DB: ${DB_NAME}

  POSTGRES_USER: ${DB_USER}

  POSTGRES_PASSWORD: ${DB_PASSWORD}

Enter fullscreen mode Exit fullscreen mode

These values come directly from the .env file.

PostgreSQL reads them only during the first initialization.

If the data directory already exists, PostgreSQL simply starts using the existing database.


Health Check


healthcheck:

  test: ["CMD-SHELL", "pg_isready -d $${DB_NAME} -U $${DB_USER}"]

Enter fullscreen mode Exit fullscreen mode

Instead of checking whether the container is merely running, Docker waits until PostgreSQL is actually ready to accept connections.

Notice the double dollar signs:


$${DB_NAME}

Enter fullscreen mode Exit fullscreen mode

Docker Compose escapes the variable, allowing it to be evaluated inside the container, not by Compose itself.


Persistent Storage


volumes:

  - ./data/db:/var/lib/postgresql/data

Enter fullscreen mode Exit fullscreen mode

This maps PostgreSQL's data directory to your project folder.

Benefits:

  • Data survives container restarts

  • Easy backups

  • Delete the folder anytime for a fresh database


Service Dependency


depends_on:

  db:

    condition: service_healthy

Enter fullscreen mode Exit fullscreen mode

Adminer waits until PostgreSQL reports a healthy state before starting.

Without this, Adminer may start too early and fail to connect.


Step 3 — Start Everything

Run:


docker compose up -d

Enter fullscreen mode Exit fullscreen mode

On the first run Docker will:

  • Download both images

  • Create the containers

  • Initialize PostgreSQL

  • Start Adminer

Give PostgreSQL around 10–15 seconds to finish initialization.


Check Container Status


docker compose ps

Enter fullscreen mode Exit fullscreen mode

A healthy PostgreSQL container looks similar to:


NAME         STATUS

postgres     Up (healthy)

database-ui  Up

Enter fullscreen mode Exit fullscreen mode

Step 4 — Open Adminer

Open your browser and navigate to:

http://localhost:8080

You'll see the Adminer login page.

Image of Adminer page

Use the following details:

Use the credentials from your .env file.

System   : PostgreSQL
Server   : db
Username : <your DB_USER>
Password : <your DB_PASSWORD>
Database : <your DB_NAME>
Enter fullscreen mode Exit fullscreen mode

Why use db instead of localhost?

Inside Docker, every service gets its own hostname.

Since PostgreSQL's service is named:


db:

Enter fullscreen mode Exit fullscreen mode

Adminer can reach it using:


db

Enter fullscreen mode Exit fullscreen mode

Using localhost would point to the Adminer container itself—not PostgreSQL.


Useful Docker Commands

Stop the containers


docker compose down

Enter fullscreen mode Exit fullscreen mode

Your database remains because it's stored in ./data/db.


View PostgreSQL logs


docker logs -f postgres

Enter fullscreen mode Exit fullscreen mode

Verify environment variables


docker compose config

Enter fullscreen mode Exit fullscreen mode

Connect directly using psql


docker exec -it postgres psql -U your_username -d postgres

Enter fullscreen mode Exit fullscreen mode

Replace your_username with the value from your .env file.


Final Thoughts

That's it!

You now have a fully reproducible PostgreSQL development environment powered by Docker Compose.

With just two containers, you've added:

  • PostgreSQL 17

  • Persistent storage

  • Health checks

  • Environment variable support

  • Adminer web interface

Top comments (0)