Docker Container
Create an integration.json file and mount it as a volume:
[
{
"service": "postgresql",
"monitor": true,
"host": "127.0.0.1",
"port": "5432",
"username": "watchlog_monitor",
"password": "your_password",
"database": ["db1", "db2"]
},
{
"service": "postgresql",
"monitor": true,
"host": "127.0.0.1",
"port": "5433",
"username": "watchlog_monitor",
"password": "your_password",
"database": ["db3"]
}
]
Then run the container:
docker run -d \
--name watchlog-agent \
--network host \
-v /path/to/integration.json:/app/app/config/integration.json \
-e WATCHLOG_APIKEY="YOUR_APIKEY" \
-e WATCHLOG_SERVER="https://log.watchlog.io" \
watchlog/agent:latest
Reaching PostgreSQL from the container
| PostgreSQL runs… | Use |
|---|---|
On the same host, agent on --network host | 127.0.0.1 |
| On the same host, agent on a bridge network | host.docker.internal (Docker Desktop) or the host's LAN IP |
| In another container on a shared user-defined network | The container or service name, e.g. postgres |
| On a remote host | Its hostname or IP |
pg_hba.conf
From PostgreSQL's perspective the agent connects from the Docker bridge network, not from localhost. A pg_hba.conf line scoped to 127.0.0.1/32 will reject it. Add the bridge subnet:
host all watchlog_monitor 172.16.0.0/12 scram-sha-256
If the agent and PostgreSQL share a Docker network:
docker run -d \
--name watchlog-agent \
--network app-net \
-v /path/to/integration.json:/app/app/config/integration.json \
-e WATCHLOG_APIKEY="YOUR_APIKEY" \
-e WATCHLOG_SERVER="https://log.watchlog.io" \
watchlog/agent:latest
{
"service": "postgresql",
"monitor": true,
"host": "postgres",
"port": "5432",
"username": "watchlog_monitor",
"password": "your_password",
"database": ["myapp"]
}
Creating the monitoring role
docker exec -i postgres psql -U postgres <<'SQL'
CREATE USER watchlog_monitor WITH PASSWORD 'your_password';
GRANT pg_monitor TO watchlog_monitor;
GRANT CONNECT ON DATABASE myapp TO watchlog_monitor;
SQL
Tips
docker exec needs -i to attach stdin. Without it the heredoc is a silent no-op — the command appears to succeed and creates nothing.
pg_stat_statements in a container
The official postgres image ships the extension but does not preload it. Watchlog will never install it for you. Start the container with the setting:
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=secret \
-p 5432:5432 \
postgres:16 \
-c shared_preload_libraries=pg_stat_statements \
-c pg_stat_statements.track=top
Then create it once per database:
docker exec -i postgres psql -U postgres -d myapp -c \
"CREATE EXTENSION IF NOT EXISTS pg_stat_statements;"
Docker Compose
services:
postgres:
image: postgres:16
command:
- -c
- shared_preload_libraries=pg_stat_statements
- -c
- pg_stat_statements.track=top
environment:
POSTGRES_PASSWORD: secret
networks:
- app-net
watchlog-agent:
image: watchlog/agent:latest
container_name: watchlog-agent
restart: unless-stopped
environment:
WATCHLOG_APIKEY: "YOUR_APIKEY"
WATCHLOG_SERVER: "https://log.watchlog.io"
volumes:
- ./integration.json:/app/app/config/integration.json:ro
networks:
- app-net
networks:
app-net:
Multiple PostgreSQL Instances
You can monitor multiple PostgreSQL databases by adding multiple entries with the same service name. Each instance is automatically identified by its host:port combination.
Monitoring both sides of a replication pair is worth doing: a replica reports its own replay position and lag, which the primary cannot tell you.
