TCP Proxy to a Postgres Database
docker compose up -d
docker compose run test
🚀
--- | |
services: | |
pghost: | |
image: postgres:15-alpine | |
environment: | |
POSTGRES_PASSWORD: foo | |
proxy: | |
build: . | |
environment: | |
PROXY_HOST: pghost | |
PROXY_PORT: 5432 | |
ports: | |
- 5432:5432 | |
volumes: | |
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro | |
test: | |
image: postgres:15-alpine | |
entrypoint: "" | |
command: | | |
sh -c ' | |
pg_isready --host=proxy --username=postgres | |
' | |
profiles: | |
- test |
FROM haproxy:2.9-alpine | |
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg | |
COPY healthcheck.sh /usr/local/bin/healthcheck.sh | |
HEALTHCHECK CMD ["/usr/local/bin/healthcheck.sh"] | |
ARG HEALTHCHECK_PORT="8080" | |
ARG METRICS_PORT="8405" | |
# align client and server timeouts with underlying server (e.g. match databaseidle_session_timeout value) | |
# WARNING: Ports Must be > 1024 in AWS Fargate -- https://github.com/aws/containers-roadmap/issues/1721 | |
ENV \ | |
CLIENT_TIMEOUT="180m" \ | |
HEALTHCHECK_PORT="${HEALTHCHECK_PORT}" \ | |
MAX_CONNECTIONS="1024" \ | |
METRICS_PORT="${METRICS_PORT}" \ | |
PROXY_HOST="replace-me" \ | |
PROXY_PORT="replace-me" \ | |
SERVER_TIMEOUT="180m" |
global | |
maxconn 24000 | |
log stderr format raw daemon info | |
defaults | |
# log-format "{\"client_ip\":\"%ci\",\"duration\":%Tt,\"bytes\":%B,\"terminaton_state\":\"%ts\",\"actconn\":%ac,\"beconn\":%bc,\"feconn\":%fc,\"retries\":%rc,\"srv_queue\":%sq,\"backend_queue\":%bq}" | |
option tcplog | |
option dontlognull | |
retries 3 | |
timeout check 2s | |
timeout connect 1s | |
# align client and server timeouts with underlying server (e.g. match databaseidle_session_timeout value) | |
timeout client "$CLIENT_TIMEOUT" | |
timeout server "$SERVER_TIMEOUT" | |
maxconn "$MAX_CONNECTIONS" | |
resolvers dns | |
parse-resolv-conf | |
frontend healthcheck | |
bind *:"$HEALTHCHECK_PORT" | |
mode http | |
monitor fail if { nbsrv(host) eq 0 } | |
monitor-uri /status | |
maxconn 16 | |
frontend metrics | |
bind *:"$METRICS_PORT" | |
mode http | |
http-request use-service prometheus-exporter if { path /metrics } | |
no log | |
maxconn 16 | |
frontend main | |
bind *:"$PROXY_PORT" | |
default_backend host | |
log global | |
mode tcp | |
backend host | |
server h1 "$PROXY_HOST":"$PROXY_PORT" resolvers dns check maxconn "$MAX_CONNECTIONS" |
#!/usr/bin/env sh | |
wget -SO - "http://127.0.0.1:${HEALTHCHECK_PORT}/status" > /dev/null 2>&1 || exit 1 |
In the above, the server FQDN is looked up once one startup and cached. In order to respond to PROXY_HOST IP changes, a
resolvers
section must be used;haproxy.cfg with runtime DNS lookups
HAProxy will now log IP changes;
to simulate this, an extended docker compose file can be used;
docker compose up
pghost
, e.g. from "172.16.238.33" to "172.16.238.34" and rundocker compose up pghost -d
docker-compose.yml with set networks and IPs