-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
144 lines (140 loc) · 5.91 KB
/
Copy pathdocker-compose.yml
File metadata and controls
144 lines (140 loc) · 5.91 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
services:
postgres:
# PostgreSQL 16 + TimescaleDB. The image is PG16-compatible, so the existing
# pgdata volume mounts unchanged — only the telemetry hypertable is Timescale-
# managed; authoritative tables stay plain Postgres. The command override sets
# shared_preload_libraries so `CREATE EXTENSION timescaledb` can load even on a
# pre-existing volume (the image's auto-tune only runs on a fresh data dir).
image: timescale/timescaledb:2.17.2-pg16
command: ['postgres', '-c', 'shared_preload_libraries=timescaledb']
ports:
- '5432:5432'
environment:
POSTGRES_USER: hashhive
POSTGRES_PASSWORD: hashhive
POSTGRES_DB: hashhive
volumes:
- pgdata:/var/lib/postgresql/data
- ./docker/postgres/init-timescaledb.sql:/docker-entrypoint-initdb.d/init-timescaledb.sql:ro
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U hashhive']
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- '6379:6379'
volumes:
- redisdata:/data
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 5s
timeout: 5s
retries: 5
# Object storage. SeaweedFS replaces MinIO (MinIO upstream archived 2026-04-25;
# SeaweedFS is Apache-2.0 and the consensus OSS replacement). The S3 API surface
# is identical from the application's perspective -- @aws-sdk/client-s3 with
# `forcePathStyle: true` works against either.
#
# Port mapping: host 9000 -> container 8333 so existing developer `.env` files
# pointing at `S3_ENDPOINT=http://localhost:9000` keep working unchanged.
# Host 9333 exposes the SeaweedFS master HTTP UI (replaces the MinIO console).
seaweedfs:
image: chrislusf/seaweedfs:4.27
ports:
- '9000:8333' # S3 API (container 8333 mapped to host 9000)
- '127.0.0.1:9333:9333' # Master HTTP UI / admin (bound to loopback;
# the master `/cluster/status` page is
# unauthenticated so we keep it off the LAN)
volumes:
- seaweedfsdata:/data
- ./docker/seaweedfs/s3-iam.json:/etc/seaweedfs/s3.json:ro
command: >-
server
-s3
-s3.config=/etc/seaweedfs/s3.json
-dir=/data
healthcheck:
# SeaweedFS 4.27 binds the master HTTP UI (port 9333) to the
# container's docker-network interface, NOT to 0.0.0.0 or
# 127.0.0.1, so an in-container probe on `localhost:9333` always
# gets connection-refused even though the master is up and the
# host port-forward works. (Alpine's `localhost` resolves to ::1
# first too; IPv6 isn't bound either.) The S3 API on 8333 is
# bound to 127.0.0.1 and responds 403 to anonymous GET — that's
# the contract the bucket-init sidecar actually needs. `curl -sS`
# (no `-f`) treats any HTTP response as success, so this probe
# goes green as soon as the S3 server is accepting connections.
test: ['CMD-SHELL', 'curl -sS -o /dev/null --max-time 3 http://127.0.0.1:8333/ || exit 1']
interval: 5s
timeout: 5s
retries: 10
start_period: 5s
# One-shot sidecar that creates the configured bucket on first boot.
# SeaweedFS does not auto-create buckets from credentials the way MinIO did,
# so this container runs `aws s3 mb` against the SeaweedFS S3 endpoint and
# exits. `set -e` propagates any failure so retry-exhaustion or auth errors
# exit non-zero rather than silently masking with a "bucket ready" log.
# Re-runs are idempotent: a `BucketAlready*` error is treated as success.
bucket-init:
image: amazon/aws-cli:2.27.8
restart: 'no'
depends_on:
seaweedfs:
condition: service_healthy
environment:
# Default to the dev IAM credentials but honor an operator override
# from `.env` so credential-rotation testing works without editing
# the compose file. Mirrors the prod compose pattern.
AWS_ACCESS_KEY_ID: ${S3_ACCESS_KEY:-minioadmin}
AWS_SECRET_ACCESS_KEY: ${S3_SECRET_KEY:-minioadmin}
AWS_DEFAULT_REGION: us-east-1
BUCKET: ${S3_BUCKET:-hashhive}
entrypoint:
- /bin/sh
- -ec
- |
# Probe loop captures stderr so we can fast-fail on auth errors
# (config drift between bucket-init and the SeaweedFS IAM file)
# within a few seconds instead of timing out after 60s.
ready=0
last_err=""
for i in $$(seq 1 30); do
if err=$$(aws --cli-connect-timeout 3 --endpoint-url http://seaweedfs:8333 s3 ls 2>&1 >/dev/null); then
ready=1
break
fi
last_err="$$err"
case "$$err" in
*InvalidAccessKeyId*|*SignatureDoesNotMatch*|*AccessDenied*)
echo "bucket-init: auth error from seaweedfs — IAM config (docker/seaweedfs/s3-iam.json) likely out of sync with AWS_ACCESS_KEY_ID. Aborting." >&2
echo "bucket-init: stderr was: $$err" >&2
exit 1
;;
esac
echo "bucket-init: waiting for seaweedfs s3 endpoint... ($$i/30)"
sleep 2
done
if [ "$$ready" -ne 1 ]; then
echo "bucket-init: seaweedfs s3 endpoint did not become ready within 60s; last_err: $$last_err" >&2
exit 1
fi
# Idempotent-success markers across AWS S3 and SeaweedFS variants.
mb_out=$$(aws --endpoint-url http://seaweedfs:8333 s3 mb "s3://$$BUCKET" 2>&1) || mb_status=$$? && mb_status=$${mb_status:-0}
if [ "$$mb_status" -ne 0 ]; then
case "$$mb_out" in
*BucketAlreadyOwnedByYou*|*BucketAlreadyExists*|*"bucket already exists"*|*"already exists"*)
echo "bucket-init: bucket $$BUCKET already exists (idempotent re-run)"
;;
*)
echo "bucket-init: failed to create bucket $$BUCKET (exit=$$mb_status): $$mb_out" >&2
exit 1
;;
esac
fi
echo "bucket-init: bucket $$BUCKET ready"
volumes:
pgdata:
redisdata:
seaweedfsdata: