Skip to content

Deployment with Docker Compose

This method deploys all HCW@Home services in Docker containers. It is the recommended approach for development, testing, and cloud environments.

Prerequisites

  • Docker Engine 20+ and Docker Compose v2
  • Minimum 2 GB RAM
  • A domain name (production) or localhost (development)

Service Architecture

graph TD
    subgraph External Services
        LK[LiveKit - WebRTC SFU]
        SMTP[SMTP Server]
        SMS[SMS Gateway - optional]
    end

    subgraph Reverse Proxy
        NGINX[Nginx / Traefik / Caddy]
    end

    subgraph Frontends
        PRACT[Practitioner :8080]
        PAT[Patient :8081]
        ADM[Admin :8082]
    end

    subgraph Backend
        API[API :8000 - Django]
        CEL[Celery Worker]
        SCHED[Celery Beat]
        MIG[Migrate]
    end

    subgraph Data
        PG[(PostgreSQL :5432)]
        RD[(Redis :6379)]
    end

    NGINX --> PRACT
    NGINX --> PAT
    NGINX --> ADM
    PRACT --> API
    PAT --> API
    ADM --> API
    API --> PG
    API --> RD
    API --> LK
    CEL --> PG
    CEL --> RD
    CEL --> SMTP
    CEL --> SMS
    SCHED --> RD
    MIG --> PG

Quick Start

1. Clone the repository

wget https://raw.githubusercontent.com/HCW-home/hcw/refs/heads/master/docker-compose.yml

2. Configure the environment

Copy the configuration file:

TAG=0.10.0 docker compose pull

Then adjust the environment: blocks of docker-compose.yml to match your setup. The api, celery, scheduler and migrate services must all share the same database, Redis and secret key settings. See Environment Variables for the full reference.

Security

Never use the default values for DJANGOSECRET_KEY in production. Generate a key with: echo -n "your secret phrase" | sha256sum

3. Start the services

docker compose up -d

On first launch, the migrate service automatically applies database migrations.

4. Create a tenant

HCW@Home uses multi-tenancy with PostgreSQL schema isolation. Each tenant has its own data, users, and configuration. Tenants are created via the Django shell.

docker compose exec api python3 manage.py create_tenant
  • schema name: localhost
  • name: localhost
  • domain: 127.0.0.1
docker compose exec api python3 manage.py tenant_command createsuperuser -s localhost

Multiple tenants

Repeat this process for each organization. Each tenant is fully isolated: separate users, consultations, configuration, and branding.

5. Load test data (optional)

docker compose exec api python manage.py loaddata initial/TestData.json

This creates test users (password: Test1234). See the README for the full list.

Services and Ports

Service Exposed Port Description
practitioner 8080 Practitioner interface (Angular)
patient 8081 Patient interface (Ionic)
admin 8082 Django admin interface
api internal REST API + WebSocket (Daphne)
celery - Asynchronous task worker
scheduler - Task scheduler (Celery Beat)
db internal PostgreSQL 15
redis internal Redis 7

Health Checks

Every long running service declares a health check, so docker compose ps reports the real state and the frontends only start once the API answers.

Service Probe
api GET /api/health/, which runs before tenant resolution and checks PostgreSQL and Redis. Reported unhealthy while MAINTENANCE=True
celery celery inspect ping against this worker only, so a healthy replica cannot mask a dead one
scheduler Celery Beat has no remote control API: the beat process is checked with pgrep
practitioner, patient, admin Local Nginx request, no backend call, so they stay green when the API is down
db pg_isready
redis redis-cli ping

Persistent Volumes

Data is stored in the ./data/ directory:

Path Content
./data/postgres_data/ PostgreSQL data
./data/redis_data/ Redis data
./data/uploads/ Uploads (MEDIA_ROOT), shared by api and celery. Unused when S3 is configured

Uploads permissions

The backend containers run as uid 1000. Create the directory with the right owner before the first start, otherwise every upload fails:

mkdir -p data/uploads && sudo chown 1000:1000 data/uploads