Docker has become increasingly useful for database administrators for development, testing, proof-of-concept environments, automation, and database tooling. This guide covers practical Docker administration commands with a DBA focus, particularly for PostgreSQL containers.
Throughout this guide, CONTAINER_ID stands for your actual container ID or container name. Substitute it in every command.
1. Basic concepts
| Docker object | Description |
|---|---|
| Image | Read-only template used to create containers |
| Container | Running or stopped instance created from an image |
| Volume | Persistent storage managed by Docker |
| Network | Communication between containers and the outside |
| Dockerfile | File used to build an image |
| Compose | Tool to define and manage multiple containers |
| Registry | Repository where images are stored |
For a DBA the chain that matters is:
PostgreSQL container
|
+-- PostgreSQL process
|
+-- /var/lib/postgresql/data
| |
| +-- Docker volume
|
+-- Port 5432
|
+-- Container logs
2. Verify Docker version
docker version
Shorter output:
docker --version
Engine and host details:
docker info
Use docker info when investigating the storage driver, Docker root directory, container runtime, logging configuration, and available CPU and memory.
3. List containers
Running containers:
docker ps
Sample output:
CONTAINER ID IMAGE COMMAND STATUS efca1e07d460 postgres:13 "docker-entrypoint..." Up 2 hours
All containers including stopped ones:
docker ps -a
This is one of the most useful DBA commands, because a database container may have stopped due to startup failure, configuration errors, permission problems, disk space, out-of-memory conditions, wrong environment variables, or failed initialization.
Container IDs only:
docker ps -aq
4. Verify container status
Filter for one container:
docker ps -a --filter id=CONTAINER_ID
Example:
docker ps -a --filter id=efca1e07d460
Full detail:
docker inspect CONTAINER_ID
docker inspect returns container state, IP address, port mappings, mounted volumes, environment variables, restart policy, network configuration, startup command and resource limits.
Just the IP address:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' CONTAINER_ID
5. Container logs
Logs are the first place to look when a database container misbehaves.
docker logs CONTAINER_ID
Example:
docker logs efca1e07d460
For a PostgreSQL container you may see:
database system is ready to accept connections
or:
FATAL: role "root" does not exist
The second message does not mean PostgreSQL is down. It means something tried to connect using the OS user root, and no PostgreSQL role called root exists. Connect as the correct database user instead:
docker exec -it CONTAINER_ID psql -U postgres
6. Recent log lines
docker logs --tail 100 CONTAINER_ID
Example:
docker logs --tail 200 efca1e07d460
Useful for recent startup failures, connection or authentication errors, crash and restart events, and extension failures.
7. Follow logs in real time
docker logs --follow CONTAINER_ID
or:
docker logs -f CONTAINER_ID
Useful while restarting the database, testing application connections, reproducing a problem, or watching initialization scripts run.
Press Ctrl+C to stop following. This stops the log display only — it does not stop the container.
8. Log timestamps
docker logs -t CONTAINER_ID
or:
docker logs --timestamps CONTAINER_ID
Timestamps let you correlate Docker events with PostgreSQL logs, application logs, monitoring alerts and OS events. Combine with --tail:
docker logs --timestamps --tail 100 CONTAINER_ID
9. Logs from a specific time
Last hour:
docker logs --since 1h CONTAINER_ID
Last 30 minutes:
docker logs --since 30m CONTAINER_ID
After a specific timestamp:
docker logs --since "2026-08-16T10:00:00" CONTAINER_ID
Combined with follow:
docker logs --since 10m -f CONTAINER_ID
During an incident this avoids scanning the entire log history.
10. Check container processes
docker top CONTAINER_ID
For a PostgreSQL container you should see the expected background processes:
postgres postgres: checkpointer postgres: background writer postgres: walwriter postgres: autovacuum launcher postgres: logical replication launcher
If these are absent, the container is up but the database is not.
11. Execute a command inside a container
docker exec CONTAINER_ID COMMAND
Example:
docker exec efca1e07d460 ps -ef
Interactive shell:
docker exec -it CONTAINER_ID bash
If bash is not present in the image:
docker exec -it CONTAINER_ID sh
Once inside, the usual checks apply:
ps -ef df -h free -m ls -ltr /var/lib/postgresql/data
12. Connect to PostgreSQL inside the container
docker exec -it CONTAINER_ID psql -U postgres
Specific database:
docker exec -it CONTAINER_ID psql -U postgres -d postgres
Single query without an interactive session:
docker exec -it CONTAINER_ID psql -U postgres -d postgres -c "SELECT version();"
Example:
docker exec -it efca1e07d460 psql -U postgres -c "SELECT version();"
13. Check database readiness
docker exec CONTAINER_ID pg_isready
Expected output:
/var/run/postgresql:5432 - accepting connections
With explicit host and port:
docker exec CONTAINER_ID pg_isready -h localhost -p 5432
This is the simplest health check for a PostgreSQL container.
14. Check database version
docker exec CONTAINER_ID psql -U postgres -c "SELECT version();"
or:
docker exec CONTAINER_ID psql -U postgres -c "SHOW server_version;"
Worth confirming after deployment, image upgrade, patch testing, migration, restore, or an environment refresh.
15. Start a stopped container
docker start CONTAINER_ID
Start and attach to output:
docker start -a CONTAINER_ID
A useful sequence after starting a database container:
docker start CONTAINER_ID docker ps docker logs --tail 100 CONTAINER_ID
16. Stop a running container
docker stop CONTAINER_ID
Docker sends a termination signal to the main process and waits for the configured timeout before forcing termination. Prefer docker stop over docker kill for databases — graceful shutdown lets the database complete its normal shutdown processing.
17. Restart a database container
docker restart CONTAINER_ID
Then validate, in order:
docker ps docker logs --tail 100 CONTAINER_ID docker exec CONTAINER_ID pg_isready docker exec CONTAINER_ID psql -U postgres -c "SELECT now();"
18. Force stop a container
docker kill CONTAINER_ID
This terminates the container process immediately. Avoid it for databases unless the container is completely unresponsive, graceful shutdown has already failed, or emergency recovery requires it.
19. Container resource usage
docker stats
For one container:
docker stats CONTAINER_ID
Shows CPU percentage, memory usage against limit, network I/O, block I/O and process count. Useful when investigating high database CPU, memory pressure, OOM-related restarts, or heavy disk I/O.
For a single non-streaming sample:
docker stats --no-stream CONTAINER_ID
20. Container storage usage
docker system df
More detail:
docker system df -v
Identifies unused images, stopped containers, unused volumes and reclaimable storage.
21. Verify database volumes
docker volume ls
Inspect one:
docker volume inspect postgres_data
A PostgreSQL volume is typically mounted at /var/lib/postgresql/data.
Container = disposable. Database data = persistent.
If PostgreSQL data exists only in the writable container layer, removing the container destroys the database.
22. Verify container mounts
docker inspect -f '{{json .Mounts}}' CONTAINER_ID
Confirm that /var/lib/postgresql/data is backed by persistent storage before running docker rm or docker system prune.
23. Check network configuration
docker network ls
Inspect a network:
docker network inspect NETWORK_NAME
For database troubleshooting, verify the container IP, network name, port mappings, application-to-database connectivity, DNS resolution and network isolation.
24. Check port mapping
docker port CONTAINER_ID
Example output:
5432/tcp -> 0.0.0.0:5432
The host port does not have to match the container port. A mapping of 15432:5432 means:
Docker host port 15432
|
v
container port 5432
|
v
PostgreSQL
25. Check environment variables
docker inspect -f '{{range .Config.Env}}{{println .}}{{end}}' CONTAINER_ID
Common PostgreSQL variables:
POSTGRES_USER POSTGRES_PASSWORD POSTGRES_DB
26. Container restart policy
docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' CONTAINER_ID
Common policies:
no always unless-stopped on-failure
Change it:
docker update --restart unless-stopped CONTAINER_ID
A restart policy improves availability but is not database HA. Understand why a database container stopped before relying on automatic restart.
27. Identify why a container stopped
docker ps -a
docker inspect -f '{{.State.Status}}' CONTAINER_ID
docker inspect -f '{{.State.ExitCode}}' CONTAINER_ID
docker inspect -f '{{.State.Error}}' CONTAINER_ID
An exit code of 1 indicates the process terminated with an error. Always correlate the exit code with docker logs — the code alone rarely explains the root cause.
28. Troubleshooting flow for an unavailable database
Step 1 — Is the container running?
docker ps -a
Step 2 — What do recent logs show?
docker logs --tail 200 CONTAINER_ID
Step 3 — What is the container state?
docker inspect -f '{{.State.Status}} {{.State.ExitCode}} {{.State.Error}}' CONTAINER_ID
Step 4 — Resource consumption?
docker stats --no-stream CONTAINER_ID
Step 5 — Storage?
docker exec CONTAINER_ID df -h
Step 6 — Is the database process running?
docker top CONTAINER_ID
Step 7 — Is PostgreSQL ready?
docker exec CONTAINER_ID pg_isready
Step 8 — Does a query succeed?
docker exec -it CONTAINER_ID psql -U postgres -c "SELECT now();"
This gives a structured path instead of immediately restarting the container.
29. PostgreSQL log examples
Database ready:
database system is ready to accept connections
Role problem:
FATAL: role "root" does not exist
Check which roles exist:
docker exec -it CONTAINER_ID psql -U postgres -c "\du"
Port already in use — the container fails to start because the host port is taken. Check on the Docker host:
docker ps ss -lntp
Disk space — check both sides:
docker exec CONTAINER_ID df -h df -h
A database can fail even when the container looks healthy, if the underlying host filesystem is full.
30. Remove a container
docker rm CONTAINER_ID
Force removal:
docker rm -f CONTAINER_ID
Before removing a database container, verify: where the data is stored, whether it is in a Docker volume, whether a backup exists, whether the container is still needed, and whether another container uses the same volume.
Removing a container and removing its volume are separate operations, but careless cleanup still causes data loss.
31. Remove unused resources
docker system prune
Review what will be removed first:
docker system df
Be especially careful with:
docker volume prune
Docker volumes may contain database data. On production database hosts, avoid blanket cleanup commands unless they are part of an approved procedure.
32. Backup PostgreSQL from Docker
Plain SQL dump:
docker exec CONTAINER_ID pg_dump -U postgres -d mydatabase > mydatabase.sql
Custom format:
docker exec CONTAINER_ID pg_dump -U postgres -d mydatabase -Fc > mydatabase.dump
All databases:
docker exec CONTAINER_ID pg_dumpall -U postgres > all_databases.sql
Production backup procedures also need retention, encryption, off-host storage, validation, restore testing, defined RPO and RTO, and monitoring.
33. Restore PostgreSQL into a container
Plain SQL dump:
cat mydatabase.sql | docker exec -i CONTAINER_ID psql -U postgres -d mydatabase
Custom-format dump:
cat mydatabase.dump | docker exec -i CONTAINER_ID pg_restore -U postgres -d mydatabase
Note the -i flag rather than -it: input is piped, so there is no TTY.
Before a production restore, validate the target database and version, required extensions, available disk space, existing objects, role requirements and backup integrity.
34. Copy files between host and container
Host to container:
docker cp backup.sql CONTAINER_ID:/tmp/backup.sql
Container to host:
docker cp CONTAINER_ID:/tmp/backup.sql ./backup.sql
Example:
docker cp efca1e07d460:/var/log/postgresql/postgresql.log .
Do not manually copy database data files while PostgreSQL is running. Use pg_dump, pg_dumpall or pg_basebackup depending on the recovery requirement.
35. Docker images
docker images docker image ls
Pull an image:
docker pull postgres:16
Image details:
docker image inspect postgres:16
Remove an image:
docker image rm IMAGE_ID
After a database upgrade, do not immediately delete the previous image — it is useful for rollback planning, reproducing issues and version comparison. Balance retention against security and storage requirements.
36. Container naming
docker run --name postgres-dev \ -e POSTGRES_PASSWORD='ExamplePassword' \ -d postgres:16
Commands then become readable:
docker logs postgres-dev docker exec -it postgres-dev psql -U postgres docker stats postgres-dev
Meaningful names beat randomly generated container IDs.
37. DBA command cheat sheet
| Requirement | Command |
|---|---|
| List running containers | docker ps |
| List all containers | docker ps -a |
| Inspect container | docker inspect CONTAINER_ID |
| View logs | docker logs CONTAINER_ID |
| Last 100 log lines | docker logs --tail 100 CONTAINER_ID |
| Follow logs | docker logs -f CONTAINER_ID |
| Logs with timestamps | docker logs -t CONTAINER_ID |
| Logs from last hour | docker logs --since 1h CONTAINER_ID |
| Container processes | docker top CONTAINER_ID |
| Execute a command | docker exec CONTAINER_ID COMMAND |
| Open a shell | docker exec -it CONTAINER_ID bash |
| Start container | docker start CONTAINER_ID |
| Stop container | docker stop CONTAINER_ID |
| Restart container | docker restart CONTAINER_ID |
| Resource usage | docker stats CONTAINER_ID |
| List volumes | docker volume ls |
| Inspect volume | docker volume inspect VOLUME_NAME |
| List networks | docker network ls |
| Inspect network | docker network inspect NETWORK_NAME |
| Check port mapping | docker port CONTAINER_ID |
| Docker disk usage | docker system df |
| Copy files | docker cp SOURCE DESTINATION |
| Remove stopped container | docker rm CONTAINER_ID |
| List images | docker image ls |
38. Troubleshooting checklist
When a database inside Docker is reported down, check in order:
- Is the Docker service running?
- Is the database container running?
- Did the container recently restart?
- What is the container exit code?
- What do the latest logs show?
- Is the database process running?
- Is the database accepting connections?
- Is the expected port exposed?
- Is the Docker network working?
- Is the database volume mounted correctly?
- Is sufficient disk space available?
- Is the container hitting its memory limit?
- Is CPU usage unusually high?
- Are database credentials correct?
- Do the required roles exist?
- Are configuration files present?
- Is the database version correct?
- Are backups available and tested?
- Is the restart policy appropriate?
39. Best practices
- Keep database data outside the container layer. Use persistent volumes or external storage.
- Never treat a container as a backup. A container can be recreated; the data needs an independent backup strategy.
- Monitor the Docker host. CPU, memory, disk latency, disk capacity, network and the storage driver all affect database performance.
- Monitor container resources with
docker stats, and feed Docker metrics into your monitoring platform. - Avoid plain-text passwords in environment variables. Use approved secret management for production.
- Pin image versions. Use
postgres:16rather thanpostgres:latest, or a more specific tag where the environment requires it. - Test upgrades before production. An image upgrade can also be a database version upgrade — validate application compatibility, extensions, parameters, backup and restore, performance, and the rollback path.
- Do not manipulate database files directly from the host or container shell. Use database-native tools.
- Separate application and database concerns using Docker networks and clear service boundaries.
- Treat production database containers as infrastructure: monitoring, patching, backup, recovery, security, capacity planning, access control, HA, DR and change management all still apply.
40. Quick health check sequence
docker ps
docker inspect -f '{{.State.Status}} {{.State.ExitCode}}' CONTAINER_ID
docker logs --tail 50 CONTAINER_ID
docker stats --no-stream CONTAINER_ID
docker exec CONTAINER_ID df -h
docker exec CONTAINER_ID pg_isready
docker exec CONTAINER_ID psql -U postgres -c "SELECT version();"
docker exec CONTAINER_ID psql -U postgres -c "SELECT now();"
That walks the full stack:
container -> process -> resources -> storage -> PostgreSQL -> connectivity
Conclusion
Docker gives DBAs a lightweight, repeatable way to build database environments for development, testing, automation, migration rehearsal and proof-of-concept work. It does not remove any traditional DBA responsibility.
The commands that matter day to day:
docker ps docker inspect docker logs docker exec docker stats docker top docker start docker stop docker restart docker volume docker network docker cp
Combined with PostgreSQL-native tools — psql, pg_isready, pg_dump, pg_dumpall, pg_restore, pg_basebackup — that is a practical foundation for administering PostgreSQL containers.