Skip to main content

Docker pgAdmin: How to Set Up a PostgreSQL GUI With Docker Compose

A step-by-step guide to setting up pgAdmin 4 and PostgreSQL with Docker Compose, covering container configuration, server registration, and core pgAdmin features including the Query Tool, schema browser, and backup/restore.
Mar 28, 2026  · 10 min read

Switching between sessions, memorizing syntax, and hoping you didn't typo a destructive query gets old fast. There's no visual query plan, no schema browser, and no easy way to back up a database. It works, but it's far from ideal.

pgAdmin 4 fixes this with a browser-based GUI built specifically for PostgreSQL. And running it in Docker means zero local installation. You just have to start the container.

In this article, I'll show you how to set up PostgreSQL and pgAdmin 4 with Docker Compose, connect the two containers, and use pgAdmin's Query Tool, schema browser, and backup features.

To follow along, you'll need Docker installed and running on your machine. If you're new to Docker Compose, read our guide to check how it simplifies multi-container development.

What Is pgAdmin 4?

pgAdmin 4 is an open-source, browser-based admin and development platform for PostgreSQL. You access it through a web browser, so there's no desktop app to install. It gives you a GUI to manage databases, run queries, inspect schemas, and handle backups - all without touching the command line.

The official Docker image is dpage/pgadmin4, maintained by the pgAdmin development team.

Running pgAdmin 4 in Docker has a couple of real advantages over a local install. First is portability - your whole database environment lives in a docker-compose.yml file you can share with teammates. Second, there are no version conflicts - pgAdmin runs in its own container, completely isolated from anything else on your machine. And when you're done, docker compose down wipes it clean.

pgAdmin 4 vs. other PostgreSQL GUIs

There's no shortage of database management GUI tools. Here's how pgAdmin 4 compares with two popular alternatives.

pgAdmin 4 versus popular alternatives

pgAdmin 4 versus popular alternatives

DBeaver and TablePlus are good tools, but neither has an official Docker image. If your PostgreSQL instance is already running in Docker, pgAdmin 4 is the great fit - you just need to add one service to your docker-compose.yml and everything runs together in the same network.

Setting Up the Environment with Docker Compose

The fastest way to get PostgreSQL and pgAdmin 4 running together is a single docker-compose.yml file. If you're new to the topic, our Docker Compose Guide covers the fundamentals. Here, I'll focus on the pgAdmin-specific configuration.

Here's the complete file you can copy-paste:

services:
  postgres:
    image: postgres:18
    container_name: postgres
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: mydb
    volumes:
      - postgres_data:/var/lib/postgresql
    networks:
      - pgnetwork

  pgadmin:
    image: dpage/pgadmin4:9.13
    container_name: pgadmin
    environment:
      PGADMIN_DEFAULT_EMAIL: you@yourdomain.com
      PGADMIN_DEFAULT_PASSWORD: password
      PGADMIN_LISTEN_PORT: 5050 
    ports:
      - "5050:5050"                
    volumes:
      - pgadmin_data:/var/lib/pgadmin
    depends_on:
      - postgres
    networks:
      - pgnetwork

volumes:
  postgres_data:
  pgadmin_data:

networks:
  pgnetwork:

The depends_on field tells Docker Compose to start the postgres container before pgadmin. Without it, pgAdmin might start before PostgreSQL is ready and fail to connect. It doesn't wait for PostgreSQL to be fully healthy - just for the container to start. It's still enough to avoid most race conditions.

pgAdmin 4 environment variables

Two environment variables are required:

  • PGADMIN_DEFAULT_EMAIL - the email address you'll use to log into the pgAdmin web interface
  • PGADMIN_DEFAULT_PASSWORD - the password for that account

A third one is optional but you should specify it:

  • PGADMIN_LISTEN_PORT - the port pgAdmin listens on inside the container. It defaults to 80, but setting it to 5050 keeps things cleaner when you're mapping ports.

That said, hardcoding credentials in the Compose file is a bad idea, especially if the file ends up in version control. Move them to a .env file instead.

Create a .env file in the same directory as your docker-compose.yml:

POSTGRES_USER=admin
POSTGRES_PASSWORD=secret
POSTGRES_DB=mydb
PGADMIN_DEFAULT_EMAIL=admin@example.com
PGADMIN_DEFAULT_PASSWORD=secret

Then reference the variables in your Compose file:

# postgres
environment:
  POSTGRES_USER: ${POSTGRES_USER}
  POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
  POSTGRES_DB: ${POSTGRES_DB}
  
# pgadmin
environment:
  PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
  PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}

Docker Compose picks up .env files when you run the command, so there’s no extra configuration needed. Just remember to add  .env to your .gitignore and your credentials will stay out of the repo.

Volumes and data persistence

The volume mapped to /var/lib/pgadmin is where pgAdmin stores the data, such as session data, saved server connections, and configuration. Removing this from the compose file means you'll lose all of it every time the container restarts.

In the current compose file, you have a named volume that Docker manages on your host machine. The data persists container restarts, re-creations, and image updates - as long as you don't explicitly delete the volume with docker volume rm.

Starting the Stack and Accessing pgAdmin 4

With your docker-compose.yml ready, starting the stack takes one command:

docker compose up -d

The -d flag runs both containers in detached mode - they start in the background and your terminal stays free. To verify both containers are running:

docker ps

You should see both postgres and pgadmin listed with a status of Up.

Container status

Container status

If something looks off, check the pgAdmin logs:

docker logs pgadmin

A healthy startup looks like this:

pgAdmin startup logs

pgAdmin startup logs

If you see an error here, it’ll likely be one of these three:

  • Password authentication failed: your PGADMIN_DEFAULT_PASSWORD is missing or malformed in the .env file

  • Port is already allocated: something else is running on port 5050; change the host port in your Compose file

  • No such file or directory: the volume path is wrong or the container doesn't have permission to write to it

Once both containers are up and the logs look clean, open your browser and go to http://localhost:5050:

pgAdmin login page

pgAdmin login page

Log in with the email and password you set in PGADMIN_DEFAULT_EMAIL and PGADMIN_DEFAULT_PASSWORD. You'll land on the pgAdmin dashboard, ready to register your PostgreSQL server:

pgAdmin home page

pgAdmin home page

Connecting pgAdmin 4 to Your PostgreSQL Container

In the pgAdmin sidebar, right-click Servers - Register - Server. A dialog opens with two tabs you need to fill out: General and Connection.

The General tab

Give your server a meaningful name - something like local-dev-postgres. This is just a label inside pgAdmin, so pick anything that makes sense for your setup.

Server registration - General tab

Server registration - General tab

The Connection tab

Don't use localhost here. 

Inside a Docker network, localhost refers to the container itself - not your host machine, and not the PostgreSQL container. Docker has its own internal DNS, and it resolves container names using the service names defined in your docker-compose.yml. So if your PostgreSQL service is named postgres, that's the hostname you use.

Fill in the fields as follows:

  • Host name/address: postgres (the service name from docker-compose.yml)

  • Port: 5432

  • Maintenance database: the value of POSTGRES_DB from your Compose file (e.g., mydb)

  • Username: the value of POSTGRES_USER (e.g., admin)

  • Password: the value of POSTGRES_PASSWORD

Click Save

Server registration - Connection tab

Server registration - Connection tab

If everything is correct, the server will appear in the sidebar and you’ll be able to expand it and view your databases:

Successful server registration

Successful server registration

This means you’re connected.

Using the Query Tool

Since you’re now connected, I’ll show you the basics of pgAdmin 4 and Postgres in general.

Open the Query Tool by clicking Tools - Query Tool from the top menu. The interface has three panels:

  • Editor: where you write SQL
  • Data Output: where results appear after you run a query
  • Messages: where PostgreSQL sends status messages, errors, and execution info

Query tool

Query tool

Writing and running SQL

Let's create a simple orders table and add some data. You can run each block by hitting the Play button or by pressing F5 which is a shortcut.

Run this to create the table:

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_name VARCHAR(100) NOT NULL,
    product VARCHAR(100) NOT NULL,
    quantity INT NOT NULL,
    order_date DATE DEFAULT CURRENT_DATE
);

Insert a few rows:

INSERT INTO orders (customer_name, product, quantity)
VALUES
    ('Alice Johnson', 'Wireless Keyboard', 2),
    ('Bob Smith', 'USB-C Hub', 1),
    ('Carol White', 'Mechanical Keyboard', 3);

And now just query the data:

SELECT * FROM orders;

Querying data

Querying data

Results show up in the Data Output panel as a table. You can sort columns, resize them, and copy rows directly from the grid.

Reading the visual query plan

To see what happens behind the scenes when you run a query, run EXPLAIN ANALYZE on your SELECT statement:

EXPLAIN ANALYZE SELECT * FROM orders WHERE customer_name = 'Alice Johnson';

Explain Analyze results

Explain Analyze results

The Data Output panel shows the raw output. But pgAdmin has a better option. Click the Explain button in the toolbar - and pgAdmin renders the query plan as an interactive graph.

Query plan as a graph

Query plan as a graph

Now, it’s simple for this query, but you’ll get a lot more if you’re joining tables or performing more complex data aggregations.

This matters because reading raw EXPLAIN output is slow and error-prone. The visual plan makes it obvious when PostgreSQL is doing a full table scan on a large table, or when an index exists but isn't being used.

Managing Your Database Schema

pgAdmin's sidebar gives you a full view of your database structure - and lets you modify it through the GUI.

The sidebar tree goes: Servers - your server name - Databases - your database - Schemas - public - Tables. Expand any table and you'll see its Columns, Indexes, and Constraints listed as child nodes. Click any of them to inspect the details in the right panel.

Creating and modifying tables

To create a new table, right-click on Tables under your schema and select Create - Table. A dialog opens with a couple tabs.

Creating tables

Creating tables

The General tab is where you set the table name. Switch to the Columns tab to add your columns - each row lets you set the column name, data type, length, and whether it's nullable. The Constraints tab takes care of primary keys, foreign keys, and unique constraints.

To add an index to an existing table, expand the table in the sidebar, right-click Indexes, and select Create - Index. Pick the columns to index and choose the index type - btree is the default and works for most cases.

Creating an index

Creating an index

Backup and restore

To back up a database, go to Tools - Backup. You'll need to pick a format:

  • Custom: compressed, binary format; the most flexible option and the best choice for most cases since you can restore individual tables from it
  • Plain: a plain SQL script you can open and read in any text editor
  • Tar: an uncompressed archive; less common but useful for some restore workflows

After you select a format and a destination path, pgAdmin runs pg_dump in the background and saves the file to your local machine.

Creating a backup

Creating a backup

To restore, go to Tools - Restore, select your backup file, and point it at the target database.

Restoring from a backup

Restoring from a backup

If you’re wondering why this is useful, imagine you're testing a destructive migration on your dev database. Take a backup first, run the migration, and if something breaks, restore the backup to get back to a known state.

Best Practices for Running pgAdmin 4 in Docker

Getting pgAdmin 4 running is one thing. But keeping it running smoothly requires you to know a couple of extra things. Here are a few practical tips.

Keep credentials out of your Compose file

If your docker-compose.yml ends up in version control - and it usually does - hardcoded passwords go with it. Use a .env file for credentials and add it to .gitignore. For production environments, go a step further and use Docker secrets, which mount sensitive values as files rather than environment variables.

Never expose the pgAdmin port publicly

By default, Docker binds ports to 0.0.0.0, which means any network interface - including public ones. On a remote server, that makes your pgAdmin instance reachable from the internet. Bind explicitly to 127.0.0.1 instead:

ports:
  - "127.0.0.1:5050:5050"

This makes pgAdmin accessible only from the server itself. Use an SSH tunnel or a reverse proxy if you need remote access.

Pin your image tags

Using dpage/pgadmin4:latest will pull a new version the next time someone runs docker compose pull. That new version might behave differently, break your config, or introduce unexpected changes. Use a specific tag like dpage/pgadmin4:9.13 so every teammate runs the exact same version.

Pre-load server connections with servers.json

If your whole team shares the same Compose setup, don't make everyone register the PostgreSQL server after spinning up the stack. pgAdmin supports a servers.json file that pre-populates connections on startup. Mount it into the container like this:

volumes:
  - ./servers.json:/pgadmin4/servers.json

Here’s what a minimal servers.json looks like:

{
  "Servers": {
    "1": {
      "Name": "local-dev-postgres",
      "Group": "Servers",
      "Host": "postgres",
      "Port": 5432,
      "MaintenanceDB": "mydb",
      "Username": "admin",
      "SSLMode": "prefer"
    }
  }
}

The server will show up when pgAdmin starts - no manual setup required.

Conclusion

In this article, I walked you through setting up pgAdmin 4 in Docker from scratch. You wrote a Docker Compose file that brings up PostgreSQL and pgAdmin 4 together, connected the two containers using Docker's internal DNS, and used pgAdmin's core features - the Query Tool, schema browser, and backup/restore workflow.

The core principle here is reproducibility. 

A docker-compose.yml file, a servers.json, and a .env file are all you need to hand a teammate a fully configured database environment. This will make sure the “it works on my machine” problem never happens again.

To go deeper on Docker and containerization, check out our Intermediate Docker course. It’s packed with useful tips on multi-stage builds, networking, and a deep dive into Compose.


Dario Radečić's photo
Author
Dario Radečić
LinkedIn
Senior Data Scientist based in Croatia. Top Tech Writer with over 700 articles published, generating more than 10M views. Book Author of Machine Learning Automation with TPOT.

Docker pgAdmin FAQs

Can I run pgAdmin 4 in Docker on Windows and macOS?

Yes. The dpage/pgadmin4 image runs on any operating system that supports Docker, including Windows and macOS. The setup process and docker-compose.yml file are identical across platforms.

Do I need to reinstall pgAdmin 4 every time I update the Docker image?

No. Pulling a new image version doesn't affect your saved data as long as you've mapped /var/lib/pgadmin to a named volume. Your server connections, session data, and configuration survive image updates and container restarts.

Is it safe to use pgAdmin 4 in Docker for production databases?

pgAdmin 4 in Docker is fine for development and internal tooling, but you need to lock it down before pointing it at a production database. Never expose the pgAdmin port publicly, always use a .env file or Docker secrets for credentials, and consider putting pgAdmin behind a reverse proxy with authentication if you need remote access.

Why can't I use `localhost` as the hostname when connecting pgAdmin to PostgreSQL?

Inside a Docker network, localhost resolves to the container itself - not your host machine or any other container. Docker has its own internal DNS that resolves container names using the service names defined in your docker-compose.yml. Use the PostgreSQL service name - typically postgres - as the hostname instead.

What's the difference between the Custom, Plain, and Tar backup formats in pgAdmin?

Custom is a compressed binary format that gives you the most flexibility - you can restore individual tables from it rather than the entire database. Plain outputs a readable SQL script you can open in any text editor, which is handy for reviewing or editing before restoring. Tar is an uncompressed archive that's less common but supported by pg_restore for selective restores.

Topics

Learn Docker with DataCamp

Course

Introduction to Docker

4 hr
44.9K
Gain an introduction to Docker and discover its importance in the data professional’s toolkit. Learn about Docker containers, images, and more.
See DetailsRight Arrow
Start Course
See MoreRight Arrow
Related

Tutorial

PostgreSQL in Docker: A Step-by-Step Guide for Beginners

Your complete guide to running PostgreSQL in Docker—from setup to best practices—so you can enhance your development workflow without headaches.
Dario Radečić's photo

Dario Radečić

Tutorial

How to Install Docker Compose: Linux, macOS, and Windows

A practical guide to installing Docker Compose v2 on Linux, macOS, and Windows - covering both package manager and manual methods, verification steps, upgrades, and troubleshooting common errors.
Dario Radečić's photo

Dario Radečić

Tutorial

How to Use Homebrew to Install PostgreSQL on Mac

Learn how to set up PostgreSQL on macOS using Homebrew, a convenient package manager. Follow step-by-step instructions to install, configure, and start PostgreSQL services.
Oluseye Jeremiah's photo

Oluseye Jeremiah

Tutorial

How to Set Up and Configure MySQL in Docker

Learn how to set up and configure MySQL database inside Docker containers. The tutorial includes concepts such as connecting to MySQL servers, running MySQL clients to connect to containers, and so on.
Bex Tuychiev's photo

Bex Tuychiev

Tutorial

Docker Compose Guide: Simplify Multi-Container Development

Master Docker Compose for efficient multi-container application development. Learn best practices, scaling, orchestration, and real-world examples.
Derrick Mwiti's photo

Derrick Mwiti

Tutorial

Play with Docker: Run Containers For Free in Your Browser

Learn how to use Docker in your browser with Play with Docker. Run containers, build Dockerfiles, and use Docker Compose using this online Docker playground.
Benito Martin's photo

Benito Martin

See MoreSee More