From 6b455e32b66807f2afb47773c524f7acebdf13bf Mon Sep 17 00:00:00 2001 From: Dominique Merle Date: Sat, 27 Jun 2026 12:40:49 +0200 Subject: [PATCH] config(docker): review and update Make sure the thing actually works. We also closed some vulnerabilities. --- docker-compose.yml | 191 +++++++++++++++++++-------------------------- 1 file changed, 82 insertions(+), 109 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index da4a087..9f474c9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,33 +1,34 @@ +# Make sure you either source .env.local or use --env-file like so: +# docker compose --env-file .env.local --profile all up + services: + + # Postgresql database, nothing fancy + # https://hub.docker.com/_/postgres mj_db: profiles: - core - all - # https://hub.docker.com/_/postgres - image: postgres:15.1 + image: postgres:15 restart: unless-stopped hostname: ${DB_HOST:-mj_db} healthcheck: - start_period: 20s + start_period: 30s test: ["CMD", "pg_isready", "--user", "${DB_USER:-mj}"] - interval: 1m + interval: 10m timeout: 10s retries: 3 environment: POSTGRES_DB: "${DB_NAME:-mj}" POSTGRES_USER: "${DB_USER:-mj}" - POSTGRES_PASSWORD: "${DB_PASS}" + POSTGRES_PASSWORD: "${DB_PASS:?error}" TZ: "${TIMEZONE:-Europe/Paris}" networks: - lan - ports: - - ${DB_PORT:-5433}:5432 volumes: - # Old mount point, before the infamous 2025-05 database wipe. - #- db:/var/lib/mysql - # Restoring the volume backup only worked when we mounted it here. - - db:/var/lib/postgresql/data + - "db:/var/lib/postgresql/data" + # The actual python fastapi we use as backend mj_api: profiles: - core @@ -37,27 +38,33 @@ services: context: . dockerfile: docker/Dockerfile restart: unless-stopped - # TODO remove reload - command: uvicorn app.main:app --host 0.0.0.0 --port 8877 --proxy-headers --env-file ${ENV_FILE:-.env.local} --reload + # Note: we might need --reload here as a last resort + command: > + uvicorn app.main:app + --host 0.0.0.0 + --port 8877 + --proxy-headers + --env-file ${ENV_FILE:-.env.local} healthcheck: start_period: 30s test: ['CMD-SHELL', 'curl localhost:8877/liveness -s -f -o /dev/null || exit 1'] - interval: 1m + interval: 10m timeout: 10s retries: 3 depends_on: mj_db: condition: service_healthy environment: - POSTGRES_HOST: ${DB_HOST:-mj_db} + POSTGRES_HOST: "${DB_HOST:-mj_db}" POSTGRES_USER: "${DB_USER:-mj}" POSTGRES_PASSWORD: "${DB_PASS}" POSTGRES_DB: "${DB_NAME:-mj}" TZ: "${TIMEZONE:-Europe/Paris}" ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-["*"]} SECRET: "${SECRET}" - ports: - - 8877:8877 + # We do not need to expose those + #ports: + # - 8877:8877 volumes: - .:/code networks: @@ -66,43 +73,13 @@ services: labels: - "traefik.enable=true" - "traefik.docker.network=traefik_network" - - "traefik.http.routers.mj.entrypoints=web,websecure" - - "traefik.http.routers.mj.rule=Host(`${API_PREFIX:-api}.${DOMAIN}`)" - "traefik.http.services.mj.loadbalancer.server.port=8877" + - "traefik.http.routers.mj.entrypoints=websecure" + - "traefik.http.routers.mj.rule=Host(`${API_PREFIX:-api}.${DOMAIN}`)" - "traefik.http.routers.mj.tls=true" - "traefik.http.routers.mj.tls.certresolver=leresolver" - # Disabled because on our server this service fails repeatedly: - # > Fatal: create repository at s3:s3.amazonaws.com/mieuxvoter-app failed: client.BucketExists: Access Denied. -# mj_restic: -# profiles: -# - backup -# - all -# depends_on: -# mj_db: -# condition: service_healthy -# image: restic -# networks: -# - lan -# build: -# context: ./docker/restic -# dockerfile: Dockerfile -# args: -# RESTIC_INIT_ARGS: $RESTIC_INIT_ARGS -# RESTIC_PASSWORD: $RESTIC_PASSWORD -# restart: unless-stopped -# volumes: -# - db:/data/db -# - imgpush:/data/images -# environment: -# - TZ=${TIMEZONE:-Europe/Paris} -# - RESTIC_REPOSITORY=$RESTIC_REPOSITORY -# - BACKUP_CRON=${RESTIC_BACKUP_CRON:-0 0 * * *} -# - RESTIC_FORGET_ARGS=--prune --keep-last 1 --keep-daily 1 -# - AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID -# - AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY -# - MAILX_ARGS=-r "${RESTIC_SEND_MAIL}" -s "Result of the last restic backup run" -S smtp="${SMTP_HOST}:${SMTP_PORT:-587}" -S smtp-use-starttls -S smtp-auth=login -S smtp-auth-user="${SMTP_USER}" -S smtp-auth-password="${SMTP_PASS}" "${RESTIC_DEST_MAIL}" - + # Microservice to handle the upload of images mj_imgpush: profiles: - image @@ -121,12 +98,14 @@ services: ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-["*"]} VALID_SIZES: ${VALID_SIZES:-"[100,200,300]"} NAME_STRATEGY: "uuidv4" - healthcheck: - start_period: 15s - test: ['CMD-SHELL', 'curl localhost:5000/liveness -s -f -o /dev/null || exit 1'] - interval: 10m - timeout: 10s - retries: 3 + # Restore this healthcheck once the slop code at imgpush has been fixed GRRRRR + # See https://github.com/hauxir/imgpush/pull/55 + # healthcheck: + # start_period: 30s + # test: ['CMD-SHELL', 'curl localhost:5000/liveness -s -f -o /dev/null || exit 1'] + # interval: 10m + # timeout: 10s + # retries: 3 volumes: - imgpush:/images networks: @@ -135,83 +114,77 @@ services: labels: - "traefik.enable=true" - "traefik.docker.network=traefik_network" - - "traefik.http.routers.imgpush.entrypoints=web,websecure" - - "traefik.http.routers.imgpush.rule=Host(`${IMGPUSH_PREFIX:-imgpush}.${DOMAIN}`)" - "traefik.http.services.imgpush.loadbalancer.server.port=5000" + - "traefik.http.routers.imgpush.entrypoints=websecure" + - "traefik.http.routers.imgpush.rule=Host(`imgpush.${DOMAIN}`)" - "traefik.http.routers.imgpush.tls=true" - "traefik.http.routers.imgpush.tls.certresolver=leresolver" - mj_metabase: - profiles: - - dashboard - - all - image: metabase/metabase - restart: unless-stopped - depends_on: - mj_db: - condition: service_healthy - environment: - MB_DB_TYPE: postgres - MB_DB_DBNAME: "${DB_NAME:-mj}" - MB_DB_HOST: ${DB_HOST:-mj_db} - MB_DB_PORT: ${DB_PORT:-5433} - MB_DB_USER: "${DB_USER:-mj}" - MB_DB_PASS: "${DB_PASS}" - TZ: ${TIMEZONE:-Europe/Paris} - networks: - - lan - - traefik_network - labels: - - "traefik.enable=true" - - "traefik.docker.network=traefik_network" - - "traefik.http.routers.metabase.entrypoints=web,websecure" - - "traefik.http.routers.metabase.rule=Host(`${METABASE_PREFIX:-metabase}.${DOMAIN}`)" - - "traefik.http.services.metabase.loadbalancer.server.port=3000" - - "traefik.http.routers.metabase.tls=true" - - "traefik.http.routers.metabase.tls.certresolver=leresolver" - mj_pgadmin: + # UI to inspect/edit the database + # https://hub.docker.com/_/adminer/ + mj_adminer: profiles: - admin - all - image: dpage/pgadmin4 + # 5.4.2 works + image: adminer:5 restart: unless-stopped depends_on: mj_db: condition: service_healthy environment: - PGADMIN_DEFAULT_EMAIL: ${EMAIL:-pgadmin4@pgadmin.org} - PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-admin} - PGADMIN_CONFIG_SERVER_MODE: 'False' - healthcheck: - start_period: 15s - test: ["CMD", "wget", "-q", "-O", "-", "http://localhost:${PGADMIN_PORT:-5050}"] - interval: 10m - timeout: 10s - retries: 3 - volumes: - - pgadmin:/var/lib/pgadmin - ports: - - "${PGADMIN_PORT:-5050}:80" + ADMINER_DEFAULT_SERVER: mj_db + ADMINER_DESIGN: dracula networks: - lan - traefik_network labels: - "traefik.enable=true" - "traefik.docker.network=traefik_network" - - "traefik.http.routers.pgadmin.entrypoints=web,websecure" - - "traefik.http.routers.pgadmin.rule=Host(`${PGADMIN:-pgadmin}.${DOMAIN}`)" - - "traefik.http.services.pgadmin.loadbalancer.server.port=80" - - "traefik.http.routers.pgadmin.tls=true" - - "traefik.http.routers.pgadmin.tls.certresolver=leresolver" + - "traefik.http.services.adminer.loadbalancer.server.port=8080" + - "traefik.http.middlewares.auth.basicauth.users=${AUTH_HASH:?error}" + - "traefik.http.routers.adminer.middlewares=auth" + - "traefik.http.routers.adminer.entrypoints=websecure" + - "traefik.http.routers.adminer.rule=Host(`adminer.${DOMAIN}`)" + - "traefik.http.routers.adminer.tls=true" + - "traefik.http.routers.adminer.tls.certresolver=leresolver" + + + # Expensive stats + # mj_metabase: + # profiles: + # - dashboard + # - all + # image: metabase/metabase + # restart: unless-stopped + # depends_on: + # mj_db: + # condition: service_healthy + # environment: + # MB_DB_TYPE: postgres + # MB_DB_DBNAME: "${DB_NAME:-mj}" + # MB_DB_HOST: "${DB_HOST:-mj_db}" + # MB_DB_PORT: ${DB_PORT:-5433} + # MB_DB_USER: "${DB_USER:-mj}" + # MB_DB_PASS: "${DB_PASS}" + # TZ: ${TIMEZONE:-Europe/Paris} + # networks: + # - lan + # - traefik_network + # labels: + # - "traefik.enable=true" + # - "traefik.docker.network=traefik_network" + # - "traefik.http.routers.metabase.entrypoints=websecure" + # - "traefik.http.routers.metabase.rule=Host(`${METABASE_PREFIX:-metabase}.${DOMAIN}`)" + # - "traefik.http.services.metabase.loadbalancer.server.port=3000" + # - "traefik.http.routers.metabase.tls=true" + # - "traefik.http.routers.metabase.tls.certresolver=leresolver" volumes: imgpush: db: - pgadmin: - redis_data: - driver: local networks: