Docker: PocketBase with media in S3, SeaweedFS or split SeaweedFS
Six compose files for the separate-container setup, a build and a prod file for each, modelled on DriverVault's Docker folder: - pocketbase.s3: media in an existing bucket elsewhere; the endpoint and key pair are required, host.docker.internal is mapped, and the homeserver waits up to 30 seconds for the endpoint before starting. - pocketbase.seaweedfs: SeaweedFS as one `weed server -s3` container whose only identity is the homeserver's key pair, plus a one-shot init that creates the bucket. - pocketbase.seaweedfs.split: master, volume, filer, S3 gateway and admin UI as separate containers; the init seeds the bucket and the homeserver's identity into the filer's IAM store, and the gateway waits for it. Only the S3 gateway and admin UI are published, on loopback. Both SeaweedFS files share one project and data layout, so switching needs no migration. .env.example gains the SEAWEED_* settings and leaves WARP_PB_S3_FORCE_PATH_STYLE empty so the S3 file's default applies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
332916e9db
commit
39583a9db0
8 files changed
+1011
-1
No files matched your search
+36
-1
@@ -31,6 +31,31 @@ WARP_VERSION=latest
|
||||
# refuses to start without it.
|
||||
WARP_POSTGRES_PASSWORD=change-me
|
||||
|
||||
# ------------------------------------------------------------- seaweedfs
|
||||
|
||||
# docker-compose.pocketbase.seaweedfs*.yml only; set WARP_PB_S3_ACCESS_KEY
|
||||
# and WARP_PB_S3_SECRET below as well.
|
||||
#
|
||||
# The SeaweedFS image every SeaweedFS container runs. Pin it: the data
|
||||
# volume outlives the image.
|
||||
SEAWEED_IMAGE=chrislusf/seaweedfs:4.45
|
||||
|
||||
# The S3 gateway's host port, on loopback unless the bind address says
|
||||
# otherwise. The homeserver reaches it over the compose network; this is
|
||||
# for aws-cli and the like.
|
||||
SEAWEED_S3_BIND=127.0.0.1
|
||||
SEAWEED_S3_PORT=8333
|
||||
|
||||
# The split file only: SeaweedFS's admin UI. It can mint credentials for
|
||||
# the bucket, so the password is required. Put it behind a reverse proxy
|
||||
# before binding it to 0.0.0.0. The read-only login is optional.
|
||||
SEAWEED_ADMIN_BIND=127.0.0.1
|
||||
SEAWEED_ADMIN_PORT=23646
|
||||
SEAWEED_ADMIN_USER=admin
|
||||
SEAWEED_ADMIN_PASSWORD=
|
||||
SEAWEED_ADMIN_READONLY_USER=
|
||||
SEAWEED_ADMIN_READONLY_PASSWORD=
|
||||
|
||||
# ------------------------------------------------------------ homeserver
|
||||
|
||||
# Part of every user and room ID: it cannot be changed later.
|
||||
@@ -87,13 +112,23 @@ WARP_DB_AUTO_MIGRATE=
|
||||
# docker-compose.pocketbase*.yml only: keep media in an S3 bucket instead
|
||||
# of pb_data/storage. Bucket, region, endpoint and keys are all required
|
||||
# when it is on.
|
||||
#
|
||||
# The pocketbase.seaweedfs files turn it on themselves, against their own
|
||||
# SeaweedFS; there only the access key and secret are needed (required:
|
||||
# they are the gateway's credentials too), and the bucket defaults to warp.
|
||||
#
|
||||
# The pocketbase.s3 files turn it on against a bucket elsewhere: the
|
||||
# endpoint, access key and secret are required, the bucket (default warp)
|
||||
# must exist, the region defaults to us-east-1 and path style to true
|
||||
# (SeaweedFS, MinIO; set false for AWS S3). For a gateway on the Docker
|
||||
# host, use http://host.docker.internal:8333.
|
||||
WARP_PB_S3_ENABLED=false
|
||||
WARP_PB_S3_BUCKET=
|
||||
WARP_PB_S3_REGION=
|
||||
WARP_PB_S3_ENDPOINT=
|
||||
WARP_PB_S3_ACCESS_KEY=
|
||||
WARP_PB_S3_SECRET=
|
||||
WARP_PB_S3_FORCE_PATH_STYLE=false
|
||||
WARP_PB_S3_FORCE_PATH_STYLE=
|
||||
|
||||
# Client API. Defaults *, false, 0s (never expire), 0s, true.
|
||||
WARP_CORS_ALLOWED_ORIGINS=
|
||||
|
||||
@@ -9,6 +9,9 @@ The homeserver (`warp`), the admin panel (`warp-admin`) and the web client
|
||||
| `docker-compose.sqlite.yml` | SQLite, in the `warp-data` volume | built here |
|
||||
| `docker-compose.pocketbase.yml` | PocketBase, embedded in the homeserver, in `warp-data` | built here |
|
||||
| `docker-compose.postgresql.yml` | PostgreSQL 17, its own container | built here |
|
||||
| `docker-compose.pocketbase.s3.yml` | PocketBase, media in an existing S3 bucket elsewhere | built here |
|
||||
| `docker-compose.pocketbase.seaweedfs.yml` | PocketBase, media in SeaweedFS, one container | built here |
|
||||
| `docker-compose.pocketbase.seaweedfs.split.yml` | PocketBase, media in SeaweedFS, one container per role, with its admin UI | built here |
|
||||
| `docker-compose.*.prod.yml` | as above | pulled, never built |
|
||||
|
||||
```sh
|
||||
@@ -26,6 +29,39 @@ TLS-terminating reverse proxy in front before exposing them; see
|
||||
PocketBase is a database driver inside the homeserver, not a separate
|
||||
server, so the PocketBase files have no PocketBase container.
|
||||
|
||||
## Media in S3
|
||||
|
||||
The three `pocketbase.s3` and `pocketbase.seaweedfs` setups keep the
|
||||
PocketBase database in `/data/pb_data` and put media in an S3 bucket
|
||||
(`WARP_PB_S3_BUCKET`, default `warp`). Media already stored on the
|
||||
filesystem is not moved into the bucket when S3 is turned on, so start
|
||||
these on a fresh `warp-data` or copy the files across first.
|
||||
|
||||
- **`docker-compose.pocketbase.s3.yml`**: a bucket that already exists
|
||||
elsewhere (AWS, MinIO, a SeaweedFS on another host). Set
|
||||
`WARP_PB_S3_ENDPOINT`, `WARP_PB_S3_ACCESS_KEY` and `WARP_PB_S3_SECRET`.
|
||||
Path style is on by default; set `WARP_PB_S3_FORCE_PATH_STYLE=false` for
|
||||
AWS S3. `http://host.docker.internal:8333` reaches a gateway on the
|
||||
Docker host. The homeserver waits up to 30 seconds for the endpoint to
|
||||
answer before it starts.
|
||||
- **`docker-compose.pocketbase.seaweedfs.yml`**: SeaweedFS as one
|
||||
`weed server -s3` container, plus a one-shot `seaweedfs-init` that
|
||||
creates the bucket. The gateway's one identity is the homeserver's key
|
||||
pair, `WARP_PB_S3_ACCESS_KEY` and `WARP_PB_S3_SECRET`.
|
||||
- **`docker-compose.pocketbase.seaweedfs.split.yml`**: master, volume,
|
||||
filer, S3 gateway and admin UI (port 23646) as separate containers.
|
||||
`seaweedfs-init` writes the homeserver's identity into the filer's IAM
|
||||
store on every start, the store the admin UI writes too, so keys added
|
||||
under *Object Store → Users* never displace it; the gateway does not
|
||||
start until that identity is there. Set `SEAWEED_ADMIN_PASSWORD` as well.
|
||||
|
||||
The S3 gateway and the admin UI are published on 127.0.0.1 only
|
||||
(`SEAWEED_S3_BIND`, `SEAWEED_ADMIN_BIND`); master, volume and filer are not
|
||||
published, since the volume server serves content by id with no
|
||||
authentication. Both SeaweedFS files share a project and the
|
||||
`seaweed-data` layout, so switching between them needs no migration.
|
||||
`SEAWEED_IMAGE` pins the SeaweedFS release (4.45).
|
||||
|
||||
## Prod files
|
||||
|
||||
The `.prod.yml` files pull `$WARP_REGISTRY/warp`, `warp-admin` and
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
# Warp on PocketBase with media in an S3 bucket elsewhere: the homeserver,
|
||||
# the admin panel and the web client, each in its own container, pulled
|
||||
# from a registry.
|
||||
#
|
||||
# cd Docker
|
||||
# cp .env.example .env # then edit it; set WARP_PB_S3_ENDPOINT,
|
||||
# # WARP_PB_S3_ACCESS_KEY and WARP_PB_S3_SECRET
|
||||
# docker compose -f docker-compose.pocketbase.s3.prod.yml up -d
|
||||
#
|
||||
# The database stays in /data/pb_data (warp-data); media goes to the bucket
|
||||
# WARP_PB_S3_BUCKET (default warp) on WARP_PB_S3_ENDPOINT, which must already
|
||||
# exist: nothing here runs a gateway or creates the bucket. For a gateway on
|
||||
# this Docker host, use http://host.docker.internal:8333; the host entry below
|
||||
# makes that name resolve. For a SeaweedFS that comes up with the stack, see
|
||||
# docker-compose.pocketbase.seaweedfs.yml. Media stored before S3 was on is
|
||||
# not moved into the bucket.
|
||||
#
|
||||
# Homeserver http://localhost:8008, admin panel http://localhost:8009, web
|
||||
# client http://localhost:8080.
|
||||
#
|
||||
# Create the first administrator once the server is up:
|
||||
#
|
||||
# docker compose -f docker-compose.pocketbase.s3.prod.yml exec warp warp create-account --username admin --admin
|
||||
#
|
||||
# Nothing is built here: the homeserver, admin panel and web client images
|
||||
# come from WARP_REGISTRY (default ghcr.io/dariuszjaniak) at tag
|
||||
# WARP_VERSION (default latest). Pin WARP_VERSION to a release in
|
||||
# production, and update with
|
||||
#
|
||||
# docker compose -f docker-compose.pocketbase.s3.prod.yml pull && docker compose -f docker-compose.pocketbase.s3.prod.yml up -d
|
||||
|
||||
name: warp-pocketbase-s3
|
||||
|
||||
services:
|
||||
warp:
|
||||
image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp:${WARP_VERSION:-latest}
|
||||
pull_policy: always
|
||||
restart: unless-stopped
|
||||
extra_hosts:
|
||||
# Lets WARP_PB_S3_ENDPOINT name the Docker host as host.docker.internal.
|
||||
- "host.docker.internal:host-gateway"
|
||||
# The homeserver does not check the endpoint at startup and would only
|
||||
# fail on the first upload, so wait up to 30 seconds for it to answer at
|
||||
# all (any HTTP status). The signing key is created on first start and
|
||||
# kept in the volume: losing it means other servers no longer recognise
|
||||
# this one.
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command:
|
||||
- >-
|
||||
i=0; until curl -s -o /dev/null --max-time 5 "$$WARP_PB_S3_ENDPOINT"; do
|
||||
i=$$((i + 1)); if [ "$$i" -ge 30 ]; then echo "S3 endpoint $$WARP_PB_S3_ENDPOINT does not answer" >&2; exit 1; fi;
|
||||
echo "waiting for S3 endpoint $$WARP_PB_S3_ENDPOINT" >&2; sleep 1; done;
|
||||
test -f /data/signing.key || warp generate-keys --output /data/signing.key; exec warp serve
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_DB_DRIVER: pocketbase
|
||||
WARP_DB_CONNECTION_STRING: /data/pb_data
|
||||
WARP_PB_S3_ENABLED: "true"
|
||||
WARP_PB_S3_ENDPOINT: ${WARP_PB_S3_ENDPOINT:?set WARP_PB_S3_ENDPOINT in .env}
|
||||
WARP_PB_S3_BUCKET: ${WARP_PB_S3_BUCKET:-warp}
|
||||
# SeaweedFS and MinIO ignore the region; the client insists on one.
|
||||
WARP_PB_S3_REGION: ${WARP_PB_S3_REGION:-us-east-1}
|
||||
WARP_PB_S3_ACCESS_KEY: ${WARP_PB_S3_ACCESS_KEY:?set WARP_PB_S3_ACCESS_KEY in .env}
|
||||
WARP_PB_S3_SECRET: ${WARP_PB_S3_SECRET:?set WARP_PB_S3_SECRET in .env}
|
||||
# true for SeaweedFS and MinIO, false for AWS S3 proper.
|
||||
WARP_PB_S3_FORCE_PATH_STYLE: ${WARP_PB_S3_FORCE_PATH_STYLE:-true}
|
||||
volumes:
|
||||
- warp-data:/data
|
||||
ports:
|
||||
- "${WARP_PORT:-8008}:8008"
|
||||
|
||||
admin:
|
||||
image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp-admin:${WARP_VERSION:-latest}
|
||||
pull_policy: always
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- warp
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_ADMIN_HOMESERVER: http://warp:8008
|
||||
ports:
|
||||
- "${WARP_ADMIN_PORT:-8009}:8009"
|
||||
|
||||
web:
|
||||
image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp-web:${WARP_VERSION:-latest}
|
||||
pull_policy: always
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- warp
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_WEB_HOMESERVER: http://warp:8008
|
||||
ports:
|
||||
- "${WARP_WEB_PORT:-8080}:8080"
|
||||
|
||||
volumes:
|
||||
warp-data:
|
||||
@@ -0,0 +1,96 @@
|
||||
# Warp on PocketBase with media in an S3 bucket elsewhere: the homeserver,
|
||||
# the admin panel and the web client, each in its own container, built from
|
||||
# this checkout.
|
||||
#
|
||||
# cd Docker
|
||||
# cp .env.example .env # then edit it; set WARP_PB_S3_ENDPOINT,
|
||||
# # WARP_PB_S3_ACCESS_KEY and WARP_PB_S3_SECRET
|
||||
# docker compose -f docker-compose.pocketbase.s3.yml up -d --build
|
||||
#
|
||||
# The database stays in /data/pb_data (warp-data); media goes to the bucket
|
||||
# WARP_PB_S3_BUCKET (default warp) on WARP_PB_S3_ENDPOINT, which must already
|
||||
# exist: nothing here runs a gateway or creates the bucket. For a gateway on
|
||||
# this Docker host, use http://host.docker.internal:8333; the host entry below
|
||||
# makes that name resolve. For a SeaweedFS that comes up with the stack, see
|
||||
# docker-compose.pocketbase.seaweedfs.yml. Media stored before S3 was on is
|
||||
# not moved into the bucket.
|
||||
#
|
||||
# Homeserver http://localhost:8008, admin panel http://localhost:8009, web
|
||||
# client http://localhost:8080.
|
||||
#
|
||||
# Create the first administrator once the server is up:
|
||||
#
|
||||
# docker compose -f docker-compose.pocketbase.s3.yml exec warp warp create-account --username admin --admin
|
||||
|
||||
name: warp-pocketbase-s3
|
||||
|
||||
services:
|
||||
warp:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: Dockerfile
|
||||
image: warp:latest
|
||||
restart: unless-stopped
|
||||
extra_hosts:
|
||||
# Lets WARP_PB_S3_ENDPOINT name the Docker host as host.docker.internal.
|
||||
- "host.docker.internal:host-gateway"
|
||||
# The homeserver does not check the endpoint at startup and would only
|
||||
# fail on the first upload, so wait up to 30 seconds for it to answer at
|
||||
# all (any HTTP status). The signing key is created on first start and
|
||||
# kept in the volume: losing it means other servers no longer recognise
|
||||
# this one.
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command:
|
||||
- >-
|
||||
i=0; until curl -s -o /dev/null --max-time 5 "$$WARP_PB_S3_ENDPOINT"; do
|
||||
i=$$((i + 1)); if [ "$$i" -ge 30 ]; then echo "S3 endpoint $$WARP_PB_S3_ENDPOINT does not answer" >&2; exit 1; fi;
|
||||
echo "waiting for S3 endpoint $$WARP_PB_S3_ENDPOINT" >&2; sleep 1; done;
|
||||
test -f /data/signing.key || warp generate-keys --output /data/signing.key; exec warp serve
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_DB_DRIVER: pocketbase
|
||||
WARP_DB_CONNECTION_STRING: /data/pb_data
|
||||
WARP_PB_S3_ENABLED: "true"
|
||||
WARP_PB_S3_ENDPOINT: ${WARP_PB_S3_ENDPOINT:?set WARP_PB_S3_ENDPOINT in .env}
|
||||
WARP_PB_S3_BUCKET: ${WARP_PB_S3_BUCKET:-warp}
|
||||
# SeaweedFS and MinIO ignore the region; the client insists on one.
|
||||
WARP_PB_S3_REGION: ${WARP_PB_S3_REGION:-us-east-1}
|
||||
WARP_PB_S3_ACCESS_KEY: ${WARP_PB_S3_ACCESS_KEY:?set WARP_PB_S3_ACCESS_KEY in .env}
|
||||
WARP_PB_S3_SECRET: ${WARP_PB_S3_SECRET:?set WARP_PB_S3_SECRET in .env}
|
||||
# true for SeaweedFS and MinIO, false for AWS S3 proper.
|
||||
WARP_PB_S3_FORCE_PATH_STYLE: ${WARP_PB_S3_FORCE_PATH_STYLE:-true}
|
||||
volumes:
|
||||
- warp-data:/data
|
||||
ports:
|
||||
- "${WARP_PORT:-8008}:8008"
|
||||
|
||||
admin:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: apps/admin/Dockerfile
|
||||
image: warp-admin:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- warp
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_ADMIN_HOMESERVER: http://warp:8008
|
||||
ports:
|
||||
- "${WARP_ADMIN_PORT:-8009}:8009"
|
||||
|
||||
web:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: apps/web/Dockerfile
|
||||
image: warp-web:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- warp
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_WEB_HOMESERVER: http://warp:8008
|
||||
ports:
|
||||
- "${WARP_WEB_PORT:-8080}:8080"
|
||||
|
||||
volumes:
|
||||
warp-data:
|
||||
@@ -0,0 +1,134 @@
|
||||
# Warp on PocketBase with media in SeaweedFS: the homeserver, the admin panel
|
||||
# and the web client pulled from a registry, plus SeaweedFS as one
|
||||
# container (`weed server -s3`: master, volume, filer and S3 gateway in one
|
||||
# process).
|
||||
#
|
||||
# cd Docker
|
||||
# cp .env.example .env # then edit it; set WARP_PB_S3_ACCESS_KEY
|
||||
# # and WARP_PB_S3_SECRET
|
||||
# docker compose -f docker-compose.pocketbase.seaweedfs.prod.yml up -d
|
||||
#
|
||||
# The database stays in /data/pb_data (warp-data); media goes to the bucket
|
||||
# WARP_PB_S3_BUCKET (default warp) in SeaweedFS (seaweed-data), whose gateway
|
||||
# has exactly one identity: the homeserver's. For SeaweedFS's admin UI and
|
||||
# per-role containers, see docker-compose.pocketbase.seaweedfs.split.yml.
|
||||
# Media stored before S3 was on is not moved into the bucket.
|
||||
#
|
||||
# Homeserver http://localhost:8008, admin panel http://localhost:8009, web
|
||||
# client http://localhost:8080. The S3 gateway (8333) is published on
|
||||
# loopback, for aws-cli and the like; SEAWEED_S3_BIND=0.0.0.0 exposes it.
|
||||
#
|
||||
# This file shares its project and volumes with
|
||||
# docker-compose.pocketbase.seaweedfs.split.yml: SeaweedFS's data has the
|
||||
# same layout either way, so switching between the two needs no migration.
|
||||
#
|
||||
# Create the first administrator once the server is up:
|
||||
#
|
||||
# docker compose -f docker-compose.pocketbase.seaweedfs.prod.yml exec warp warp create-account --username admin --admin
|
||||
#
|
||||
# Nothing is built here: the homeserver, admin panel and web client images
|
||||
# come from WARP_REGISTRY (default ghcr.io/dariuszjaniak) at tag
|
||||
# WARP_VERSION (default latest), and SeaweedFS from SEAWEED_IMAGE. Pin
|
||||
# WARP_VERSION to a release in production, and update with
|
||||
#
|
||||
# docker compose -f docker-compose.pocketbase.seaweedfs.prod.yml pull && docker compose -f docker-compose.pocketbase.seaweedfs.prod.yml up -d
|
||||
|
||||
name: warp-pocketbase-seaweedfs
|
||||
|
||||
services:
|
||||
seaweedfs:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: unless-stopped
|
||||
command: server -dir=/data -s3 -volume.max=0 -master.volumeSizeLimitMB=1024
|
||||
environment:
|
||||
# With no -s3.config, the gateway takes its single identity from these,
|
||||
# which is also what takes it out of its allow-anyone default. The same
|
||||
# pair the homeserver signs with.
|
||||
AWS_ACCESS_KEY_ID: ${WARP_PB_S3_ACCESS_KEY:?set WARP_PB_S3_ACCESS_KEY in .env}
|
||||
AWS_SECRET_ACCESS_KEY: ${WARP_PB_S3_SECRET:?set WARP_PB_S3_SECRET in .env}
|
||||
volumes:
|
||||
- seaweed-data:/data
|
||||
ports:
|
||||
# For aws-cli and the like; the homeserver uses the compose network.
|
||||
- "${SEAWEED_S3_BIND:-127.0.0.1}:${SEAWEED_S3_PORT:-8333}:8333"
|
||||
healthcheck:
|
||||
# The gateway answering means master, volume and filer are up too.
|
||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8333/healthz >/dev/null || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 12
|
||||
start_period: 20s
|
||||
|
||||
# Runs once per start and exits. The homeserver never creates its bucket;
|
||||
# creating one that exists is a no-op.
|
||||
seaweedfs-init:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: "no"
|
||||
depends_on:
|
||||
seaweedfs:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
WARP_PB_S3_BUCKET: ${WARP_PB_S3_BUCKET:-warp}
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command:
|
||||
- echo "s3.bucket.create -name $$WARP_PB_S3_BUCKET" | weed shell -master=seaweedfs:9333 >/dev/null
|
||||
|
||||
warp:
|
||||
image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp:${WARP_VERSION:-latest}
|
||||
pull_policy: always
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
seaweedfs:
|
||||
condition: service_healthy
|
||||
seaweedfs-init:
|
||||
condition: service_completed_successfully
|
||||
# The signing key is created on first start and kept in the volume:
|
||||
# losing it means other servers no longer recognise this one.
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command:
|
||||
- test -f /data/signing.key || warp generate-keys --output /data/signing.key; exec warp serve
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_DB_DRIVER: pocketbase
|
||||
WARP_DB_CONNECTION_STRING: /data/pb_data
|
||||
# The gateway on the compose network; these override whatever .env
|
||||
# says about S3.
|
||||
WARP_PB_S3_ENABLED: "true"
|
||||
WARP_PB_S3_ENDPOINT: http://seaweedfs:8333
|
||||
WARP_PB_S3_BUCKET: ${WARP_PB_S3_BUCKET:-warp}
|
||||
WARP_PB_S3_REGION: ${WARP_PB_S3_REGION:-us-east-1}
|
||||
WARP_PB_S3_FORCE_PATH_STYLE: "true"
|
||||
WARP_PB_S3_ACCESS_KEY: ${WARP_PB_S3_ACCESS_KEY:?set WARP_PB_S3_ACCESS_KEY in .env}
|
||||
WARP_PB_S3_SECRET: ${WARP_PB_S3_SECRET:?set WARP_PB_S3_SECRET in .env}
|
||||
volumes:
|
||||
- warp-data:/data
|
||||
ports:
|
||||
- "${WARP_PORT:-8008}:8008"
|
||||
|
||||
admin:
|
||||
image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp-admin:${WARP_VERSION:-latest}
|
||||
pull_policy: always
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- warp
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_ADMIN_HOMESERVER: http://warp:8008
|
||||
ports:
|
||||
- "${WARP_ADMIN_PORT:-8009}:8009"
|
||||
|
||||
web:
|
||||
image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp-web:${WARP_VERSION:-latest}
|
||||
pull_policy: always
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- warp
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_WEB_HOMESERVER: http://warp:8008
|
||||
ports:
|
||||
- "${WARP_WEB_PORT:-8080}:8080"
|
||||
|
||||
volumes:
|
||||
warp-data:
|
||||
seaweed-data:
|
||||
@@ -0,0 +1,240 @@
|
||||
# Warp on PocketBase with media in SeaweedFS split into its roles: the
|
||||
# homeserver, the admin panel and the web client pulled from a registry,
|
||||
# plus SeaweedFS's master, volume, filer, S3 gateway and admin UI as
|
||||
# separate containers.
|
||||
#
|
||||
# cd Docker
|
||||
# cp .env.example .env # then edit it; set WARP_PB_S3_ACCESS_KEY,
|
||||
# # WARP_PB_S3_SECRET and SEAWEED_ADMIN_PASSWORD
|
||||
# docker compose -f docker-compose.pocketbase.seaweedfs.split.prod.yml up -d
|
||||
#
|
||||
# The database stays in /data/pb_data (warp-data); media goes to the bucket
|
||||
# WARP_PB_S3_BUCKET (default warp) in SeaweedFS (seaweed-data). Over
|
||||
# docker-compose.pocketbase.seaweedfs.yml this buys SeaweedFS's admin UI,
|
||||
# where S3 identities are created and revoked under Object Store → Users,
|
||||
# per-role restarts, upgrades and metrics, and room for a second volume
|
||||
# server. The S3 behaviour is the same. Media stored before S3 was on is not
|
||||
# moved into the bucket.
|
||||
#
|
||||
# Homeserver http://localhost:8008, admin panel http://localhost:8009, web
|
||||
# client http://localhost:8080. The S3 gateway (8333) and the SeaweedFS admin
|
||||
# UI (23646) are published on loopback; SEAWEED_S3_BIND and
|
||||
# SEAWEED_ADMIN_BIND=0.0.0.0 expose them, the admin UI only behind a proxy.
|
||||
# Master, volume and filer are not published: the volume server serves file
|
||||
# content by id with no authentication at all.
|
||||
#
|
||||
# Master, volume and filer share seaweed-data in the layout `weed server
|
||||
# -dir` writes, and this file shares its project with
|
||||
# docker-compose.pocketbase.seaweedfs.yml, so switching between the two
|
||||
# needs no migration.
|
||||
#
|
||||
# Create the first administrator once the server is up:
|
||||
#
|
||||
# docker compose -f docker-compose.pocketbase.seaweedfs.split.prod.yml exec warp warp create-account --username admin --admin
|
||||
#
|
||||
# Nothing is built here: the homeserver, admin panel and web client images
|
||||
# come from WARP_REGISTRY (default ghcr.io/dariuszjaniak) at tag
|
||||
# WARP_VERSION (default latest), and SeaweedFS from SEAWEED_IMAGE. Pin
|
||||
# WARP_VERSION to a release in production, and update with
|
||||
#
|
||||
# docker compose -f docker-compose.pocketbase.seaweedfs.split.prod.yml pull && docker compose -f docker-compose.pocketbase.seaweedfs.split.prod.yml up -d
|
||||
|
||||
name: warp-pocketbase-seaweedfs
|
||||
|
||||
services:
|
||||
# Volume and topology metadata; hands out file ids. -ip is the name the
|
||||
# other roles reach it by.
|
||||
seaweedfs-master:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: unless-stopped
|
||||
command: >
|
||||
master -ip=seaweedfs-master -ip.bind=0.0.0.0 -mdir=/data
|
||||
-volumeSizeLimitMB=1024 -metricsPort=9324
|
||||
volumes:
|
||||
- seaweed-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:9333/cluster/status >/dev/null || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 12
|
||||
start_period: 15s
|
||||
|
||||
# Where the bytes land. -max=0 sizes itself from free disk instead of the
|
||||
# default cap of 8 volumes.
|
||||
seaweedfs-volume:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: unless-stopped
|
||||
command: >
|
||||
volume -master=seaweedfs-master:9333 -ip=seaweedfs-volume -ip.bind=0.0.0.0
|
||||
-port=8080 -dir=/data -max=0 -metricsPort=9325
|
||||
depends_on:
|
||||
seaweedfs-master:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- seaweed-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8080/healthz >/dev/null || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 12
|
||||
start_period: 15s
|
||||
|
||||
# The directory tree over the volume store (buckets, object keys) and the
|
||||
# IAM store the S3 identities live in, kept on the data volume.
|
||||
seaweedfs-filer:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: unless-stopped
|
||||
command: >
|
||||
filer -master=seaweedfs-master:9333 -ip=seaweedfs-filer -ip.bind=0.0.0.0
|
||||
-port=8888 -defaultStoreDir=/data -metricsPort=9326
|
||||
depends_on:
|
||||
seaweedfs-volume:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- seaweed-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8888/healthz >/dev/null || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 12
|
||||
start_period: 15s
|
||||
|
||||
# Runs once per start and exits: creates the bucket (the homeserver never
|
||||
# does) and writes the homeserver's identity into the filer's IAM store,
|
||||
# both in place, so a rotated WARP_PB_S3_SECRET lands on the next start.
|
||||
# That store is the one the admin UI writes, so the gateway gets no AWS_*
|
||||
# variables or -config: those lower-priority sources would be displaced by
|
||||
# the first identity added in the admin UI. The closing grep fails the
|
||||
# start if the identity is missing, rather than letting the gateway come
|
||||
# up open to anyone.
|
||||
seaweedfs-init:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: "no"
|
||||
depends_on:
|
||||
seaweedfs-filer:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
# Expanded by the shell inside the container, so the secret stays off
|
||||
# the command line.
|
||||
WARP_PB_S3_BUCKET: ${WARP_PB_S3_BUCKET:-warp}
|
||||
WARP_PB_S3_ACCESS_KEY: ${WARP_PB_S3_ACCESS_KEY:?set WARP_PB_S3_ACCESS_KEY in .env}
|
||||
WARP_PB_S3_SECRET: ${WARP_PB_S3_SECRET:?set WARP_PB_S3_SECRET in .env}
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command:
|
||||
- |
|
||||
set -e
|
||||
printf '%s\n' \
|
||||
"s3.bucket.create -name $$WARP_PB_S3_BUCKET" \
|
||||
"s3.configure -user warp -access_key $$WARP_PB_S3_ACCESS_KEY -secret_key $$WARP_PB_S3_SECRET -actions Admin -apply" \
|
||||
| weed shell -master=seaweedfs-master:9333 -filer=seaweedfs-filer:8888 >/dev/null
|
||||
echo "s3.configure" \
|
||||
| weed shell -master=seaweedfs-master:9333 -filer=seaweedfs-filer:8888 \
|
||||
| grep -q "$$WARP_PB_S3_ACCESS_KEY"
|
||||
|
||||
# The homeserver's endpoint. Credentials come from the filer's IAM store.
|
||||
seaweedfs-s3:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: unless-stopped
|
||||
command: s3 -filer=seaweedfs-filer:8888 -ip.bind=0.0.0.0 -port=8333 -metricsPort=9327
|
||||
depends_on:
|
||||
seaweedfs-filer:
|
||||
condition: service_healthy
|
||||
seaweedfs-init:
|
||||
condition: service_completed_successfully
|
||||
ports:
|
||||
# For aws-cli and the like; the homeserver uses the compose network.
|
||||
- "${SEAWEED_S3_BIND:-127.0.0.1}:${SEAWEED_S3_PORT:-8333}:8333"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8333/healthz >/dev/null || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 12
|
||||
start_period: 15s
|
||||
|
||||
# Cluster view, buckets, maintenance, and Object Store → Users. It can mint
|
||||
# credentials for the bucket, and weed serves it with no authentication
|
||||
# when the password is empty, so the password is required. Read from
|
||||
# WEED_ADMIN_* to keep it off the command line.
|
||||
seaweedfs-admin:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: unless-stopped
|
||||
command: admin -port=23646 -master=seaweedfs-master:9333 -dataDir=/data -metricsPort=9328
|
||||
depends_on:
|
||||
seaweedfs-master:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
WEED_ADMIN_USER: ${SEAWEED_ADMIN_USER:-admin}
|
||||
WEED_ADMIN_PASSWORD: ${SEAWEED_ADMIN_PASSWORD:?set SEAWEED_ADMIN_PASSWORD in .env}
|
||||
WEED_ADMIN_READONLY_USER: ${SEAWEED_ADMIN_READONLY_USER:-}
|
||||
WEED_ADMIN_READONLY_PASSWORD: ${SEAWEED_ADMIN_READONLY_PASSWORD:-}
|
||||
volumes:
|
||||
- seaweed-admin:/data
|
||||
ports:
|
||||
- "${SEAWEED_ADMIN_BIND:-127.0.0.1}:${SEAWEED_ADMIN_PORT:-23646}:23646"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:23646/health >/dev/null || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 12
|
||||
start_period: 15s
|
||||
|
||||
warp:
|
||||
image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp:${WARP_VERSION:-latest}
|
||||
pull_policy: always
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
seaweedfs-s3:
|
||||
condition: service_healthy
|
||||
# The signing key is created on first start and kept in the volume:
|
||||
# losing it means other servers no longer recognise this one.
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command:
|
||||
- test -f /data/signing.key || warp generate-keys --output /data/signing.key; exec warp serve
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_DB_DRIVER: pocketbase
|
||||
WARP_DB_CONNECTION_STRING: /data/pb_data
|
||||
# The gateway on the compose network; these override whatever .env
|
||||
# says about S3.
|
||||
WARP_PB_S3_ENABLED: "true"
|
||||
WARP_PB_S3_ENDPOINT: http://seaweedfs-s3:8333
|
||||
WARP_PB_S3_BUCKET: ${WARP_PB_S3_BUCKET:-warp}
|
||||
WARP_PB_S3_REGION: ${WARP_PB_S3_REGION:-us-east-1}
|
||||
WARP_PB_S3_FORCE_PATH_STYLE: "true"
|
||||
WARP_PB_S3_ACCESS_KEY: ${WARP_PB_S3_ACCESS_KEY:?set WARP_PB_S3_ACCESS_KEY in .env}
|
||||
WARP_PB_S3_SECRET: ${WARP_PB_S3_SECRET:?set WARP_PB_S3_SECRET in .env}
|
||||
volumes:
|
||||
- warp-data:/data
|
||||
ports:
|
||||
- "${WARP_PORT:-8008}:8008"
|
||||
|
||||
admin:
|
||||
image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp-admin:${WARP_VERSION:-latest}
|
||||
pull_policy: always
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- warp
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_ADMIN_HOMESERVER: http://warp:8008
|
||||
ports:
|
||||
- "${WARP_ADMIN_PORT:-8009}:8009"
|
||||
|
||||
web:
|
||||
image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp-web:${WARP_VERSION:-latest}
|
||||
pull_policy: always
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- warp
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_WEB_HOMESERVER: http://warp:8008
|
||||
ports:
|
||||
- "${WARP_WEB_PORT:-8080}:8080"
|
||||
|
||||
volumes:
|
||||
warp-data:
|
||||
# Master, volume and filer share it, as `weed server -dir` lays it out.
|
||||
seaweed-data:
|
||||
# The admin UI's session key and maintenance state; no object data.
|
||||
seaweed-admin:
|
||||
@@ -0,0 +1,239 @@
|
||||
# Warp on PocketBase with media in SeaweedFS split into its roles: the
|
||||
# homeserver, the admin panel and the web client built from this checkout,
|
||||
# plus SeaweedFS's master, volume, filer, S3 gateway and admin UI as
|
||||
# separate containers.
|
||||
#
|
||||
# cd Docker
|
||||
# cp .env.example .env # then edit it; set WARP_PB_S3_ACCESS_KEY,
|
||||
# # WARP_PB_S3_SECRET and SEAWEED_ADMIN_PASSWORD
|
||||
# docker compose -f docker-compose.pocketbase.seaweedfs.split.yml up -d --build
|
||||
#
|
||||
# The database stays in /data/pb_data (warp-data); media goes to the bucket
|
||||
# WARP_PB_S3_BUCKET (default warp) in SeaweedFS (seaweed-data). Over
|
||||
# docker-compose.pocketbase.seaweedfs.yml this buys SeaweedFS's admin UI,
|
||||
# where S3 identities are created and revoked under Object Store → Users,
|
||||
# per-role restarts, upgrades and metrics, and room for a second volume
|
||||
# server. The S3 behaviour is the same. Media stored before S3 was on is not
|
||||
# moved into the bucket.
|
||||
#
|
||||
# Homeserver http://localhost:8008, admin panel http://localhost:8009, web
|
||||
# client http://localhost:8080. The S3 gateway (8333) and the SeaweedFS admin
|
||||
# UI (23646) are published on loopback; SEAWEED_S3_BIND and
|
||||
# SEAWEED_ADMIN_BIND=0.0.0.0 expose them, the admin UI only behind a proxy.
|
||||
# Master, volume and filer are not published: the volume server serves file
|
||||
# content by id with no authentication at all.
|
||||
#
|
||||
# Master, volume and filer share seaweed-data in the layout `weed server
|
||||
# -dir` writes, and this file shares its project with
|
||||
# docker-compose.pocketbase.seaweedfs.yml, so switching between the two
|
||||
# needs no migration.
|
||||
#
|
||||
# Create the first administrator once the server is up:
|
||||
#
|
||||
# docker compose -f docker-compose.pocketbase.seaweedfs.split.yml exec warp warp create-account --username admin --admin
|
||||
|
||||
name: warp-pocketbase-seaweedfs
|
||||
|
||||
services:
|
||||
# Volume and topology metadata; hands out file ids. -ip is the name the
|
||||
# other roles reach it by.
|
||||
seaweedfs-master:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: unless-stopped
|
||||
command: >
|
||||
master -ip=seaweedfs-master -ip.bind=0.0.0.0 -mdir=/data
|
||||
-volumeSizeLimitMB=1024 -metricsPort=9324
|
||||
volumes:
|
||||
- seaweed-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:9333/cluster/status >/dev/null || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 12
|
||||
start_period: 15s
|
||||
|
||||
# Where the bytes land. -max=0 sizes itself from free disk instead of the
|
||||
# default cap of 8 volumes.
|
||||
seaweedfs-volume:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: unless-stopped
|
||||
command: >
|
||||
volume -master=seaweedfs-master:9333 -ip=seaweedfs-volume -ip.bind=0.0.0.0
|
||||
-port=8080 -dir=/data -max=0 -metricsPort=9325
|
||||
depends_on:
|
||||
seaweedfs-master:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- seaweed-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8080/healthz >/dev/null || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 12
|
||||
start_period: 15s
|
||||
|
||||
# The directory tree over the volume store (buckets, object keys) and the
|
||||
# IAM store the S3 identities live in, kept on the data volume.
|
||||
seaweedfs-filer:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: unless-stopped
|
||||
command: >
|
||||
filer -master=seaweedfs-master:9333 -ip=seaweedfs-filer -ip.bind=0.0.0.0
|
||||
-port=8888 -defaultStoreDir=/data -metricsPort=9326
|
||||
depends_on:
|
||||
seaweedfs-volume:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- seaweed-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8888/healthz >/dev/null || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 12
|
||||
start_period: 15s
|
||||
|
||||
# Runs once per start and exits: creates the bucket (the homeserver never
|
||||
# does) and writes the homeserver's identity into the filer's IAM store,
|
||||
# both in place, so a rotated WARP_PB_S3_SECRET lands on the next start.
|
||||
# That store is the one the admin UI writes, so the gateway gets no AWS_*
|
||||
# variables or -config: those lower-priority sources would be displaced by
|
||||
# the first identity added in the admin UI. The closing grep fails the
|
||||
# start if the identity is missing, rather than letting the gateway come
|
||||
# up open to anyone.
|
||||
seaweedfs-init:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: "no"
|
||||
depends_on:
|
||||
seaweedfs-filer:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
# Expanded by the shell inside the container, so the secret stays off
|
||||
# the command line.
|
||||
WARP_PB_S3_BUCKET: ${WARP_PB_S3_BUCKET:-warp}
|
||||
WARP_PB_S3_ACCESS_KEY: ${WARP_PB_S3_ACCESS_KEY:?set WARP_PB_S3_ACCESS_KEY in .env}
|
||||
WARP_PB_S3_SECRET: ${WARP_PB_S3_SECRET:?set WARP_PB_S3_SECRET in .env}
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command:
|
||||
- |
|
||||
set -e
|
||||
printf '%s\n' \
|
||||
"s3.bucket.create -name $$WARP_PB_S3_BUCKET" \
|
||||
"s3.configure -user warp -access_key $$WARP_PB_S3_ACCESS_KEY -secret_key $$WARP_PB_S3_SECRET -actions Admin -apply" \
|
||||
| weed shell -master=seaweedfs-master:9333 -filer=seaweedfs-filer:8888 >/dev/null
|
||||
echo "s3.configure" \
|
||||
| weed shell -master=seaweedfs-master:9333 -filer=seaweedfs-filer:8888 \
|
||||
| grep -q "$$WARP_PB_S3_ACCESS_KEY"
|
||||
|
||||
# The homeserver's endpoint. Credentials come from the filer's IAM store.
|
||||
seaweedfs-s3:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: unless-stopped
|
||||
command: s3 -filer=seaweedfs-filer:8888 -ip.bind=0.0.0.0 -port=8333 -metricsPort=9327
|
||||
depends_on:
|
||||
seaweedfs-filer:
|
||||
condition: service_healthy
|
||||
seaweedfs-init:
|
||||
condition: service_completed_successfully
|
||||
ports:
|
||||
# For aws-cli and the like; the homeserver uses the compose network.
|
||||
- "${SEAWEED_S3_BIND:-127.0.0.1}:${SEAWEED_S3_PORT:-8333}:8333"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8333/healthz >/dev/null || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 12
|
||||
start_period: 15s
|
||||
|
||||
# Cluster view, buckets, maintenance, and Object Store → Users. It can mint
|
||||
# credentials for the bucket, and weed serves it with no authentication
|
||||
# when the password is empty, so the password is required. Read from
|
||||
# WEED_ADMIN_* to keep it off the command line.
|
||||
seaweedfs-admin:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: unless-stopped
|
||||
command: admin -port=23646 -master=seaweedfs-master:9333 -dataDir=/data -metricsPort=9328
|
||||
depends_on:
|
||||
seaweedfs-master:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
WEED_ADMIN_USER: ${SEAWEED_ADMIN_USER:-admin}
|
||||
WEED_ADMIN_PASSWORD: ${SEAWEED_ADMIN_PASSWORD:?set SEAWEED_ADMIN_PASSWORD in .env}
|
||||
WEED_ADMIN_READONLY_USER: ${SEAWEED_ADMIN_READONLY_USER:-}
|
||||
WEED_ADMIN_READONLY_PASSWORD: ${SEAWEED_ADMIN_READONLY_PASSWORD:-}
|
||||
volumes:
|
||||
- seaweed-admin:/data
|
||||
ports:
|
||||
- "${SEAWEED_ADMIN_BIND:-127.0.0.1}:${SEAWEED_ADMIN_PORT:-23646}:23646"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:23646/health >/dev/null || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 12
|
||||
start_period: 15s
|
||||
|
||||
warp:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: Dockerfile
|
||||
image: warp:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
seaweedfs-s3:
|
||||
condition: service_healthy
|
||||
# The signing key is created on first start and kept in the volume:
|
||||
# losing it means other servers no longer recognise this one.
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command:
|
||||
- test -f /data/signing.key || warp generate-keys --output /data/signing.key; exec warp serve
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_DB_DRIVER: pocketbase
|
||||
WARP_DB_CONNECTION_STRING: /data/pb_data
|
||||
# The gateway on the compose network; these override whatever .env
|
||||
# says about S3.
|
||||
WARP_PB_S3_ENABLED: "true"
|
||||
WARP_PB_S3_ENDPOINT: http://seaweedfs-s3:8333
|
||||
WARP_PB_S3_BUCKET: ${WARP_PB_S3_BUCKET:-warp}
|
||||
WARP_PB_S3_REGION: ${WARP_PB_S3_REGION:-us-east-1}
|
||||
WARP_PB_S3_FORCE_PATH_STYLE: "true"
|
||||
WARP_PB_S3_ACCESS_KEY: ${WARP_PB_S3_ACCESS_KEY:?set WARP_PB_S3_ACCESS_KEY in .env}
|
||||
WARP_PB_S3_SECRET: ${WARP_PB_S3_SECRET:?set WARP_PB_S3_SECRET in .env}
|
||||
volumes:
|
||||
- warp-data:/data
|
||||
ports:
|
||||
- "${WARP_PORT:-8008}:8008"
|
||||
|
||||
admin:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: apps/admin/Dockerfile
|
||||
image: warp-admin:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- warp
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_ADMIN_HOMESERVER: http://warp:8008
|
||||
ports:
|
||||
- "${WARP_ADMIN_PORT:-8009}:8009"
|
||||
|
||||
web:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: apps/web/Dockerfile
|
||||
image: warp-web:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- warp
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_WEB_HOMESERVER: http://warp:8008
|
||||
ports:
|
||||
- "${WARP_WEB_PORT:-8080}:8080"
|
||||
|
||||
volumes:
|
||||
warp-data:
|
||||
# Master, volume and filer share it, as `weed server -dir` lays it out.
|
||||
seaweed-data:
|
||||
# The admin UI's session key and maintenance state; no object data.
|
||||
seaweed-admin:
|
||||
@@ -0,0 +1,133 @@
|
||||
# Warp on PocketBase with media in SeaweedFS: the homeserver, the admin panel
|
||||
# and the web client built from this checkout, plus SeaweedFS as one
|
||||
# container (`weed server -s3`: master, volume, filer and S3 gateway in one
|
||||
# process).
|
||||
#
|
||||
# cd Docker
|
||||
# cp .env.example .env # then edit it; set WARP_PB_S3_ACCESS_KEY
|
||||
# # and WARP_PB_S3_SECRET
|
||||
# docker compose -f docker-compose.pocketbase.seaweedfs.yml up -d --build
|
||||
#
|
||||
# The database stays in /data/pb_data (warp-data); media goes to the bucket
|
||||
# WARP_PB_S3_BUCKET (default warp) in SeaweedFS (seaweed-data), whose gateway
|
||||
# has exactly one identity: the homeserver's. For SeaweedFS's admin UI and
|
||||
# per-role containers, see docker-compose.pocketbase.seaweedfs.split.yml.
|
||||
# Media stored before S3 was on is not moved into the bucket.
|
||||
#
|
||||
# Homeserver http://localhost:8008, admin panel http://localhost:8009, web
|
||||
# client http://localhost:8080. The S3 gateway (8333) is published on
|
||||
# loopback, for aws-cli and the like; SEAWEED_S3_BIND=0.0.0.0 exposes it.
|
||||
#
|
||||
# This file shares its project and volumes with
|
||||
# docker-compose.pocketbase.seaweedfs.split.yml: SeaweedFS's data has the
|
||||
# same layout either way, so switching between the two needs no migration.
|
||||
#
|
||||
# Create the first administrator once the server is up:
|
||||
#
|
||||
# docker compose -f docker-compose.pocketbase.seaweedfs.yml exec warp warp create-account --username admin --admin
|
||||
|
||||
name: warp-pocketbase-seaweedfs
|
||||
|
||||
services:
|
||||
seaweedfs:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: unless-stopped
|
||||
command: server -dir=/data -s3 -volume.max=0 -master.volumeSizeLimitMB=1024
|
||||
environment:
|
||||
# With no -s3.config, the gateway takes its single identity from these,
|
||||
# which is also what takes it out of its allow-anyone default. The same
|
||||
# pair the homeserver signs with.
|
||||
AWS_ACCESS_KEY_ID: ${WARP_PB_S3_ACCESS_KEY:?set WARP_PB_S3_ACCESS_KEY in .env}
|
||||
AWS_SECRET_ACCESS_KEY: ${WARP_PB_S3_SECRET:?set WARP_PB_S3_SECRET in .env}
|
||||
volumes:
|
||||
- seaweed-data:/data
|
||||
ports:
|
||||
# For aws-cli and the like; the homeserver uses the compose network.
|
||||
- "${SEAWEED_S3_BIND:-127.0.0.1}:${SEAWEED_S3_PORT:-8333}:8333"
|
||||
healthcheck:
|
||||
# The gateway answering means master, volume and filer are up too.
|
||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8333/healthz >/dev/null || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 12
|
||||
start_period: 20s
|
||||
|
||||
# Runs once per start and exits. The homeserver never creates its bucket;
|
||||
# creating one that exists is a no-op.
|
||||
seaweedfs-init:
|
||||
image: ${SEAWEED_IMAGE:-chrislusf/seaweedfs:4.45}
|
||||
restart: "no"
|
||||
depends_on:
|
||||
seaweedfs:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
WARP_PB_S3_BUCKET: ${WARP_PB_S3_BUCKET:-warp}
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command:
|
||||
- echo "s3.bucket.create -name $$WARP_PB_S3_BUCKET" | weed shell -master=seaweedfs:9333 >/dev/null
|
||||
|
||||
warp:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: Dockerfile
|
||||
image: warp:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
seaweedfs:
|
||||
condition: service_healthy
|
||||
seaweedfs-init:
|
||||
condition: service_completed_successfully
|
||||
# The signing key is created on first start and kept in the volume:
|
||||
# losing it means other servers no longer recognise this one.
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command:
|
||||
- test -f /data/signing.key || warp generate-keys --output /data/signing.key; exec warp serve
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_DB_DRIVER: pocketbase
|
||||
WARP_DB_CONNECTION_STRING: /data/pb_data
|
||||
# The gateway on the compose network; these override whatever .env
|
||||
# says about S3.
|
||||
WARP_PB_S3_ENABLED: "true"
|
||||
WARP_PB_S3_ENDPOINT: http://seaweedfs:8333
|
||||
WARP_PB_S3_BUCKET: ${WARP_PB_S3_BUCKET:-warp}
|
||||
WARP_PB_S3_REGION: ${WARP_PB_S3_REGION:-us-east-1}
|
||||
WARP_PB_S3_FORCE_PATH_STYLE: "true"
|
||||
WARP_PB_S3_ACCESS_KEY: ${WARP_PB_S3_ACCESS_KEY:?set WARP_PB_S3_ACCESS_KEY in .env}
|
||||
WARP_PB_S3_SECRET: ${WARP_PB_S3_SECRET:?set WARP_PB_S3_SECRET in .env}
|
||||
volumes:
|
||||
- warp-data:/data
|
||||
ports:
|
||||
- "${WARP_PORT:-8008}:8008"
|
||||
|
||||
admin:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: apps/admin/Dockerfile
|
||||
image: warp-admin:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- warp
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_ADMIN_HOMESERVER: http://warp:8008
|
||||
ports:
|
||||
- "${WARP_ADMIN_PORT:-8009}:8009"
|
||||
|
||||
web:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: apps/web/Dockerfile
|
||||
image: warp-web:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- warp
|
||||
env_file: .env
|
||||
environment:
|
||||
WARP_WEB_HOMESERVER: http://warp:8008
|
||||
ports:
|
||||
- "${WARP_WEB_PORT:-8080}:8080"
|
||||
|
||||
volumes:
|
||||
warp-data:
|
||||
seaweed-data:
|
||||
Reference in new issue
Block a user