Files
libnovel/backend/Dockerfile
Admin fc73756308
Some checks failed
Release / Test backend (push) Successful in 56s
Release / Check ui (push) Successful in 1m59s
Release / Docker (push) Successful in 7m49s
Release / Deploy to prod (push) Failing after 33s
Release / Gitea Release (push) Successful in 29s
fix: run pocketbase as root + add healthcheck start_period
- Remove non-root user from pocketbase Docker image; the existing pb_data
  volume was created by the previous root-running image so files are owned
  by root — running as a non-root appuser caused an immediate permission
  error and container exit
- Increase healthcheck retries to 10 and add start_period=30s so migrations
  have time to run on first boot before liveness checks begin

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 19:00:21 +05:00

68 lines
3.0 KiB
Docker

# syntax=docker/dockerfile:1
FROM golang:1.26.1-alpine AS builder
WORKDIR /app
# Download modules into the BuildKit cache so they survive across builds.
# This layer is only invalidated when go.mod or go.sum changes.
COPY go.mod go.sum ./
RUN --mount=type=cache,target=/root/go/pkg/mod \
go mod download
COPY . .
ARG VERSION=dev
ARG COMMIT=unknown
# Build all three binaries in a single layer so the Go compiler can reuse
# intermediate object files. Both cache mounts are preserved between builds:
# /root/go/pkg/mod — downloaded module source
# /root/.cache/go-build — compiled package objects (incremental recompile)
RUN --mount=type=cache,target=/root/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=0 GOOS=linux go build \
-ldflags="-s -w -X main.version=${VERSION} -X main.commit=${COMMIT}" \
-o /out/backend ./cmd/backend && \
CGO_ENABLED=0 GOOS=linux go build \
-ldflags="-s -w -X main.version=${VERSION} -X main.commit=${COMMIT}" \
-o /out/runner ./cmd/runner && \
CGO_ENABLED=0 GOOS=linux go build \
-ldflags="-s -w" \
-o /out/healthcheck ./cmd/healthcheck && \
CGO_ENABLED=0 GOOS=linux go build \
-ldflags="-s -w" \
-o /out/pocketbase ./cmd/pocketbase
# ── backend service ──────────────────────────────────────────────────────────
# Uses Alpine (not distroless) so ffmpeg is available for on-demand voice
# sample generation via pocket-tts (WAV→MP3 transcoding).
FROM alpine:3.21 AS backend
RUN apk add --no-cache ffmpeg ca-certificates && \
addgroup -S appgroup && adduser -S appuser -G appgroup
COPY --from=builder /out/healthcheck /healthcheck
COPY --from=builder /out/backend /backend
USER appuser
ENTRYPOINT ["/backend"]
# ── pocketbase service ───────────────────────────────────────────────────────
# Runs the custom PocketBase binary with Go migrations baked in.
# On every `serve` startup it applies any pending migrations automatically.
# Data is stored in /pb_data (mounted as a Docker volume in production).
FROM alpine:3.21 AS pocketbase
RUN apk add --no-cache ca-certificates wget
COPY --from=builder /out/pocketbase /pocketbase
RUN mkdir -p /pb_data
VOLUME /pb_data
EXPOSE 8090
CMD ["/pocketbase", "serve", "--dir", "/pb_data", "--http", "0.0.0.0:8090"]
# ── runner service ───────────────────────────────────────────────────────────
# Uses Alpine (not distroless) so ffmpeg is available for WAV→MP3 transcoding
# when pocket-tts voices are used.
FROM alpine:3.21 AS runner
RUN apk add --no-cache ffmpeg ca-certificates && \
addgroup -S appgroup && adduser -S appuser -G appgroup
COPY --from=builder /out/healthcheck /healthcheck
COPY --from=builder /out/runner /runner
USER appuser
ENTRYPOINT ["/runner"]