Rebuild deploy process on the project template

- Dockerfile: deps → builder → pb-downloader → runner stages, cross-arch
  (BUILDPLATFORM node stages, TARGETARCH PocketBase binary), Debian slim
  runner, VOLUME /app/pb_data, dual healthcheck, docker-entrypoint.sh
- docker-entrypoint.sh: bash supervisor replacing scripts/run-all.mjs
- Makefile: build-production (multi-arch push from git remote),
  build-check, build-check-local
- deploy.sh [tag]: make build-production then ansible-playbook with tag
- drop .env/.env.example (credentials live in ansible/vars/default.yml)
This commit is contained in:
2026-09-03 10:24:48 +05:30
parent 757ec8aee2
commit 0ff90cde27
9 changed files with 202 additions and 212 deletions
+67 -40
View File
@@ -1,61 +1,88 @@
# syntax=docker/dockerfile:1
# The Great Bear — single image running TanStack Start (site) + PocketBase (CMS/API)
ARG NODE_VERSION=22
ARG PB_VERSION=0.40.2
# ------------------------------------------------------------------------------
# Stage 1: Install frontend dependencies (Native execution on host architecture)
# ------------------------------------------------------------------------------
FROM --platform=$BUILDPLATFORM node:lts-trixie-slim AS deps
WORKDIR /work
# ---------- Stage 1: build the TanStack Start app ----------
FROM node:${NODE_VERSION}-alpine AS build
WORKDIR /app
COPY app/package.json app/package-lock.json* ./
RUN --mount=type=cache,target=/root/.npm \
npm ci
COPY app/package.json app/package-lock.json ./
RUN npm ci --no-audit --no-fund
# ------------------------------------------------------------------------------
# Stage 2: Build the TanStack Start frontend (Native execution on host architecture)
# ------------------------------------------------------------------------------
FROM --platform=$BUILDPLATFORM node:lts-trixie-slim AS builder
WORKDIR /work
COPY --from=deps /work/node_modules ./node_modules
COPY app/ ./
ENV NODE_ENV=production
RUN npm run build
# ---------- Stage 2: runtime ----------
FROM node:${NODE_VERSION}-alpine AS runtime
ARG PB_VERSION
# ------------------------------------------------------------------------------
# Stage 3: Fetch PocketBase binary for target architecture (Native host downloader)
# ------------------------------------------------------------------------------
FROM --platform=$BUILDPLATFORM alpine:3.20 AS pb-downloader
ARG TARGETARCH
ARG PB_VERSION=0.40.2
ENV NODE_ENV=production \
PORT=3000 \
PB_URL=http://127.0.0.1:8090
RUN apk add --no-cache curl unzip ca-certificates \
&& case "${TARGETARCH}" in \
amd64) PB_ARCH="amd64" ;; \
arm64) PB_ARCH="arm64" ;; \
arm) PB_ARCH="armv7" ;; \
*) echo "Unsupported target architecture: ${TARGETARCH}" >&2; exit 1 ;; \
esac \
&& curl -fsSL -o /tmp/pb.zip "https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/pocketbase_${PB_VERSION}_linux_${PB_ARCH}.zip" \
&& unzip /tmp/pb.zip -d /tmp/pb \
&& chmod +x /tmp/pb/pocketbase \
&& rm -f /tmp/pb.zip
# ------------------------------------------------------------------------------
# Stage 4: Production runner (Target architecture)
# ------------------------------------------------------------------------------
FROM node:lts-trixie-slim AS runner
LABEL maintainer="Amritanshu <docker@tanshu.com>"
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
RUN apk add --no-cache curl unzip
# Copy PocketBase binary and migrations
COPY --from=pb-downloader /tmp/pb/pocketbase /app/pocketbase
COPY pb/migrations /app/pb_migrations
RUN mkdir -p /app/pb_public
# Site server build output
COPY --from=build /app/.output ./.output
# Copy compiled frontend application
COPY --from=builder /work/.output /app/.output
# Content seed (shared with the frontend fallback) + process supervisor
COPY app/src/data/content.json ./scripts/content.json
COPY scripts/seed.mjs scripts/run-all.mjs ./scripts/
# Copy content seed + entrypoint script
COPY app/src/data/content.json /app/scripts/content.json
COPY scripts/seed.mjs /app/scripts/seed.mjs
COPY docker-entrypoint.sh /app/docker-entrypoint.sh
RUN chmod +x /app/docker-entrypoint.sh
# PocketBase schema migrations
COPY pb/migrations ./pb_migrations
RUN mkdir -p pb_public
# Environment variables
ENV NODE_ENV=production \
PORT=3000 \
HOST=0.0.0.0 \
PB_DATA_DIR=/app/pb_data
# PocketBase binary (static Go binary, runs fine on Alpine)
RUN case "${TARGETARCH:-amd64}" in \
arm64) PB_ARCH=arm64 ;; \
*) PB_ARCH=amd64 ;; \
esac \
&& curl -fsSL -o /tmp/pb.zip \
"https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/pocketbase_${PB_VERSION}_linux_${PB_ARCH}.zip" \
&& unzip -o /tmp/pb.zip pocketbase -d /app \
&& chmod +x /app/pocketbase \
&& rm /tmp/pb.zip \
&& mkdir -p /app/pb_data
# Runs as root so the Ansible-managed bind mount (/var/lib/greatbear/pb_data)
# is writable regardless of host-side ownership.
# Persistent data volume for PocketBase SQLite database and file storage
VOLUME ["/app/pb_data"]
# Port 3000: TanStack Start Web Application
# Port 8090: PocketBase REST API & Admin UI
EXPOSE 3000 8090
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=5 \
CMD curl -fsS http://127.0.0.1:8090/api/health -o /dev/null || exit 1
# Health check for both PocketBase and frontend server
HEALTHCHECK --interval=15s --timeout=3s --start-period=5s --retries=3 \
CMD curl -fsS http://127.0.0.1:8090/api/health > /dev/null && curl -fsS http://127.0.0.1:3000 > /dev/null || exit 1
CMD ["node", "scripts/run-all.mjs"]
ENTRYPOINT ["/app/docker-entrypoint.sh"]