Repository navigation
Expand file tree
/
Copy pathcompose.yaml
More file actions
134 lines (126 loc) · 4.84 KB
/
Copy pathcompose.yaml
File metadata and controls
134 lines (126 loc) · 4.84 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
# Run with: docker compose --env-file secrets.env ...
# Each service names only the secrets it needs; never use `env_file: secrets.env`.
# Every secret is required (`:?`), so a missing value stops compose instead of starting with a blank one.
name: discosticker
x-bucket: &bucket stickers
services:
postgres:
image: postgres:18.6-alpine
environment:
POSTGRES_USER: discosticker
POSTGRES_DB: discosticker
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in secrets.env}
volumes:
# Postgres 18+ declares its VOLUME here; PGDATA is /var/lib/postgresql/18/docker.
- postgres-data:/var/lib/postgresql
networks: [backend]
healthcheck:
test: ["CMD", "pg_isready", "-U", "discosticker", "-d", "discosticker"]
interval: 5s
timeout: 3s
retries: 20
seaweedfs:
image: chrislusf/seaweedfs:4.48
# Same image tag and flags as TestcontainersConfiguration in api/src/test; keep the two in sync.
command: >-
mini -dir=/data -webdav=false -admin.ui=false -master.telemetry=false
-s3.port.iceberg=0 -s3.port.lance=0 -s3.autoCreateBucket=false
environment:
AWS_ACCESS_KEY_ID: ${S3_ACCESS_KEY:?set S3_ACCESS_KEY in secrets.env}
AWS_SECRET_ACCESS_KEY: ${S3_SECRET_KEY:?set S3_SECRET_KEY in secrets.env}
volumes:
- seaweedfs-data:/data
networks: [backend]
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:8333/healthz"]
interval: 5s
timeout: 3s
retries: 20
# One-shot: creates the bucket through the S3 API (proving the keys work), then exits.
# Safe to re-run: an existing bucket passes head-bucket.
bucket-init:
image: amazon/aws-cli:2.37.12
entrypoint: ["sh", "-c"]
command:
- |
for i in $$(seq 1 30); do
if aws s3api head-bucket --bucket "$$BUCKET" --endpoint-url http://seaweedfs:8333 >/dev/null 2>&1 ||
aws s3api create-bucket --bucket "$$BUCKET" --endpoint-url http://seaweedfs:8333 >/dev/null; then
echo "bucket $$BUCKET ready"
exit 0
fi
sleep 2
done
echo "bucket $$BUCKET not ready after 30 attempts" >&2
exit 1
environment:
BUCKET: *bucket
AWS_REGION: us-east-1
AWS_ACCESS_KEY_ID: ${S3_ACCESS_KEY:?set S3_ACCESS_KEY in secrets.env}
AWS_SECRET_ACCESS_KEY: ${S3_SECRET_KEY:?set S3_SECRET_KEY in secrets.env}
networks: [backend]
depends_on:
seaweedfs:
condition: service_healthy
api:
build: api
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/discosticker
SPRING_DATASOURCE_USERNAME: discosticker
SPRING_DATASOURCE_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in secrets.env}
APP_S3_ENDPOINT: http://seaweedfs:8333
APP_S3_REGION: us-east-1
APP_S3_BUCKET: *bucket
APP_S3_PATH_STYLE_ACCESS: "true"
APP_S3_ACCESS_KEY: ${S3_ACCESS_KEY:?set S3_ACCESS_KEY in secrets.env}
APP_S3_SECRET_KEY: ${S3_SECRET_KEY:?set S3_SECRET_KEY in secrets.env}
# The client ID is public (it's in every authorize URL). This is the dev application's;
# compose.prod.yaml overrides it with the production application's.
DISCORD_CLIENT_ID: "1558633255404699710"
DISCORD_CLIENT_SECRET: ${DISCORD_CLIENT_SECRET:?set DISCORD_CLIENT_SECRET in secrets.env}
# Multipart parts are written here, on the tmpfs below.
SPRING_SERVLET_MULTIPART_LOCATION: /tmp
# Upload originals never reach a persistent disk: Tomcat's multipart temp files (and any
# other JVM temp file) live in memory, capped at 128m, and are deleted when the request ends.
tmpfs:
- /tmp:size=128m
networks: [edge, backend]
depends_on:
postgres:
condition: service_healthy
bucket-init:
condition: service_completed_successfully
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:8080/api/health | grep -q UP"]
interval: 5s
timeout: 3s
retries: 30
start_period: 30s
gateway:
build:
context: .
dockerfile: gateway/Dockerfile
# The only published port, bound to loopback.
ports:
- "127.0.0.1:8080:8080"
# Upload originals never reach a persistent disk: request bodies larger than nginx's
# in-memory buffer go to its compiled-in client-body temp path, which is memory, capped at 128m.
tmpfs:
- /var/cache/nginx/client_temp:size=128m
networks: [edge]
depends_on:
api:
condition: service_healthy
healthcheck:
# 127.0.0.1, not localhost: localhost resolves to ::1 first and nginx listens on IPv4 only.
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8080/ >/dev/null"]
interval: 5s
timeout: 3s
retries: 10
# The gateway is only on edge, so it can't reach postgres or seaweedfs.
networks:
edge:
backend:
volumes:
postgres-data:
seaweedfs-data: