Files
Warp/Docker-AIO/Dockerfile.PocketBase.SeaweedFS
T
tajniak81andClaude Opus 5.5 36d83551aa Docker-AIO: PocketBase images with SeaweedFS for media
Dockerfile.PocketBase.SeaweedFS bakes SeaweedFS into the PocketBase
all-in-one image as one `weed server -s3` process;
Dockerfile.PocketBase.SeaweedFS.split runs master, volume, filer, S3
gateway and the admin UI as separate processes, with the homeserver's
S3 identity seeded into the filer's IAM store on every boot. Media goes
to the bucket, the database stays in /data/pb_data, and both layouts
share /seaweed/data, so switching between them needs no migration.

The entrypoint now tracks every process in one list and stops them in
reverse start order, and it refuses to start an open S3 gateway or
admin UI. Each image gets a build and a prod compose file, and
.env.example and the README cover the new settings. Modelled on
DriverVault's Docker-AIO SeaweedFS images.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 20:33:21 +02:00

148 lines
6.0 KiB
Docker

# warp-aio-pocketbase-seaweedfs — the homeserver, the admin panel and the
# web client on PocketBase, with SeaweedFS in the same image as the media
# store: one `weed server -s3` process, master, volume, filer and S3 gateway
# in one. The homeserver keeps its database in /data/pb_data and its media
# in the bucket WARP_PB_S3_BUCKET (default warp) on the gateway at
# 127.0.0.1:8333. For per-role processes and SeaweedFS's admin UI, see
# Dockerfile.PocketBase.SeaweedFS.split.
#
# Build from the repository root:
#
# docker build -t warp-aio-pocketbase-seaweedfs -f Docker-AIO/Dockerfile.PocketBase.SeaweedFS .
# docker run -p 8008:8008 -p 8009:8009 -p 8080:8080 -p 127.0.0.1:8333:8333 \
# -v warp-data:/data -v seaweed-data:/seaweed/data \
# -e WARP_SERVER_NAME=warp.example \
# -e WARP_PB_S3_ACCESS_KEY=warp -e WARP_PB_S3_SECRET=change-me \
# warp-aio-pocketbase-seaweedfs
#
# WARP_PB_S3_ACCESS_KEY and WARP_PB_S3_SECRET are required: they are the
# gateway's only identity and what the homeserver signs its requests with.
#
# Ports inside the container (publish 8333 on loopback at most; never 8081,
# the volume server, which serves content by id with no authentication):
#
# 8008 homeserver 8333 SeaweedFS S3 gateway
# 8009 admin panel 8888 SeaweedFS filer
# 8080 web client 9333 SeaweedFS master
# 8081 SeaweedFS volume (not its usual 8080, which is the web client)
# SeaweedFS release to bake in, pinned so a rebuild later brings up the same
# one; --build-arg SEAWEED_VERSION=... to upgrade. Global, because a FROM uses
# it.
ARG SEAWEED_VERSION="4.45"
FROM node:22-alpine AS web
WORKDIR /src
RUN corepack enable
# Lockfile and manifests first, so the package store survives source changes.
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./
COPY apps/ui/package.json ./apps/ui/
COPY apps/admin/package.json ./apps/admin/
COPY apps/web/package.json ./apps/web/
RUN pnpm install --frozen-lockfile --filter @warp/admin... --filter @warp/web...
COPY apps/ui ./apps/ui
COPY apps/admin ./apps/admin
COPY apps/web ./apps/web
RUN pnpm --filter @warp/admin build && pnpm --filter @warp/web build
FROM golang:1.26-alpine AS build
ARG VERSION=0.0.0-dev
ARG COMMIT=unknown
ARG BUILD_DATE=unknown
ENV CGO_ENABLED=0
WORKDIR /src
# The homeserver. Dependencies first, so the module cache survives source
# changes.
COPY server/go.mod server/go.sum ./server/
RUN cd server && go mod download
COPY server ./server
RUN cd server && go build -trimpath \
-ldflags "-s -w \
-X github.com/dariuszjaniak/warp/server/internal/buildinfo.Version=${VERSION} \
-X github.com/dariuszjaniak/warp/server/internal/buildinfo.Commit=${COMMIT} \
-X github.com/dariuszjaniak/warp/server/internal/buildinfo.BuildDate=${BUILD_DATE}" \
-o /out/warp ./cmd/warp
# The admin panel and the web client, each with its frontend embedded.
COPY apps/admin/go.mod ./apps/admin/
COPY apps/admin/cmd ./apps/admin/cmd
COPY apps/admin/internal ./apps/admin/internal
COPY --from=web /src/apps/admin/internal/panel/build/dist ./apps/admin/internal/panel/build/dist
RUN cd apps/admin && GOWORK=off go build -trimpath -ldflags "-s -w -X main.version=${VERSION}" \
-o /out/warp-admin ./cmd/warp-admin
COPY apps/web/go.mod ./apps/web/
COPY apps/web/cmd ./apps/web/cmd
COPY apps/web/host ./apps/web/host
COPY apps/web/client/client.go ./apps/web/client/
COPY --from=web /src/apps/web/client/build/dist ./apps/web/client/build/dist
RUN cd apps/web && GOWORK=off go build -trimpath -ldflags "-s -w -X main.version=${VERSION}" \
-o /out/warp-web ./cmd/warp-web
# The one static weed binary from the official image.
FROM chrislusf/seaweedfs:${SEAWEED_VERSION} AS seaweed
FROM alpine:3.21
# tini is PID 1 so signals reach the entrypoint and zombies are reaped.
RUN apk add --no-cache ca-certificates tzdata curl tini && \
adduser -D -u 10001 -h /data warp
COPY --from=build /out/warp /out/warp-admin /out/warp-web /usr/local/bin/
COPY --from=seaweed /usr/bin/weed /usr/local/bin/weed
COPY warp.yaml.example /etc/warp/warp.yaml.example
COPY --chmod=755 Docker-AIO/entrypoint.sh /usr/local/bin/warp-aio
# /data: the database, signing key and anything stored before S3 was on.
# /seaweed/data: everything SeaweedFS keeps.
# Mount a volume on each; a fresh named volume inherits the ownership.
RUN mkdir -p /data /seaweed/data && chown -R warp:warp /data /seaweed
WORKDIR /data
USER warp
# Media goes to the bucket on the gateway inside this image: a fixed
# loopback address, path style because a self-hosted gateway has no
# per-bucket DNS, and a region SeaweedFS ignores. Media stored on the
# filesystem before S3 was on is not moved into the bucket.
ENV WARP_LISTEN_ADDRESS=":8008" \
WARP_PRIVATE_KEY="/data/signing.key" \
WARP_DB_DRIVER="pocketbase" \
WARP_DB_CONNECTION_STRING="/data/pb_data" \
WARP_PB_S3_ENABLED="true" \
WARP_PB_S3_ENDPOINT="http://127.0.0.1:8333" \
WARP_PB_S3_BUCKET="warp" \
WARP_PB_S3_REGION="us-east-1" \
WARP_PB_S3_FORCE_PATH_STYLE="true" \
WARP_LOG_FORMAT="json" \
WARP_ADMIN_LISTEN=":8009" \
WARP_ADMIN_HOMESERVER="http://127.0.0.1:8008" \
WARP_ADMIN_LOG_FORMAT="json" \
WARP_WEB_LISTEN=":8080" \
WARP_WEB_HOMESERVER="http://127.0.0.1:8008" \
WARP_WEB_LOG_FORMAT="json" \
WARP_AIO_ADMIN="true" \
WARP_AIO_WEB="true" \
WARP_AIO_EMBEDDED_POSTGRES="false" \
WARP_AIO_SEAWEEDFS="server"
EXPOSE 8008 8009 8080 8333
# Every process must answer, so a wedged one shows in `docker ps`.
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD curl -fsS -o /dev/null http://127.0.0.1:9333/cluster/status && \
curl -fsS -o /dev/null http://127.0.0.1:8333/healthz && \
curl -fsS -o /dev/null http://127.0.0.1:8008/healthz && \
{ [ "$WARP_AIO_ADMIN" != true ] || curl -fsS -o /dev/null http://127.0.0.1:8009/healthz; } && \
{ [ "$WARP_AIO_WEB" != true ] || curl -fsS -o /dev/null http://127.0.0.1:8080/healthz; } || exit 1
ENTRYPOINT ["/sbin/tini", "--", "warp-aio"]