@@ -4,9 +4,12 @@ services:
44image :alpine:3.22.0
55container_name :sources-generator
66working_dir :/app
7+ depends_on :
8+ -postgres-ai
79volumes :
8- -./instances.yml:/app/instances.yaml
9- -./config:/app/config
10+ -./instances.yml:/app/instances.yaml:rw
11+ -postgres_ai_configs:/app/config:rw
12+ -grafana_data:/var/lib/grafana:rw
1013command :>
1114 sh -c "
1215 mkdir -p /app/config/pgwatch-postgres /app/config/pgwatch-prometheus &&
@@ -15,7 +18,20 @@ services:
1518 echo '# PGWatch Sources Configuration - Prometheus Instance' > /app/config/pgwatch-prometheus/sources.yml &&
1619 echo '' >> /app/config/pgwatch-prometheus/sources.yml &&
1720 sed 's/~sink_type~/prometheus/g' /app/instances.yaml >> /app/config/pgwatch-prometheus/sources.yml &&
18- echo 'Generated sources.yml files for both postgres and prometheus'
21+ echo 'Generated sources.yml files for both postgres and prometheus' &&
22+ ls -la /app/config/pgwatch-postgres/ &&
23+ ls -la /app/config/pgwatch-prometheus/ &&
24+ echo 'Copying files to shared volume location...' &&
25+ mkdir -p /app/config/pgwatch &&
26+ cp /app/config/pgwatch-postgres/sources.yml /app/config/pgwatch/ &&
27+ cp /app/config/pgwatch-postgres/metrics.yml /app/config/pgwatch/ &&
28+ echo 'Files copied to shared volume:' &&
29+ ls -la /app/config/pgwatch/ &&
30+ echo 'Copying Grafana dashboards...' &&
31+ cp /app/config/grafana/dashboards/*.json /var/lib/grafana/dashboards/ &&
32+ echo 'Grafana dashboards copied to shared volume:' &&
33+ ls -la /var/lib/grafana/dashboards/ &&
34+ tail -f /dev/null
1935 "
2036
2137# Target Database - The PostgreSQL database being monitored
@@ -26,12 +42,65 @@ services:
2642POSTGRES_DB :target_database
2743POSTGRES_USER :postgres
2844POSTGRES_PASSWORD :postgres
29- command :["postgres", "-c", "shared_preload_libraries=pg_stat_statements", "-c", "pg_stat_statements.track=all"]
3045ports :
3146 -" 55432:5432"
47+ depends_on :
48+ -postgres-ai
3249volumes :
3350 -target_db_data:/var/lib/postgresql/data
34- -./config/target-db/init.sql:/docker-entrypoint-initdb.d/init.sql
51+ command :>
52+ sh -c "
53+ echo '-- Initialize target database for monitoring' > /docker-entrypoint-initdb.d/init.sql &&
54+ echo '-- Enable pg_stat_statements extension for query monitoring' >> /docker-entrypoint-initdb.d/init.sql &&
55+ echo 'CREATE EXTENSION IF NOT EXISTS pg_stat_statements;' >> /docker-entrypoint-initdb.d/init.sql &&
56+ echo '' >> /docker-entrypoint-initdb.d/init.sql &&
57+ echo '-- Create a sample table for demonstration' >> /docker-entrypoint-initdb.d/init.sql &&
58+ echo 'CREATE TABLE IF NOT EXISTS sample_data (' >> /docker-entrypoint-initdb.d/init.sql &&
59+ echo ' id SERIAL PRIMARY KEY,' >> /docker-entrypoint-initdb.d/init.sql &&
60+ echo ' name VARCHAR(100),' >> /docker-entrypoint-initdb.d/init.sql &&
61+ echo ' created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP' >> /docker-entrypoint-initdb.d/init.sql &&
62+ echo ');' >> /docker-entrypoint-initdb.d/init.sql &&
63+ echo '' >> /docker-entrypoint-initdb.d/init.sql &&
64+ echo '-- Insert some sample data' >> /docker-entrypoint-initdb.d/init.sql &&
65+ echo 'INSERT INTO sample_data (name) VALUES' >> /docker-entrypoint-initdb.d/init.sql &&
66+ echo ' (''Sample Record 1''),' >> /docker-entrypoint-initdb.d/init.sql &&
67+ echo ' (''Sample Record 2''),' >> /docker-entrypoint-initdb.d/init.sql &&
68+ echo ' (''Sample Record 3'');' >> /docker-entrypoint-initdb.d/init.sql &&
69+ echo '' >> /docker-entrypoint-initdb.d/init.sql &&
70+ echo '-- Create a user for PGWatch monitoring' >> /docker-entrypoint-initdb.d/init.sql &&
71+ echo 'CREATE USER monitor WITH PASSWORD ''monitor_pass'';' >> /docker-entrypoint-initdb.d/init.sql &&
72+ echo 'GRANT CONNECT ON DATABASE target_database TO monitor;' >> /docker-entrypoint-initdb.d/init.sql &&
73+ echo 'GRANT USAGE ON SCHEMA public TO monitor;' >> /docker-entrypoint-initdb.d/init.sql &&
74+ echo '' >> /docker-entrypoint-initdb.d/init.sql &&
75+ echo '-- Create a public view for pg_statistic access' >> /docker-entrypoint-initdb.d/init.sql &&
76+ echo 'CREATE OR REPLACE VIEW public.pg_statistic AS' >> /docker-entrypoint-initdb.d/init.sql &&
77+ echo 'SELECT' >> /docker-entrypoint-initdb.d/init.sql &&
78+ echo ' n.nspname as schemaname,' >> /docker-entrypoint-initdb.d/init.sql &&
79+ echo ' c.relname as tablename,' >> /docker-entrypoint-initdb.d/init.sql &&
80+ echo ' a.attname,' >> /docker-entrypoint-initdb.d/init.sql &&
81+ echo ' s.stanullfrac as null_frac,' >> /docker-entrypoint-initdb.d/init.sql &&
82+ echo ' s.stawidth as avg_width,' >> /docker-entrypoint-initdb.d/init.sql &&
83+ echo ' false as inherited' >> /docker-entrypoint-initdb.d/init.sql &&
84+ echo 'FROM pg_statistic s' >> /docker-entrypoint-initdb.d/init.sql &&
85+ echo 'JOIN pg_class c ON c.oid = s.starelid' >> /docker-entrypoint-initdb.d/init.sql &&
86+ echo 'JOIN pg_namespace n ON n.oid = c.relnamespace' >> /docker-entrypoint-initdb.d/init.sql &&
87+ echo 'JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum' >> /docker-entrypoint-initdb.d/init.sql &&
88+ echo 'WHERE a.attnum > 0 AND NOT a.attisdropped;' >> /docker-entrypoint-initdb.d/init.sql &&
89+ echo '' >> /docker-entrypoint-initdb.d/init.sql &&
90+ echo '-- Grant specific access instead of all tables' >> /docker-entrypoint-initdb.d/init.sql &&
91+ echo 'GRANT SELECT ON public.pg_statistic TO pg_monitor;' >> /docker-entrypoint-initdb.d/init.sql &&
92+ echo '' >> /docker-entrypoint-initdb.d/init.sql &&
93+ echo '-- Grant access to monitoring views' >> /docker-entrypoint-initdb.d/init.sql &&
94+ echo 'GRANT SELECT ON pg_stat_statements TO monitor;' >> /docker-entrypoint-initdb.d/init.sql &&
95+ echo 'GRANT SELECT ON pg_stat_database TO monitor;' >> /docker-entrypoint-initdb.d/init.sql &&
96+ echo 'GRANT SELECT ON pg_stat_user_tables TO monitor;' >> /docker-entrypoint-initdb.d/init.sql &&
97+ echo '-- Grant pg_monitor role to monitor user for enhanced monitoring capabilities' >> /docker-entrypoint-initdb.d/init.sql &&
98+ echo 'GRANT pg_monitor TO monitor;' >> /docker-entrypoint-initdb.d/init.sql &&
99+ echo '' >> /docker-entrypoint-initdb.d/init.sql &&
100+ echo '-- Set search path for the monitor user' >> /docker-entrypoint-initdb.d/init.sql &&
101+ echo 'ALTER USER monitor SET search_path = \"$$user\", public, pg_catalog;' >> /docker-entrypoint-initdb.d/init.sql &&
102+ exec postgres -c shared_preload_libraries=pg_stat_statements -c pg_stat_statements.track=all
103+ "
35104
36105# Postgres Sink - Storage for metrics in PostgreSQL format
37106sink-postgres :
@@ -41,23 +110,52 @@ services:
41110POSTGRES_DB :postgres
42111POSTGRES_USER :postgres
43112POSTGRES_PASSWORD :postgres
113+ depends_on :
114+ -postgres-ai
44115ports :
45116 -" 55433:5432"
46117volumes :
47118 -sink_postgres_data:/var/lib/postgresql/data
48- -./config/sink-postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
119+ command :>
120+ sh -c "
121+ echo '-- Initialize PostgreSQL sink database for storing pgwatch measurements' > /docker-entrypoint-initdb.d/init.sql &&
122+ echo '-- This database will store all the monitoring metrics collected by PGWatch' >> /docker-entrypoint-initdb.d/init.sql &&
123+ echo '-- Based on https://pgwat.ch/latest/howto/metrics_db_bootstrap.html' >> /docker-entrypoint-initdb.d/init.sql &&
124+ echo '' >> /docker-entrypoint-initdb.d/init.sql &&
125+ echo '-- Create the pgwatch role for measurements database' >> /docker-entrypoint-initdb.d/init.sql &&
126+ echo 'CREATE ROLE pgwatch WITH LOGIN PASSWORD ''pgwatchadmin'';' >> /docker-entrypoint-initdb.d/init.sql &&
127+ echo '' >> /docker-entrypoint-initdb.d/init.sql &&
128+ echo '-- Create the measurements database owned by pgwatch' >> /docker-entrypoint-initdb.d/init.sql &&
129+ echo 'CREATE DATABASE measurements OWNER pgwatch;' >> /docker-entrypoint-initdb.d/init.sql &&
130+ echo '' >> /docker-entrypoint-initdb.d/init.sql &&
131+ echo '-- Switch to the measurements database context' >> /docker-entrypoint-initdb.d/init.sql &&
132+ echo '\\c measurements;' >> /docker-entrypoint-initdb.d/init.sql &&
133+ echo '' >> /docker-entrypoint-initdb.d/init.sql &&
134+ echo '-- Create extensions that might be useful for metrics storage' >> /docker-entrypoint-initdb.d/init.sql &&
135+ echo 'CREATE EXTENSION IF NOT EXISTS btree_gist;' >> /docker-entrypoint-initdb.d/init.sql &&
136+ echo 'CREATE EXTENSION IF NOT EXISTS pg_stat_statements;' >> /docker-entrypoint-initdb.d/init.sql &&
137+ echo '' >> /docker-entrypoint-initdb.d/init.sql &&
138+ echo '-- Grant necessary permissions to pgwatch user' >> /docker-entrypoint-initdb.d/init.sql &&
139+ echo 'GRANT ALL PRIVILEGES ON DATABASE measurements TO pgwatch;' >> /docker-entrypoint-initdb.d/init.sql &&
140+ echo 'GRANT ALL PRIVILEGES ON SCHEMA public TO pgwatch;' >> /docker-entrypoint-initdb.d/init.sql &&
141+ echo '' >> /docker-entrypoint-initdb.d/init.sql &&
142+ echo '-- pgwatch will automatically create the admin and subpartitions schemas' >> /docker-entrypoint-initdb.d/init.sql &&
143+ echo '-- and all necessary tables when it starts up' >> /docker-entrypoint-initdb.d/init.sql &&
144+ "
49145
50146# Prometheus Sink - Storage for metrics in Prometheus format
51147sink-prometheus :
52148image :prom/prometheus:v3.4.2
53149container_name :sink-prometheus
150+ depends_on :
151+ -postgres-ai
54152ports :
55153 -" 59090:9090"
56154volumes :
57- -. /config/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
155+ -postgres_ai_configs: /config:ro
58156 -prometheus_data:/prometheus
59157command :
60- -' --config.file=/etc /prometheus/prometheus.yml'
158+ -' --config.file=/config /prometheus/prometheus.yml'
61159 -' --storage.tsdb.path=/prometheus'
62160 -' --web.console.libraries=/etc/prometheus/console_libraries'
63161 -' --web.console.templates=/etc/prometheus/consoles'
@@ -68,30 +166,30 @@ services:
68166pgwatch-postgres :
69167image :cybertecpostgresql/pgwatch:3
70168container_name :pgwatch-postgres
71- command :["--sources=/etc /pgwatch/sources.yml", "--metrics=/etc /pgwatch/metrics.yml", "--sink=postgresql://pgwatch:pgwatchadmin@sink-postgres:5432/measurements", "--web-addr=:8080"]
169+ command :["--sources=/config /pgwatch-postgres /sources.yml", "--metrics=/config /pgwatch-postgres /metrics.yml", "--sink=postgresql://pgwatch:pgwatchadmin@sink-postgres:5432/measurements", "--web-addr=:8080"]
72170ports :
73171 -" 58080:8080"
74172depends_on :
173+ -postgres-ai
75174 -sources-generator
76175 -sink-postgres
77176volumes :
78- -./config/pgwatch-postgres/sources.yml:/etc/pgwatch/sources.yml
79- -./config/pgwatch-postgres/metrics.yml:/etc/pgwatch/metrics.yml
177+ -postgres_ai_configs:/config:rw
80178
81179# PGWatch Instance 2 - Monitoring service (Prometheus sink)
82180pgwatch-prometheus :
83181image :cybertecpostgresql/pgwatch:3
84182container_name :pgwatch-prometheus
85- command :["--sources=/etc /pgwatch/sources.yml", "--metrics=/etc /pgwatch/metrics.yml", "--sink=prometheus://0.0.0.0:9091/pgwatch", "--web-addr=:8089"]
183+ command :["--sources=/config /pgwatch-prometheus /sources.yml", "--metrics=/config /pgwatch-prometheus /metrics.yml", "--sink=prometheus://0.0.0.0:9091/pgwatch", "--web-addr=:8089"]
86184ports :
87185 -" 58089:8089"
88186 -" 59091:9091"
89187depends_on :
188+ -postgres-ai
90189 -sources-generator
91190 -sink-prometheus
92191volumes :
93- -./config/pgwatch-prometheus/sources.yml:/etc/pgwatch/sources.yml
94- -./config/pgwatch-prometheus/metrics.yml:/etc/pgwatch/metrics.yml
192+ -postgres_ai_configs:/config:rw
95193
96194# Grafana with datasources - Visualization layer
97195grafana :
@@ -101,16 +199,19 @@ services:
101199GF_SECURITY_ADMIN_USER :demo
102200GF_SECURITY_ADMIN_PASSWORD :demo
103201GF_INSTALL_PLUGINS :yesoreyeram-infinity-datasource
202+ GF_PATHS_PROVISIONING :/config/grafana/provisioning
203+ GF_PATHS_CONFIG :/config/grafana/provisioning/grafana.ini
204+ GF_PATHS_DATA :/var/lib/grafana
104205ports :
105206 -" 3000:3000"
106207volumes :
107208 -grafana_data:/var/lib/grafana
108- -./config/grafana/provisioning:/etc/grafana/provisioning
109- -./config/grafana/dashboards:/var/lib/grafana/dashboards
110- -./config/grafana/provisioning/grafana.ini:/etc/grafana/grafana.ini
209+ -postgres_ai_configs:/config:rw
111210depends_on :
211+ -postgres-ai
112212 -sink-postgres
113213 -sink-prometheus
214+
114215flask-backend :
115216build :
116217context :./flask-backend
@@ -164,9 +265,17 @@ services:
164265 sleep 86400
165266 done
166267 "
268+ postgres-ai :
269+ build :
270+ context :.
271+ dockerfile :Dockerfile.postgres_ai
272+ container_name :postgres-ai
273+ volumes :
274+ -postgres_ai_configs:/config:/config
167275
168276volumes :
169277target_db_data :
170278sink_postgres_data :
171279prometheus_data :
172280grafana_data :
281+ postgres_ai_configs :