docker-compose.yml
Rama main · réplica de lectura del repositorio original.
services:
db:
image: timescale/timescaledb:2.31.0-pg16@sha256:322ae364eca3321cf2a48f1ef31213b87843413b3cf8feeebf54e999a26bb731
container_name: pulsebase-db
restart: unless-stopped
environment:
POSTGRES_DB: garmin
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
ports:
- "127.0.0.1:5433:5432"
volumes:
- timescale-data:/var/lib/postgresql/data
networks:
- internal
labels:
- "monitoring=true"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d garmin"]
interval: 10s
timeout: 5s
retries: 5
deploy:
resources:
limits:
memory: 2g
cpus: '1.00'
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
flyway:
image: flyway/flyway:13@sha256:4c535796a4a08daf542ac266b4f218e01e35051a8103de876536dfcdd1808471
container_name: pulsebase-flyway
command: migrate
volumes:
- ./db/migrations:/flyway/sql
environment:
- FLYWAY_URL=jdbc:postgresql://db:5432/garmin
- FLYWAY_USER=${DB_USER}
- FLYWAY_PASSWORD=${DB_PASSWORD}
- FLYWAY_CONNECT_RETRIES=10
- FLYWAY_MIXED=true
- FLYWAY_PLACEHOLDERS_DB_APP_USER=${DB_APP_USER}
- FLYWAY_PLACEHOLDERS_DB_APP_PASSWORD=${DB_APP_PASSWORD}
- FLYWAY_PLACEHOLDERS_DB_SYNC_USER=${DB_SYNC_USER}
- FLYWAY_PLACEHOLDERS_DB_SYNC_PASSWORD=${DB_SYNC_PASSWORD}
- FLYWAY_PLACEHOLDERS_DB_ML_USER=${DB_ML_USER}
- FLYWAY_PLACEHOLDERS_DB_ML_PASSWORD=${DB_ML_PASSWORD}
depends_on:
db:
condition: service_healthy
networks:
- internal
deploy:
resources:
limits:
memory: 256m
cpus: '0.25'
logging:
driver: json-file
options:
max-size: "5m"
max-file: "2"
api:
build:
context: .
dockerfile: api/Dockerfile
container_name: pulsebase-api
restart: unless-stopped
stop_grace_period: 45s
init: true
security_opt:
- "no-new-privileges:true"
labels:
- "monitoring=true"
env_file:
- env/.env.app
- env/.env.api
environment:
DB_HOST: db
DB_PORT: 5432
DB_NAME: garmin
depends_on:
flyway:
condition: service_completed_successfully
networks:
- internal
- gateway-garmin
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/ready"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
deploy:
resources:
limits:
memory: 512m
cpus: '0.50'
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
sync-service:
build:
context: .
dockerfile: sync-service/Dockerfile
container_name: pulsebase-sync
restart: unless-stopped
stop_grace_period: 120s
init: true
security_opt:
- "no-new-privileges:true"
labels:
- "monitoring=true"
depends_on:
flyway:
condition: service_completed_successfully
env_file:
- env/.env.app
- env/.env.sync
environment:
DB_HOST: db
DB_PORT: 5432
DB_NAME: garmin
networks:
- internal
healthcheck:
test: ["CMD-SHELL", "test -f /tmp/sync_alive && python -c \"import urllib.request; urllib.request.urlopen('http://localhost:8080/health')\""]
interval: 30s
timeout: 5s
start_period: 120s
retries: 3
deploy:
resources:
limits:
memory: 256m
cpus: '0.25'
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
ml-service:
build: ./ml-service
container_name: pulsebase-ml
restart: unless-stopped
stop_grace_period: 120s
init: true
security_opt:
- "no-new-privileges:true"
labels:
- "monitoring=true"
depends_on:
flyway:
condition: service_completed_successfully
env_file:
- env/.env.app
- env/.env.ml
environment:
MODEL_DIR: /app/models
DB_HOST: db
DB_PORT: 5432
DB_NAME: garmin
volumes:
- ml-models:/app/models
networks:
- internal
healthcheck:
test: ["CMD-SHELL", "test -f /tmp/ml_alive && python -c \"import urllib.request; urllib.request.urlopen('http://localhost:8080/health')\""]
interval: 30s
timeout: 5s
start_period: 60s
retries: 3
deploy:
resources:
limits:
memory: 1g
cpus: '1.00'
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
backup:
build: ./backup
container_name: pulsebase-backup
restart: unless-stopped
labels:
- "monitoring=true"
# DB admin creds come from env/.env (pg_dump needs full read); backup config
# from env/.env.backup (optional — stack still starts if absent, the run just
# fails its preflight on a missing AGE_RECIPIENT).
env_file:
- path: env/.env.backup
required: false
environment:
PGHOST: db
PGPORT: 5432
PGUSER: ${DB_USER}
PGPASSWORD: ${DB_PASSWORD}
PGDATABASE: garmin
depends_on:
db:
condition: service_healthy
volumes:
- backups:/backups
networks:
- internal
deploy:
resources:
limits:
memory: 256m
cpus: '0.25'
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
volumes:
timescale-data:
ml-models:
backups:
networks:
internal:
driver: bridge
gateway-garmin:
external: true
name: gateway-garmin