-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdocker-compose.yml.tera
More file actions
269 lines (259 loc) · 8.92 KB
/
docker-compose.yml.tera
File metadata and controls
269 lines (259 loc) · 8.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# ============================================================================
# Torrust Tracker Deployer - Generated Configuration
# ============================================================================
#
# This file was generated by the Torrust Tracker Deployer.
# Generated: {{ generated_at }}
#
# DOCUMENTATION:
# Repository: https://github.com/torrust/torrust-tracker-deployer
# Template: templates/docker-compose/docker-compose.yml.tera
# Rust Wrapper: src/infrastructure/templating/docker_compose/template/wrappers/docker_compose/template.rs
# API Docs: https://docs.rs/torrust-tracker-deployer/latest/
#
# DESCRIPTION:
# Docker Compose service definitions for Torrust Tracker deployment.
# Includes tracker, optional MySQL, Prometheus, Grafana, and Caddy services.
#
# For configuration options and valid values, see the API documentation link above.
# ============================================================================
# IMPORTANT: Environment Variable Injection Pattern
#
# All configuration values that may need to be changed during maintenance
# should be injected via environment variables from the .env file, not
# hardcoded in this docker-compose template.
#
# Pattern to follow:
# CORRECT: - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
# INCORRECT: - MYSQL_ROOT_PASSWORD=hardcoded_value
#
# Rationale:
# - System administrators can modify .env values and restart services without
# regenerating templates
# - Supports runtime configuration changes without redeployment
# - Follows Docker Compose best practices for configuration management
# - Separates template generation (deploy-time) from configuration (runtime)
#
# See ADR: docs/decisions/environment-variable-injection-in-docker-compose.md
# Common service defaults (YAML anchor for DRY configuration)
x-defaults: &defaults
tty: true
restart: unless-stopped
logging:
options:
max-size: "10m"
max-file: "10"
services:
{%- if caddy %}
# Caddy reverse proxy for automatic HTTPS with Let's Encrypt
# Placed first as it's the entry point for HTTPS traffic
caddy:
<<: *defaults
image: caddy:2.10
container_name: caddy
# NOTE: No UFW firewall rule needed for these ports!
# Docker-published ports bypass iptables/UFW rules entirely.
# The configure-firewall.yml playbook closes all ports except SSH,
# but Docker creates its own iptables chains that take precedence.
# See: docs/user-guide/security.md for the full security model.
{%- if caddy.ports | length > 0 %}
ports:
{%- for port in caddy.ports %}
# {{ port.description }}
- "{{ port.binding }}"
{%- endfor %}
{%- endif %}
volumes:
- ./storage/caddy/etc/Caddyfile:/etc/caddy/Caddyfile:ro
- ./storage/caddy/data:/data # TLS certificates (MUST persist!)
- ./storage/caddy/config:/config
{%- if caddy.networks | length > 0 %}
networks:
{%- for network in caddy.networks %}
- {{ network }}
{%- endfor %}
{%- endif %}
healthcheck:
test: ["CMD", "caddy", "validate", "--config", "/etc/caddy/Caddyfile"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
{%- endif %}
tracker:
<<: *defaults
# TODO: Pin to stable v4.0.0 when released (currently using develop tag)
# Tracking issue: https://github.com/torrust/torrust-tracker-deployer/issues/TBD
# Rationale: The develop tag is mutable and introduces deployment non-reproducibility.
# Pinning to a stable release ensures predictable deployments and easier rollback.
image: torrust/tracker:develop
container_name: tracker
{%- if mysql %}
depends_on:
mysql:
condition: service_healthy
{%- endif %}
environment:
- USER_ID=1000
- TORRUST_TRACKER_CONFIG_OVERRIDE_CORE__DATABASE__DRIVER=${TORRUST_TRACKER_CONFIG_OVERRIDE_CORE__DATABASE__DRIVER}
- TORRUST_TRACKER_CONFIG_TOML_PATH=${TORRUST_TRACKER_CONFIG_TOML_PATH}
- TORRUST_TRACKER_CONFIG_OVERRIDE_HTTP_API__ACCESS_TOKENS__ADMIN=${TORRUST_TRACKER_CONFIG_OVERRIDE_HTTP_API__ACCESS_TOKENS__ADMIN}
{%- if tracker.networks | length > 0 %}
networks:
{%- for network in tracker.networks %}
- {{ network }}
{%- endfor %}
{%- endif %}
{%- if tracker.ports | length > 0 %}
ports:
{%- for port in tracker.ports %}
# {{ port.description }}
- "{{ port.binding }}"
{%- endfor %}
{%- endif %}
volumes:
- ./storage/tracker/lib:/var/lib/torrust/tracker:Z
- ./storage/tracker/log:/var/log/torrust/tracker:Z
- ./storage/tracker/etc:/etc/torrust/tracker:Z
{%- if prometheus %}
prometheus:
<<: *defaults
image: prom/prometheus:v3.5.0
container_name: prometheus
{%- if prometheus.networks | length > 0 %}
networks:
{%- for network in prometheus.networks %}
- {{ network }}
{%- endfor %}
{%- endif %}
{%- if prometheus.ports | length > 0 %}
ports:
{%- for port in prometheus.ports %}
# {{ port.description }}
- "{{ port.binding }}"
{%- endfor %}
{%- endif %}
# Grafana accesses Prometheus via Docker network: http://prometheus:9090
# Host can access for validation via: curl http://localhost:9090
volumes:
- ./storage/prometheus/etc:/etc/prometheus:Z
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://localhost:9090/-/healthy"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
depends_on:
- tracker
{%- endif %}
{%- if grafana %}
grafana:
<<: *defaults
image: grafana/grafana:12.3.1
container_name: grafana
{%- if grafana.networks | length > 0 %}
networks:
{%- for network in grafana.networks %}
- {{ network }}
{%- endfor %}
{%- endif %}
{%- if grafana.ports | length > 0 %}
ports:
{%- for port in grafana.ports %}
# {{ port.description }}
- "{{ port.binding }}"
{%- endfor %}
{%- endif %}
environment:
- GF_SECURITY_ADMIN_USER=${GF_SECURITY_ADMIN_USER}
- GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD}
{%- if grafana.server_root_url %}
- GF_SERVER_ROOT_URL=${GF_SERVER_ROOT_URL}
{%- endif %}
volumes:
- ./storage/grafana/data:/var/lib/grafana
- ./storage/grafana/provisioning:/etc/grafana/provisioning:ro
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://localhost:3000/api/health"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
depends_on:
prometheus:
condition: service_healthy
{%- endif %}
{%- if mysql %}
mysql:
<<: *defaults
image: mysql:8.4
container_name: mysql
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
{%- if mysql.networks | length > 0 %}
networks:
{%- for network in mysql.networks %}
- {{ network }}
{%- endfor %}
{%- endif %}
# SECURITY: MySQL port is NOT exposed to the host/external network.
# - Only the tracker container can access MySQL via Docker's internal database_network
# - The healthcheck runs inside the container, so no external port is needed
# - This prevents unauthorized external access to the database
# See: https://github.com/torrust/torrust-tracker-deployer/issues/277
volumes:
- ./storage/mysql/data:/var/lib/mysql
command: --mysql-native-password=ON
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
{%- endif %}
{%- if backup %}
# Backup service for database and configuration backups
# Runs on-demand via "docker compose run --rm backup" (triggered by crontab)
# Uses profiles to prevent automatic startup on "docker compose up"
backup:
<<: *defaults
image: torrust/tracker-backup:latest
container_name: backup
restart: "no" # Override defaults - backup runs once and exits
profiles:
- backup # Only runs when explicitly invoked, not on "docker compose up"
{%- if backup.dependencies | length > 0 %}
depends_on:
{%- for dep in backup.dependencies %}
{{ dep.service }}:
condition: {{ dep.condition }}
{%- endfor %}
{%- endif %}
volumes:
# Backup configuration (sourceable by backup.sh)
- ./storage/backup/etc/backup.conf:/etc/backup/backup.conf:ro
- ./storage/backup/etc/backup-paths.txt:/etc/backup/backup-paths.txt:ro
# Mount storage read-only for config file backup
- ./storage:/data/storage:ro
# Mount backup output directory read-write
- ./storage/backup:/backups
{%- if backup.networks | length > 0 %}
networks:
{%- for network in backup.networks %}
- {{ network }}
{%- endfor %}
{%- endif %}
{%- endif %}
# Networks are derived from service configurations in Rust code.
# See: src/domain/topology/network.rs for security rationale.
{%- if required_networks | length > 0 %}
networks:
{%- for net in required_networks %}
# {{ net.description }}
{{ net.name }}:
driver: {{ net.driver }}
{%- endfor %}
{%- endif %}