From 17c766c27f9bac34eae6e530bac024bcd2267522 Mon Sep 17 00:00:00 2001 From: kawa Date: Mon, 9 Mar 2026 21:17:00 +0100 Subject: [PATCH] Added Docker workflow --- .dockerignore | 36 ++++++++++++++++++++++++ .gitea/workflows/docker.yml | 47 +++++++++++++++++++++++++++++++ Dockerfile | 47 +++++++++++++++++++++++++++++++ docker-compose.yml | 56 +++++++++++++++++++++++++++++++++++++ 4 files changed, 186 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitea/workflows/docker.yml create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f025358 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,36 @@ +# Dependencies +node_modules + +# Next.js build output (rebuilt in Docker) +.next + +# Local env files (pass secrets via Docker env, not baked into image) +.env.local +.env*.local + +# Dev / editor artifacts +.git +.gitignore +*.md +.vscode +.idea + +# OS +.DS_Store +Thumbs.db + +# Logs +*.log +npm-debug.log* + +# Data directories (mounted as volumes) +data +mc-data +backups + +# Test / CI +coverage +.nyc_output + +# Misc +*.tsbuildinfo diff --git a/.gitea/workflows/docker.yml b/.gitea/workflows/docker.yml new file mode 100644 index 0000000..8307ee5 --- /dev/null +++ b/.gitea/workflows/docker.yml @@ -0,0 +1,47 @@ +name: Build & Push Docker Image + +on: + push: + tags: + - "v*" # triggers on v0.1.0, v1.0.0, etc. + workflow_dispatch: # allow manual trigger from Gitea UI + +env: + REGISTRY: git.azuze.fr + IMAGE: git.azuze.fr/kawa/cubeadmin + +jobs: + build-and-push: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Extract version tag + id: meta + run: | + TAG="${GITHUB_REF_NAME}" # e.g. v0.1.0 + VERSION="${TAG#v}" # strip leading v → 0.1.0 + echo "tag=${TAG}" >> $GITHUB_OUTPUT + echo "version=${VERSION}" >> $GITHUB_OUTPUT + + - name: Log in to Gitea container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ secrets.REGISTRY_USER }} + password: ${{ secrets.REGISTRY_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: | + ${{ env.IMAGE }}:latest + ${{ env.IMAGE }}:${{ steps.meta.outputs.version }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7224b0e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +# ─── Stage 1: Install dependencies ─────────────────────────────────────────── +FROM oven/bun:1 AS deps +WORKDIR /app + +COPY package.json bun.lock ./ +RUN bun install --frozen-lockfile + +# ─── Stage 2: Build Next.js ────────────────────────────────────────────────── +FROM oven/bun:1 AS builder +WORKDIR /app + +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +RUN bun run build + +# ─── Stage 3: Production runner ────────────────────────────────────────────── +FROM oven/bun:1-slim AS runner +WORKDIR /app + +ENV NODE_ENV=production + +# Copy runtime dependencies +COPY --from=builder /app/node_modules ./node_modules + +# Copy Next.js build output +COPY --from=builder /app/.next ./.next +COPY --from=builder /app/public ./public + +# Copy server entry point and all runtime source files +COPY --from=builder /app/server.ts ./server.ts +COPY --from=builder /app/lib ./lib +COPY --from=builder /app/drizzle ./drizzle +COPY --from=builder /app/tsconfig.json ./tsconfig.json +COPY --from=builder /app/next.config.ts ./next.config.ts + +# Pre-create data directory (SQLite db + uploads land here) +RUN mkdir -p /app/data + +EXPOSE 3000 + +# Volumes for persistent data +# Mount your Minecraft server directory to /mc-server +# Mount your backups directory to /backups +VOLUME ["/app/data", "/mc-server", "/backups"] + +CMD ["bun", "--bun", "run", "server.ts"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7862661 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,56 @@ +services: + cubeadmin: + image: cubeadmin:latest + # To build locally instead of pulling, uncomment: + # build: . + container_name: cubeadmin + restart: unless-stopped + ports: + - "${PORT:-3000}:3000" + environment: + NODE_ENV: production + PORT: 3000 + + # ── Auth ──────────────────────────────────────────────────── + BETTER_AUTH_URL: ${BETTER_AUTH_URL} + BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET} + + # ── Email / SMTP ──────────────────────────────────────────── + SMTP_HOST: ${SMTP_HOST:-} + SMTP_PORT: ${SMTP_PORT:-587} + SMTP_SECURE: ${SMTP_SECURE:-false} + SMTP_USER: ${SMTP_USER:-} + SMTP_PASS: ${SMTP_PASS:-} + EMAIL_FROM: ${EMAIL_FROM:-CubeAdmin } + + # ── Minecraft / RCON ──────────────────────────────────────── + MC_SERVER_PATH: /mc-server + MC_RCON_HOST: ${MC_RCON_HOST:-127.0.0.1} + MC_RCON_PORT: ${MC_RCON_PORT:-25575} + MC_RCON_PASSWORD: ${MC_RCON_PASSWORD} + + # ── Database ──────────────────────────────────────────────── + DATABASE_PATH: /app/data/cubeadmin.db + + # ── Security ──────────────────────────────────────────────── + TRUSTED_ORIGINS: ${TRUSTED_ORIGINS} + RATE_LIMIT_RPM: ${RATE_LIMIT_RPM:-100} + + # ── First admin (only used on first startup) ───────────────── + INITIAL_ADMIN_EMAIL: ${INITIAL_ADMIN_EMAIL:-admin@example.com} + INITIAL_ADMIN_NAME: ${INITIAL_ADMIN_NAME:-Administrator} + INITIAL_ADMIN_PASSWORD: ${INITIAL_ADMIN_PASSWORD:-ChangeMe123!} + + # ── Optional ──────────────────────────────────────────────── + BLUEMAP_URL: ${BLUEMAP_URL:-} + + volumes: + # SQLite database + uploaded files + - cubeadmin-data:/app/data + # Minecraft server files (set MC_DATA_PATH in .env to override host path) + - ${MC_DATA_PATH:-./mc-data}:/mc-server + # Backups + - ${BACKUPS_PATH:-./backups}:/backups + +volumes: + cubeadmin-data: