@@ -23,39 +23,124 @@ services:
2323 - PYTHONUNBUFFERED=1
2424 # Ensures Python output is sent directly to logs (not buffered)
2525 # Makes 'docker-compose logs' show real-time output
26+ - VIRTUAL_HOST=${HOST}
27+ # Tells nginx-proxy which domain should route to this container
28+ # nginx-proxy watches Docker and auto-configures when it sees this variable
29+ - VIRTUAL_PATH=${VIRTUAL_PATH}
30+ # Restricts access to only this specific path on the domain
31+ # Example: VIRTUAL_PATH=/survey-dashboard means only /survey-dashboard/* is accessible
32+ # All other paths on this domain return 404
33+ - VIRTUAL_PROTO=http
34+ # Protocol nginx-proxy uses to communicate with this container
35+ # Uses HTTP inside Docker network (fast, safe), HTTPS for external traffic
36+ - LETSENCRYPT_HOST=${HOST}
37+ # Tells acme-companion to get SSL certificate for this domain
38+ # acme-companion watches Docker and auto-requests certificates when it sees this
39+ - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL}
40+ # Email for Let's Encrypt certificate notifications
41+ # Used for expiry warnings and security notices about your certificates
2642
2743 # Uncomment to mount local code for development
2844 # volumes:
2945 # - ./survey_dashboard:/app/survey_dashboard
3046
31- # Nginx reverse proxy container
32- nginx :
33- image : nginx:latest
34- # Uses official nginx image from Docker Hub
35- # No custom build needed - just mount our config
47+ # Nginx reverse proxy container with auto-configuration
48+ nginx-proxy :
49+ container_name : nginx-proxy
50+ image : nginxproxy/nginx-proxy:latest
51+ # Auto-configuring reverse proxy that watches Docker containers
52+ # Automatically generates nginx config based on container environment variables
3653
3754 ports :
3855 - " 80:80"
39- # Maps host port 80 to container port 80
40- # This is the ONLY port exposed to the internet
41- # Users access dashboard via http://yourdomain.com (port 80)
56+ # HTTP port - used for ACME challenges and auto-redirect to HTTPS
57+ - " 443:443 "
58+ # HTTPS port - secure encrypted connections
4259
4360 volumes :
44- - ./nginx/conf.d:/etc/nginx/conf.d:ro
45- # Mounts our nginx config into the container
46- # :ro = read-only (nginx cannot modify our files)
47- # Changes to config files are reflected immediately
61+ # nginx-proxy auto-generates configuration based on container env vars
62+ # Custom per-domain configs can be placed in ./nginx/vhost.d/
63+ - ./nginx/certs:/etc/nginx/certs:ro
64+ # SSL certificates storage (read-only for nginx-proxy)
65+ # acme-companion writes certificates here, nginx-proxy reads them
66+ - ./nginx/vhost.d:/etc/nginx/vhost.d
67+ # Per-domain custom nginx configurations
68+ # Files named after domains (e.g., survey.example.com) are included in that domain's config
69+ - ./nginx/html:/usr/share/nginx/html
70+ # Web root for serving ACME challenge files during Let's Encrypt verification
71+ # acme-companion creates challenge files here, nginx-proxy serves them
72+ - /var/run/docker.sock:/tmp/docker.sock:ro
73+ # Docker socket for auto-discovery of containers
74+ # nginx-proxy watches for containers with VIRTUAL_HOST env var
75+ # Read-only for security (can observe but not control Docker)
4876
4977 depends_on :
5078 - dashboard
51- # Ensures dashboard container starts before nginx
52- # Nginx needs dashboard to be available for proxying
79+ # Ensures dashboard container starts before nginx-proxy
80+ # nginx-proxy needs dashboard to be available for proxying
5381
5482 restart : unless-stopped
5583 # Same restart policy as dashboard
5684
85+ labels :
86+ - " com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true"
87+ # Identifies this container as the nginx instance for acme-companion to manage
88+ # acme-companion will reload this container when SSL certificates are updated
89+
90+ # Let's Encrypt certificate management container
91+ letsencrypt :
92+ container_name : acme-companion
93+ image : nginxproxy/acme-companion
94+ # ACME protocol client for automatic Let's Encrypt certificate management
95+ # Watches for containers with LETSENCRYPT_HOST environment variable
96+
97+ environment :
98+ - NGINX_PROXY_CONTAINER=nginx-proxy
99+ # Tells acme-companion which nginx container to reload when certificates update
100+ # Must match the container_name of nginx-proxy service
101+ - DEFAULT_EMAIL=${LETSENCRYPT_EMAIL}
102+ # Default email for Let's Encrypt certificate registration and notifications
103+ # Individual containers can override with their own LETSENCRYPT_EMAIL
104+ # Used for certificate expiry warnings and security notices
105+
106+ volumes :
107+ - ./nginx/certs:/etc/nginx/certs:rw
108+ # SSL certificates storage (read-write for acme-companion)
109+ # acme-companion writes new certificates here, nginx-proxy reads them
110+ # Note: :rw (not :ro like nginx-proxy) because acme-companion must write certs
111+ - ./nginx/vhost.d:/etc/nginx/vhost.d
112+ # Per-domain custom nginx configurations
113+ # acme-companion may add temporary configs for ACME challenge handling
114+ - ./nginx/html:/usr/share/nginx/html
115+ # Web root for ACME challenge files
116+ # acme-companion creates challenge files here, nginx-proxy serves them to Let's Encrypt
117+ - /var/run/docker.sock:/var/run/docker.sock:ro
118+ # Docker socket for container discovery and nginx reload
119+ # Watches for containers with LETSENCRYPT_HOST environment variable
120+ # Sends reload signal to nginx-proxy when certificates update
121+ - acme-data:/etc/acme.sh
122+ # Named volume for Let's Encrypt account data (NOT a directory)
123+ # Stores account credentials, must persist across container restarts
124+ # Losing this data means re-registering with Let's Encrypt
125+
126+ depends_on :
127+ - nginx-proxy
128+ # Ensures nginx-proxy starts before acme-companion
129+ # acme-companion needs nginx-proxy to be running to reload it when certificates update
130+
131+ restart : unless-stopped
132+ # Automatically restart if container crashes
133+ # Persists across system reboots unless manually stopped
134+ # Critical for certificate renewal - must stay running to renew certs every 90 days
135+
57136networks :
58137 default :
59138 # Docker Compose automatically creates a default network
60139 # Both containers join this network and can communicate
61140 # Service names (dashboard, nginx) work as DNS hostnames
141+
142+ volumes :
143+ acme-data :
144+ # Named volume for Let's Encrypt account credentials
145+ # Docker manages this volume's lifecycle (persists across container removals)
146+ # Only destroyed if explicitly deleted with: docker volume rm survey-dashboard_acme-data
0 commit comments