Introduction#
In my videos about installing various services and applications on a home server, I often use external databases, mostly Postgres. On my Telegram channel someone once asked me why I don’t use a single, shared database for all the services that need one, since that’s more logical from a resource-efficiency standpoint, easier to manage, and much simpler to back up one database in one container instead of many. That’s true. But in my case the reason is pretty mundane. My audience has very different levels of preparation and knowledge. So I have to keep the material accessible, and as you can imagine, telling beginners in every single video “here I have an external database, here’s how we connect a container to it, go watch other videos about working with external databases” would rightfully be seen as annoying. So let’s finally start using our resources more sensibly and move all our services to a single PostgreSQL database, and while we’re at it, set up pgAdmin - a web interface for managing the database.
NB!!! I understand that using a PostgreSQL database at home is overkill, even excessive, but a lot of serious applications recommend it as their database of choice (Nextcloud, Authentik, Linkwarden, etc.). So why not?
Disclaimer To keep this simpler, in this article we’ll only install PostgreSQL and pgAdmin and connect them. Configuring third-party containers and hooking them up to a shared PostgreSQL database will be covered in a separate article (part 2).
What is PostgreSQL#
PostgreSQL is a powerful open-source object-relational database management system (DBMS). It stands out for its reliability, flexibility, and extensibility, which makes it one of the most popular DBMSes in the world.
History#
- The project started in 1986 at the University of California, Berkeley, under the name POSTGRES.
- In 1996 SQL support was added and the system got its modern name, PostgreSQL.
- Today it’s developed by a global community of contributors and is actively used both by startups and large corporations.
Key features of PostgreSQL#
Full SQL compliance
- Support for the SQL:2011 standard and many extensions.
- Rich syntax for complex queries.
Extensibility
- Ability to add your own data types, functions, and operators.
- Support for custom extensions, such as PostGIS for geospatial data.
Reliability and fault tolerance
- Write-ahead log (WAL) to protect against data loss.
- Support for replication and clustering.
Performance
- Query optimization via indexes (B-tree, GiST, GIN, etc.).
- Support for parallel query execution.
Security
- Strong access control system.
- Encrypted connections (SSL/TLS).
JSON support
- Ability to work with both relational and document-oriented data.
Where PostgreSQL is used#
- Web applications - backends built on Django, Ruby on Rails, Laravel, Spring Boot.
- Analytics systems - BI platforms, reporting.
- Geographic information systems - via the PostGIS extension.
- Financial and banking systems - thanks to its reliability and transactional guarantees.
PostgreSQL in the development ecosystem#
PostgreSQL runs on:
- Windows, Linux, macOS, and BSD.
- Cloud services (AWS RDS, Google Cloud SQL, Azure Database for PostgreSQL).
- Docker containers.
Advantages of PostgreSQL#
- Free and open source.
- The community actively releases updates and fixes.
- Suitable both for small projects and for high-load systems.
When to choose PostgreSQL#
- When you need a reliable, scalable DBMS.
- When SQL compatibility and extensibility matter.
- When the project needs to work with large volumes of data and complex analytical queries.
- When you need hybrid storage - relational and JSON data in the same database.
What is pgAdmin#
pgAdmin is the official and most popular PostgreSQL administration tool with a graphical web interface. It lets you work with PostgreSQL without constantly using the command line, which is especially convenient for administrators, developers, and data analysts.
History and purpose#
pgAdmin was created as an open-source project to simplify PostgreSQL management. Over the years it has grown into a powerful, full-featured tool that supports both local and remote database administration.
Its main goal is to provide a convenient way to:
- Create, edit, and delete databases, tables, and functions.
- Run SQL queries.
- Monitor PostgreSQL’s status and performance.
- Configure users, permissions, and roles.
Key pgAdmin features#
Visual administration interface
- Create and manage schemas, tables, indexes, and views.
- Easily configure relationships between tables.
SQL editor
- Syntax highlighting.
- SQL autocompletion.
- Query history.
Monitoring and diagnostics
- View active connections.
- Analyze query execution (
EXPLAIN,EXPLAIN ANALYZE). - Charts of load and resource usage.
User and security management
- Create and configure roles.
- Manage access permissions.
- Manage security policies.
Support for connecting to remote servers
- Manage multiple PostgreSQL servers from a single interface.
- Works with both local and cloud infrastructure.
pgAdmin architecture#
pgAdmin is a web application that can run:
Locally - on your own computer.
In server mode - accessible via browser from anywhere.
In a Docker container - for quick deployment without installing dependencies.
Main components:
Backend - written in Python (Flask), handles request processing and interaction with PostgreSQL.
Frontend - written in JavaScript (React), powers the web interface.
Database storage - stores pgAdmin’s settings, the list of servers, and user sessions.
Why it’s convenient to run pgAdmin in Docker#
Fast startup without a complicated install.
Easy version upgrades (just change the image tag).
Environment isolation - doesn’t clutter the host system.
Can be integrated with PostgreSQL in a single
docker-compose.yml.
When to use pgAdmin#
When you need to administer PostgreSQL through a convenient web interface.
To visualize the database structure and make navigation easier.
For performance monitoring and query analysis.
If you have multiple PostgreSQL servers and want centralized management.
Why we’ll install it in Docker#
Docker Compose lets us deploy these services quickly and conveniently without installing them directly on the host system.
In this guide we’ll create a docker-compose.yml to run PostgreSQL and pgAdmin in separate containers. Yes, you could set both up with a single docker-compose file, but since we want to keep the database container isolated from all other containers, we’ll split the database and the admin app apart.
Requirements#
Before you start, make sure you have:
Ideally, the database shouldn’t just live in its own container, but also be moved off the working machine entirely - for example, hosted on a NAS. This not only protects us from host-related issues, but also lets applications and servers on other machines in the local network connect to it. On top of that, we can confidently wipe and rebuild working machines from scratch, just point them at the path to our database, and everything keeps working as if nothing happened.
Setting up the PostgreSQL project#
Let’s create a directory where we’ll place our database
mkdir postgres
cd postgres
sudo touch docker-compose.ymlNow let’s create a simple docker-compose file for the database
I took all the variables from Docker Hub
services:
postgres:
image: postgres:16 # pick whatever version you consider appropriate, but as of August 2025 serious applications still tend to use version 16
container_name: postgres
restart: always
# set shared memory limit when using docker compose
#shm_size: 128mb
# or set shared memory limit when deploy via swarm stack
#volumes:
# - type: tmpfs
# target: /dev/shm
# tmpfs:
# size: 134217728 # 128*2^20 bytes = 128Mb
environment: # set the minimum required variables
- POSTGRES_PASSWORD=password
- POSTGRES_USER=stilicho
- POSTGRES_DB=postgres
ports: # if all your database-consuming containers will be on the same docker network, you can comment out the ports. Containers will talk to each other by container name inside docker
- 5432:5432
volumes:
- /home/stilicho/docker/postgres/pgdata:/var/lib/postgresql/data # path on the host where the database will be stored
networks: # specify the docker network the database will run on. All containers on the same docker network can communicate by container name
database:
networks:
database:
external: trueCreate a new docker network with the command
docker network create databaseNow let’s start our project with docker compose up -d.
Once the container has been pulled and started, you’ll see a new pgdata folder appear at the path specified in the docker compose file.
If you try to open it, you won’t see any information. That’s normal - it’s because the postgres user has its own permissions that the user you’re currently working as doesn’t have. So if you just want to check that everything’s fine and that there’s something inside the pgdata folder, use sudo cd pgdata && sudo ls. Once you see that files and directories have appeared in the pgdata folder, don’t touch anything there - we’ve just confirmed everything is working.
Setting up the pgAdmin project#
Let’s create a directory where we’ll place our database
mkdir pgadmin
cd pgadmin
sudo touch docker-compose.ymlNow let’s create a simple docker-compose file for pgAdmin
I took all the variables from Docker Hub and from the developer’s own site for that specific version of the app
services:
pgadmin:
image: dpage/pgadmin4:9.6.0 # the latest version of the app as of when this article was written
container_name: pgadmin
restart: always
environment: # the minimum variables required to start the container
- PGADMIN_DEFAULT_EMAIL=user@domain.com
- PGADMIN_DEFAULT_PASSWORD=SuperSecret
volumes:
- /home/stilicho/docker/pgadmin/data:/var/lib/pgadmin # path to the folder where all the app's data will be stored
ports: # container ports. Consider whether you need to close these off if you're using a reverse proxy. For the purposes of this article I'm leaving them open.
- 8080:80
networks: # define the networks pgAdmin will run on.
- proxy # the network where my Traefik reverse proxy runs
- database # the network where our database runs
labels: # standard Traefik reverse-proxy labels for the pgAdmin container, so we can access the web panel via a subdomain over an SSL-secured connection
- "traefik.enable=true"
- "traefik.http.routers.pgadmin.entrypoints=http"
- "traefik.http.routers.pgadmin.rule=Host(`pgadmin.your_domain.ru`)"
- "traefik.http.middlewares.pgadmin-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.pgadmin.middlewares=pgadmin-https-redirect"
- "traefik.http.routers.pgadmin-secure.entrypoints=https"
- "traefik.http.routers.pgadmin-secure.rule=Host(`pgadmin.your_domain.ru`)"
- "traefik.http.routers.pgadmin-secure.tls=true"
- "traefik.http.routers.pgadmin-secure.service=pgadmin"
- "traefik.http.services.pgadmin.loadbalancer.server.port=80"
- "traefik.docker.network=proxy"
networks:
database:
external: true
proxy:
external: trueBut before starting the container, we need to manually create the directory where pgAdmin’s data will live and set the correct permissions on it. This is a mandatory step.
Set the permissions with a simple command
sudo chown -R 5050:5050 <host_directory>` # userid and groupid taken from the official documentation.Now we can start the pgAdmin docker compose file
docker compose up -dThe container will download and start fairly quickly.
Now, depending on how you’re running your container, you can access it at your_ip_address:8080, or, in my case, at the subdomain pgadmin.your_domain.ru
We land on the welcome screen

Enter the login and password we set in the docker compose file
We land in pgAdmin’s standard welcome screen

Since this article has already gotten quite long, let’s wrap up the initial setup with two mandatory things.
Let’s enable dark mode
Go to Files > Preferences > Miscellaneous > User Interface and select the dark theme.

Now that the visuals are sorted, let’s connect to our database
Right-click on the servers section in the pgAdmin browser. Choose register, then click Server.
In the window that appears, on the General tab, give your server a name

Go to the Connection tab and enter the address where our database is reachable. If it’s on the same docker network, the container name alone will be enough - docker handles the rest of the magic for you.
In the login field your login is already filled in, taken from the values you specified in the docker compose file, and in the password field you need to enter the database password specified in the database’s docker compose file

You can toggle the “save password” switch so you don’t have to enter it every time.
Now, if everything’s in order, you’ll see our Postgres database show up under the server section

We now have full access to our database and are ready to deploy the services that will use the shared database. For how to properly create a separate user and database for a specific application and connect it to the shared PostgreSQL, see part two.
If you enjoyed this article and found it useful, you can become a sponsor on Boosty via the link in the contacts.




