-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdocker-compose.yml.tera
More file actions
204 lines (195 loc) · 6.55 KB
/
Copy pathdocker-compose.yml.tera
File metadata and controls
204 lines (195 loc) · 6.55 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
# Docker Compose configuration for Torrust Tracker deployment
# 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
networks:
{%- for network in caddy.networks %}
- {{ network }}
{%- endfor %}
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}
networks:
{%- for network in tracker.networks %}
- {{ network }}
{%- endfor %}
{%- 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
networks:
{%- for network in prometheus.networks %}
- {{ network }}
{%- endfor %}
{%- 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
networks:
{%- for network in grafana.networks %}
- {{ network }}
{%- endfor %}
{%- 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}
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}
networks:
{%- for network in mysql.networks %}
- {{ network }}
{%- endfor %}
# 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 %}
# 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 %}