-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
205 lines (199 loc) · 8.89 KB
/
Copy pathdocker-compose.yml
File metadata and controls
205 lines (199 loc) · 8.89 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
# The three database passwords use `:?` rather than a default on purpose. This
# repo is public and MySQL's port is published to the host, so a fallback value
# here would be a known password on a reachable database for every install that
# did not override it. Missing means the container refuses to start, which is
# noisy and fixable; a silent default is neither. install.sh and
# docker/scripts/prepare-build.sh generate all three into .env on first run.
services:
mysql:
image: mysql:8.0
container_name: teemops-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:?missing from .env; install.sh and docker/scripts/prepare-build.sh generate it}
MYSQL_DATABASE: ${MYSQL_DATABASE:-teemops}
MYSQL_USER: ${MYSQL_USER:-teem}
MYSQL_PASSWORD: ${MYSQL_PASSWORD:?missing from .env; install.sh and docker/scripts/prepare-build.sh generate it}
ports:
- "${MYSQL_PORT:-3306}:3306"
volumes:
- mysql-data:/var/lib/mysql
# Binary logging + durability settings the backup scheduler depends on.
# See docker/mysql/conf.d/10-teemops-backup.cnf and docs/backups.md.
- ./docker/mysql/conf.d:/etc/mysql/conf.d:ro
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:?missing from .env; install.sh and docker/scripts/prepare-build.sh generate it}"]
interval: 5s
timeout: 5s
retries: 10
start_period: 30s
command: --default-authentication-plugin=mysql_native_password
maildev:
image: maildev/maildev
container_name: teemops-maildev
restart: unless-stopped
ports:
- "8090:1080"
- "1025:1025"
logging:
driver: json-file
options:
max-size: 1m
app:
# Published image. Pin a release by setting TOPS_IMAGE_TAG in .env; roll back
# by setting it to a previous version and restarting. To build from your
# working tree instead, use install-build.sh (adds docker-compose.build.yml).
image: ${TOPS_IMAGE:-teem/tops}:${TOPS_IMAGE_TAG:-latest}
container_name: teemops-app
restart: unless-stopped
ports:
- "${APP_PORT:-8080}:80"
env_file:
- path: .env
required: false
- path: generated/teemops.env
required: false
environment:
APP_URL: ${APP_URL:-http://localhost:8080}
APP_ENV: ${APP_ENV:-local}
APP_DEBUG: ${APP_DEBUG:-true}
APP_KEY: ${APP_KEY:-}
DB_CONNECTION: mysql
DB_HOST: mysql
DB_PORT: "3306"
DB_DATABASE: ${MYSQL_DATABASE:-teemops}
DB_USERNAME: ${MYSQL_USER:-teem}
DB_PASSWORD: ${MYSQL_PASSWORD:?missing from .env; install.sh and docker/scripts/prepare-build.sh generate it}
LOG_CHANNEL: ${LOG_CHANNEL:-stderr}
# NOTE: QUEUE_CONNECTION / SCAN_QUEUE_CONNECTION / SCAN_REGION_QUEUE_CONNECTION
# are deliberately NOT set here. `environment:` overrides `env_file:`, so
# setting them would clobber the sqs-* values that generated/teemops.env
# provides after install.sh's AWS step, silently sending scan jobs to the database
# queue while the workers poll SQS. They come from env_file layering instead:
# .env (database, Phase 1) -> generated/teemops.env (sqs-*, from
# ./install.sh --aws-only).
MAIL_MAILER: smtp
MAIL_HOST: maildev
MAIL_PORT: "1025"
FIREBASE_USER_AUTH: ${FIREBASE_USER_AUTH:-false}
TOPS_DEPLOYMENT_REGION: ${TOPS_DEPLOYMENT_REGION:-}
AWS_DEFAULT_REGION: ${TOPS_DEPLOYMENT_REGION:-}
AWS_REGION: ${TOPS_DEPLOYMENT_REGION:-}
AWS_PROFILE: ${AWS_PROFILE:-default}
AWS_SDK_LOAD_CONFIG: "1"
AWS_SHARED_CREDENTIALS_FILE: /var/www/.aws/credentials
AWS_CONFIG_FILE: /var/www/.aws/config
volumes:
- app-storage:/var/www/html/storage
- ${HOME}/.aws:/var/www/.aws:ro
depends_on:
mysql:
condition: service_healthy
maildev:
condition: service_started
worker:
# Same image as `app`; only the entrypoint differs.
image: ${TOPS_IMAGE:-teem/tops}:${TOPS_IMAGE_TAG:-latest}
container_name: teemops-worker
restart: unless-stopped
env_file:
- path: .env
required: false
- path: generated/teemops.env
required: false
environment:
APP_ENV: ${APP_ENV:-local}
APP_KEY: ${APP_KEY:-}
DB_CONNECTION: mysql
DB_HOST: mysql
DB_PORT: "3306"
DB_DATABASE: ${MYSQL_DATABASE:-teemops}
DB_USERNAME: ${MYSQL_USER:-teem}
DB_PASSWORD: ${MYSQL_PASSWORD:?missing from .env; install.sh and docker/scripts/prepare-build.sh generate it}
LOG_CHANNEL: ${LOG_CHANNEL:-stderr}
# How many region-scan workers run in parallel. A full scan fans out to roughly
# 153 region jobs, so this is the number that decides how long a scan takes.
# Each process holds the AWS SDK (~60-120 MB) and one MySQL connection, so 5 costs
# about 0.6-0.8 GB. Raise it only with the memory and the AWS API rate limits to
# match — five concurrent workers against one account already raises throttling
# risk noticeably.
TOPS_WORKER_PROCESSES: ${TOPS_WORKER_PROCESSES:-5}
# See the note on the app service: these queue-connection vars must come
# from env_file layering, not `environment:`, or generated/teemops.env's
# sqs-* values get overridden and jobs are dispatched to the wrong queue.
FIREBASE_USER_AUTH: ${FIREBASE_USER_AUTH:-false}
TOPS_DEPLOYMENT_REGION: ${TOPS_DEPLOYMENT_REGION:-}
AWS_DEFAULT_REGION: ${TOPS_DEPLOYMENT_REGION:-}
AWS_REGION: ${TOPS_DEPLOYMENT_REGION:-}
AWS_PROFILE: ${AWS_PROFILE:-default}
AWS_SDK_LOAD_CONFIG: "1"
AWS_SHARED_CREDENTIALS_FILE: /var/www/.aws/credentials
AWS_CONFIG_FILE: /var/www/.aws/config
entrypoint: ["/usr/local/bin/worker-entrypoint.sh"]
volumes:
- app-storage:/var/www/html/storage
- ${HOME}/.aws:/var/www/.aws:ro
depends_on:
app:
condition: service_started
# Database backup scheduler: daily full, hourly differential, 15-minute
# binary log archive. See docs/backups.md and ./backup.sh.
backup:
image: ${TOPS_BACKUP_IMAGE:-teem/tops-backup}:${TOPS_IMAGE_TAG:-latest}
container_name: teemops-backup
restart: unless-stopped
environment:
DB_HOST: mysql
DB_PORT: "3306"
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:?missing from .env; install.sh and docker/scripts/prepare-build.sh generate it}
TOPS_BACKUP_USER: ${TOPS_BACKUP_USER:-tops_backup}
TOPS_BACKUP_PASSWORD: ${TOPS_BACKUP_PASSWORD:?missing from .env; install.sh and docker/scripts/prepare-build.sh generate it}
# Drives both the cron schedule and the backup directory names, so "5pm"
# means 5pm where you are rather than 5pm UTC.
TZ: ${TOPS_BACKUP_TZ:-UTC}
TOPS_BACKUP_FULL_CRON: ${TOPS_BACKUP_FULL_CRON:-0 17 * * *}
TOPS_BACKUP_DIFF_CRON: ${TOPS_BACKUP_DIFF_CRON:-10 * * * *}
TOPS_BACKUP_BINLOG_CRON: ${TOPS_BACKUP_BINLOG_CRON:-*/15 * * * *}
TOPS_BACKUP_PRUNE_CRON: ${TOPS_BACKUP_PRUNE_CRON:-30 3 * * *}
TOPS_BACKUP_FULL_RETENTION_DAYS: ${TOPS_BACKUP_FULL_RETENTION_DAYS:-7}
TOPS_BACKUP_BINLOG_RETENTION_DAYS: ${TOPS_BACKUP_BINLOG_RETENTION_DAYS:-14}
# Finished backups are chowned to this uid:gid so the host user owns
# ~/.tops/backups. install.sh fills these in from `id -u` / `id -g`.
TOPS_BACKUP_UID: ${TOPS_BACKUP_UID:-1000}
TOPS_BACKUP_GID: ${TOPS_BACKUP_GID:-1000}
volumes:
# Read-only: the scheduler only ever reads the live datadir. The restore
# service below is the one that gets write access, and it only runs
# while MySQL is stopped.
- mysql-data:/var/lib/mysql:ro
- ${TOPS_BACKUP_DIR:-${HOME}/.tops/backups}:/backups
depends_on:
mysql:
condition: service_healthy
logging:
driver: json-file
options:
max-size: 10m
# Same image, write access to the datadir, and never started automatically.
# `./backup.sh restore` runs it with `docker compose run --rm` while MySQL is
# stopped. Keeping it behind a profile means a stray `docker compose up`
# cannot bring up something that is able to overwrite the database.
db-restore:
image: ${TOPS_BACKUP_IMAGE:-teem/tops-backup}:${TOPS_IMAGE_TAG:-latest}
profiles: ["restore"]
environment:
DB_HOST: mysql
DB_PORT: "3306"
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:?missing from .env; install.sh and docker/scripts/prepare-build.sh generate it}
TOPS_BACKUP_USER: ${TOPS_BACKUP_USER:-tops_backup}
TOPS_BACKUP_PASSWORD: ${TOPS_BACKUP_PASSWORD:?missing from .env; install.sh and docker/scripts/prepare-build.sh generate it}
TZ: ${TOPS_BACKUP_TZ:-UTC}
TOPS_BACKUP_UID: ${TOPS_BACKUP_UID:-1000}
TOPS_BACKUP_GID: ${TOPS_BACKUP_GID:-1000}
volumes:
- mysql-data:/var/lib/mysql
- ${TOPS_BACKUP_DIR:-${HOME}/.tops/backups}:/backups
entrypoint: ["/usr/local/bin/entrypoint.sh", "restore"]
volumes:
mysql-data:
app-storage: