@underpostnet/underpost
Version:
Underpost Platform — end-to-end CI/CD and application-delivery toolchain CLI. Covers bare metal, Kubernetes, K3s, kubeadm, LXD, container/image orchestration, secrets, databases, cron jobs, monitoring, SSH, runners, PWA + Workbox delivery, and release orc
225 lines (215 loc) • 8.04 kB
YAML
# Production-style Docker Compose stack mirroring the Kubernetes development
# environment defined under manifests/{mongodb,valkey,deployment/dd-default-development}.
#
# Mapping summary (K8s -> Compose):
# StatefulSet mongodb (replSet rs0, keyFile auth) -> mongodb + mongodb-keyfile-init + mongodb-rs-init
# StatefulSet valkey-service -> valkey-service
# Deployment dd-default-development-blue -> app
# HTTPProxy default.net / www.default.net (Contour) -> proxy (nginx reverse proxy)
# Service type LoadBalancer / NodePort -> published host ports via the proxy
# Secret mongodb-secret / mongodb-keyfile -> .env values + generated keyfile volume
# PVC mongodb-storage / volumeClaimTemplates -> named volumes
name: dd-default-development
services:
# --- MongoDB -------------------------------------------------------------
# Mirrors manifests/mongodb/statefulset.yaml: replSet rs0, keyFile cluster
# auth, --auth, bind to all interfaces. Single-node replica set for local dev.
#
# Bootstrap follows src/db/mongo/MongoBootstrap.js rather than the image's
# MONGO_INITDB_ROOT_USERNAME auto-init (whose temp server + keyFile combination
# is unreliable). The generated entrypoint (docker/mongodb/entrypoint.sh)
# generates the keyfile, starts mongod, and bootstraps the replica set + root
# user over the loopback localhost exception. The healthcheck gates readiness
# on an authenticated writable primary.
mongodb:
image: ${MONGO_IMAGE:-mongo:latest}
container_name: dd-mongodb
entrypoint: ['bash', '/docker-init/entrypoint.sh']
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME:?set MONGO_INITDB_ROOT_USERNAME in docker/compose.env}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD:?set MONGO_INITDB_ROOT_PASSWORD in docker/compose.env}
DB_REPLICA_SET: ${DB_REPLICA_SET:-rs0}
volumes:
- ./docker/mongodb:/docker-init:ro
- mongodb-keyfile:/opt/keyfile
- mongodb-data:/data/db
networks:
- dd-internal
expose:
- '27017'
ports:
- '${MONGO_HOST_PORT:-27017}:27017'
healthcheck:
test:
- CMD-SHELL
- >
mongosh --quiet -u "$$MONGO_INITDB_ROOT_USERNAME" -p "$$MONGO_INITDB_ROOT_PASSWORD"
--authenticationDatabase admin --eval "db.hello().isWritablePrimary" | grep -q true
interval: 10s
timeout: 5s
retries: 20
start_period: 60s
restart: unless-stopped
# --- Valkey --------------------------------------------------------------
# Mirrors manifests/valkey/statefulset.yaml.
valkey-service:
image: ${VALKEY_IMAGE:-valkey/valkey:latest}
container_name: dd-valkey
command: ['valkey-server', '--port', '6379', '--bind', '0.0.0.0', '--protected-mode', 'no']
volumes:
- valkey-data:/data
networks:
- dd-internal
expose:
- '6379'
# NodePort equivalent (manifests/valkey/valkey-nodeport.yaml nodePort 32079).
ports:
- '${VALKEY_NODEPORT:-32079}:6379'
healthcheck:
test: ['CMD', 'valkey-cli', '-p', '6379', 'ping']
interval: 10s
timeout: 5s
retries: 10
start_period: 10s
restart: unless-stopped
# --- Application ---------------------------------------------------------
# Mirrors manifests/deployment/dd-default-development/deployment.yaml
# (dd-default-development-blue). Connection targets use Docker service
# discovery instead of hardcoded localhost.
app:
image: ${APP_IMAGE:-underpost/underpost-engine}:${APP_TAG:-v3.2.70}
container_name: dd-app
# The start command is supplied by the generated override docker/compose.app.yml
# (see `underpost docker-compose --generate --deploy-id <id>`), keeping this
# file deployment-agnostic.
environment:
NODE_ENV: ${NODE_ENV:-development}
DB_PROVIDER: ${DB_PROVIDER:-mongoose}
DB_HOST: ${DB_HOST:-mongodb://mongodb:27017}
DB_NAME: ${DB_NAME:-default}
DB_REPLICA_SET: ${DB_REPLICA_SET:-rs0}
DB_AUTH_SOURCE: ${DB_AUTH_SOURCE:-admin}
DB_USER: ${MONGO_INITDB_ROOT_USERNAME:?}
DB_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD:?}
VALKEY_HOST: ${VALKEY_HOST:-valkey-service}
VALKEY_PORT: ${VALKEY_PORT:-6379}
networks:
- dd-internal
expose:
- '4001'
- '4002'
- '4003'
- '4004'
# Direct access to the LoadBalancer-equivalent ports (manifest 4001-4004).
ports:
- '${APP_PORT_4001:-4001}:4001'
- '${APP_PORT_4002:-4002}:4002'
- '${APP_PORT_4003:-4003}:4003'
- '${APP_PORT_4004:-4004}:4004'
healthcheck:
test: ['CMD-SHELL', "timeout 2 bash -c '</dev/tcp/127.0.0.1/4001' || exit 1"]
interval: 15s
timeout: 5s
retries: 5
start_period: 60s
depends_on:
mongodb:
condition: service_healthy
valkey-service:
condition: service_healthy
restart: unless-stopped
# --- Reverse proxy / NodePort-equivalent load balancer -------------------
# Mirrors manifests/deployment/dd-default-development/proxy.yaml (Contour
# HTTPProxy) using nginx with websocket upgrade support.
proxy:
image: ${PROXY_IMAGE:-nginx:stable-alpine}
container_name: dd-proxy
volumes:
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
networks:
- dd-internal
ports:
- '${PROXY_HTTP_PORT:-80}:80'
healthcheck:
test: ['CMD', 'wget', '-q', '-O', '-', 'http://127.0.0.1/healthz']
interval: 15s
timeout: 5s
retries: 5
start_period: 10s
depends_on:
app:
condition: service_started
restart: unless-stopped
# --- Monitoring: Prometheus ----------------------------------------------
# Mirrors manifests/prometheus/deployment.yaml. Scrapes the app's /metrics
# endpoint (prom-client) over the internal network. Config is generated by
# `underpost docker-compose --generate` into docker/prometheus/prometheus.yml.
prometheus:
image: ${PROMETHEUS_IMAGE:-prom/prometheus:latest}
container_name: dd-prometheus
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.path=/prometheus
volumes:
- ./docker/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus-data:/prometheus
networks:
- dd-internal
expose:
- '9090'
ports:
- '${PROMETHEUS_PORT:-9090}:9090'
healthcheck:
test: ['CMD', 'wget', '-q', '-O', '-', 'http://127.0.0.1:9090/-/healthy']
interval: 15s
timeout: 5s
retries: 5
start_period: 15s
depends_on:
app:
condition: service_started
restart: unless-stopped
# --- Monitoring: Grafana -------------------------------------------------
# Mirrors manifests/grafana/deployment.yaml. Prometheus datasource is
# pre-provisioned (generated) so dashboards work out of the box.
grafana:
image: ${GRAFANA_IMAGE:-grafana/grafana:latest}
container_name: dd-grafana
environment:
GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER:-admin}
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD:-admin}
GF_USERS_ALLOW_SIGN_UP: 'false'
volumes:
- ./docker/grafana/provisioning:/etc/grafana/provisioning:ro
- grafana-data:/var/lib/grafana
networks:
- dd-internal
expose:
- '3000'
ports:
- '${GRAFANA_PORT:-3000}:3000'
healthcheck:
test: ['CMD', 'wget', '-q', '-O', '-', 'http://127.0.0.1:3000/api/health']
interval: 15s
timeout: 5s
retries: 5
start_period: 15s
depends_on:
prometheus:
condition: service_started
restart: unless-stopped
networks:
dd-internal:
name: dd-internal
driver: bridge
volumes:
mongodb-data:
name: dd-mongodb-data
mongodb-keyfile:
name: dd-mongodb-keyfile
valkey-data:
name: dd-valkey-data
prometheus-data:
name: dd-prometheus-data
grafana-data:
name: dd-grafana-data