# VHS installation: db, migrate, backend, worker, nginx (see docs/installation.md). # The VHS images are the ones published for this release on GitHub's container registry: an # installation pulls them, it never builds them. Their version is changed only by a release # (CONTRIBUTING.md, "Releasing"). Development uses this same file plus the # docker-compose.dev.yml override, which builds its own images (docs/development.md); # docker-compose.build.yml builds the production images locally, to test them before a release. # # The video library is a folder of the host, set in .env with VHS_HOST_LIBRARY (see # docs/installation.md). It must exist before starting and be writable by uid 1000: # sudo mkdir -p /srv/vhs/library && sudo chown 1000:1000 /srv/vhs/library # create_host_path: false -> if the folder is missing, the containers are not created and # Docker does not create it. PostgreSQL keeps its data in the pgdata volume: never use # "down -v", which deletes it. name: vhs x-library: &library type: bind source: ${VHS_HOST_LIBRARY:?set VHS_HOST_LIBRARY in .env (e.g. /srv/vhs/library)} target: /srv/video-library bind: create_host_path: false x-backend: &backend image: ghcr.io/rocchidavide/vhs-backend:0.3.0 env_file: - path: .env required: false environment: POSTGRES_HOST: db POSTGRES_PORT: "5432" VHS_MEDIA_ROOT: /srv/video-library DJANGO_STATIC_ROOT: /srv/static volumes: - *library services: db: image: postgres:16-alpine environment: POSTGRES_DB: ${POSTGRES_DB:-vhs} POSTGRES_USER: ${POSTGRES_USER:-vhs} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-vhs} volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] interval: 5s timeout: 5s retries: 10 migrate: <<: *backend command: sh -c "python manage.py migrate --noinput && python manage.py collectstatic --noinput && python manage.py reconcile_downloads" volumes: - *library - static:/srv/static depends_on: db: condition: service_healthy backend: <<: *backend command: uvicorn config.asgi:application --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips="*" depends_on: migrate: condition: service_completed_successfully healthcheck: test: - CMD - python - -c # Host header: the first DJANGO_ALLOWED_HOSTS entry, since Django rejects any other # host (a real installation rarely lists "localhost"). - >- import os, urllib.request; host = os.environ.get('DJANGO_ALLOWED_HOSTS', 'localhost').split(',')[0].strip().lstrip('.'); host = 'localhost' if host in ('', '*') else host; urllib.request.urlopen(urllib.request.Request('http://127.0.0.1:8000/api/v1/health', headers={'Host': host}), timeout=3) interval: 10s timeout: 5s retries: 5 worker: <<: *backend command: python manage.py qcluster depends_on: migrate: condition: service_completed_successfully nginx: image: ghcr.io/rocchidavide/vhs-nginx:0.3.0 ports: - "${VHS_HTTP_PORT:-1976}:80" volumes: - <<: *library read_only: true - static:/srv/static:ro depends_on: backend: condition: service_healthy volumes: pgdata: static: