CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Test (windows-latest) (push) Canceled after 0s
CI / Storage tests on PostgreSQL (push) Canceled after 0s
CI / Complement (federation off) (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
CI / Smoke test the binary (push) Canceled after 0s
CI / Admin panel (push) Canceled after 0s
CI / Web client (push) Canceled after 0s
CI / Desktop client (ubuntu-24.04) (push) Canceled after 0s
CI / Desktop client (windows-latest) (push) Canceled after 0s
The pocketbase driver no longer embeds PocketBase: Warp keeps its data as PocketBase collections on a server of its own and reaches it only through the REST API, the way the postgres driver reaches PostgreSQL. database.connection_string is the server's URL, and Warp signs in as the superuser in WARP_PB_SUPERUSER_EMAIL / WARP_PB_SUPERUSER_PASSWORD (or a WARP_PB_SUPERUSER_FILE of the two). Every SQL table is a superuser-only collection of the same name and columns, created by warp migrate. Reads go through PocketBase's SQL endpoint with the SQL drivers' queries, via a read-only database/sql driver that inlines arguments, moves long ones into warp_params and pages past 1000 rows. Writes are record operations in batch requests under one write lock in the Warp process. Media is a protected file field in warp_media, local or in the S3 bucket Warp writes into PocketBase's settings. Search matches word prefixes with LIKE. The storage tests run against an in-process PocketBase and pass as on SQLite. Docker: the PocketBase stacks get a pocketbase service running tajniak81/pocketbase-docker-root (WARP_PB_IMAGE), with a pb-data volume and its admin UI on loopback; the AIO images run that PocketBase binary as a process beside the homeserver, making up a superuser when none is set. The .env examples, READMEs, docs and warp.yaml.example follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
168 lines
7.1 KiB
Docker
168 lines
7.1 KiB
Docker
# warp-aio-pocketbase-seaweedfs-split — the homeserver, the admin panel and
|
|
# the web client on PocketBase, with SeaweedFS in the same image as the
|
|
# media store, split into its roles: master, volume, filer, S3 gateway and
|
|
# admin UI, one process each. Over Dockerfile.PocketBase.SeaweedFS that buys
|
|
# per-role restart, per-role metrics ports and the admin UI, where S3
|
|
# identities are minted and revoked under Object Store → Users.
|
|
#
|
|
# The homeserver's identity lives in the filer's IAM store, seeded on every
|
|
# boot, the same store the admin UI writes; so a key added there never
|
|
# displaces the homeserver's. /seaweed/data has the layout `weed server -dir`
|
|
# writes, so it moves between the two SeaweedFS images unchanged.
|
|
#
|
|
# Build from the repository root:
|
|
#
|
|
# docker build -t warp-aio-pocketbase-seaweedfs-split -f Docker-AIO/Dockerfile.PocketBase.SeaweedFS.split .
|
|
# docker run -p 8008:8008 -p 8009:8009 -p 8080:8080 \
|
|
# -p 127.0.0.1:8333:8333 -p 127.0.0.1:23646:23646 \
|
|
# -v warp-data:/data -v seaweed-data:/seaweed/data -v seaweed-admin:/seaweed/admin \
|
|
# -e WARP_SERVER_NAME=warp.example \
|
|
# -e WARP_PB_S3_ACCESS_KEY=warp -e WARP_PB_S3_SECRET=change-me \
|
|
# -e WEED_ADMIN_PASSWORD=change-me \
|
|
# warp-aio-pocketbase-seaweedfs-split
|
|
#
|
|
# WARP_PB_S3_ACCESS_KEY, WARP_PB_S3_SECRET and WEED_ADMIN_PASSWORD are
|
|
# required; the container refuses to start an open gateway or admin UI.
|
|
#
|
|
# Ports inside the container (publish 8333 and 23646 on loopback at most;
|
|
# master, volume and filer listen on loopback only):
|
|
#
|
|
# 8008 homeserver 8333 SeaweedFS S3 gateway
|
|
# 8009 admin panel 8888 SeaweedFS filer
|
|
# 8080 web client 9333 SeaweedFS master
|
|
# 8081 SeaweedFS volume 23646 SeaweedFS admin UI
|
|
# 9324-9328 SeaweedFS metrics: master, volume, filer, S3, admin
|
|
|
|
# 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"
|
|
|
|
# PocketBase itself: the binary of this image, PocketBase 0.40 or later.
|
|
ARG PB_IMAGE=tajniak81/pocketbase-docker-root:latest
|
|
FROM ${PB_IMAGE} AS pocketbase
|
|
|
|
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/
|
|
# PocketBase, from the same image the separate-container stacks run.
|
|
COPY --from=pocketbase /pb/pocketbase /usr/local/bin/pocketbase
|
|
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: master, volume and filer, sharing it.
|
|
# /seaweed/admin: the admin UI's session key and maintenance state.
|
|
# Mount a volume on each; a fresh named volume inherits the ownership.
|
|
RUN mkdir -p /data /seaweed/data /seaweed/admin && 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="http://127.0.0.1:8070" \
|
|
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_POCKETBASE="true" \
|
|
WARP_PB_SUPERUSER_FILE="/data/pocketbase-superuser.env" \
|
|
WARP_AIO_EMBEDDED_POSTGRES="false" \
|
|
WARP_AIO_SEAWEEDFS="split" \
|
|
WEED_ADMIN_USER="admin"
|
|
|
|
EXPOSE 8008 8009 8080 8070 8333 23646
|
|
|
|
# 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:8081/healthz && \
|
|
curl -fsS -o /dev/null http://127.0.0.1:8888/healthz && \
|
|
curl -fsS -o /dev/null http://127.0.0.1:8333/healthz && \
|
|
curl -fsS -o /dev/null http://127.0.0.1:23646/health && \
|
|
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"]
|