From e31990fdfdf601ae8306504676cae6043d8c3032 Mon Sep 17 00:00:00 2001 From: Christomatt Date: Sat, 31 Jan 2026 04:13:50 +0100 Subject: [PATCH] Add GitHub Actions workflow for Docker image builds - Build and push to GHCR on every push to main - Multi-platform support (amd64, arm64) - Root-level docker-compose.yml using pre-built image - Users can now deploy without cloning repo --- .github/workflows/docker.yml | 71 ++++++++++++++++++++++ docker-compose.yml | 111 +++++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 .github/workflows/docker.yml create mode 100644 docker-compose.yml diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..4e4ff77 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,71 @@ +name: Build and Push Docker Image + +on: + push: + branches: + - main + tags: + - 'v*' + pull_request: + branches: + - main + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + attestations: write + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha,prefix=,suffix=,format=short + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push Docker image + id: push + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + platforms: linux/amd64,linux/arm64 + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v1 + with: + subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..d34416f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,111 @@ +# Synapsis - Docker Compose +# One-command deployment: docker-compose up -d +# +# Uses pre-built image from GitHub Container Registry +# Users just download this file + Caddyfile + .env, no git clone needed +# +# Services: +# - Synapsis Next.js application (pre-built image) +# - PostgreSQL database (persistent storage) +# - Caddy reverse proxy with automatic SSL + +version: "3.8" + +services: + # ============================================ + # PostgreSQL Database + # ============================================ + postgres: + image: postgres:16-alpine + container_name: synapsis-db + restart: unless-stopped + environment: + POSTGRES_USER: ${DB_USER:-synapsis} + POSTGRES_PASSWORD: ${DB_PASSWORD:-changeme} + POSTGRES_DB: ${DB_NAME:-synapsis} + PGDATA: /var/lib/postgresql/data/pgdata + volumes: + - postgres_data:/var/lib/postgresql/data + networks: + - synapsis-network + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-synapsis} -d ${DB_NAME:-synapsis}"] + interval: 10s + timeout: 5s + retries: 5 + + # ============================================ + # Synapsis Application (Pre-built Image) + # ============================================ + app: + image: ghcr.io/cyph3rasi/synapsis:latest + container_name: synapsis-app + restart: unless-stopped + environment: + DATABASE_URL: postgresql://${DB_USER:-synapsis}:${DB_PASSWORD:-changeme}@postgres:5432/${DB_NAME:-synapsis} + AUTH_SECRET: ${AUTH_SECRET} + NEXT_PUBLIC_NODE_DOMAIN: ${DOMAIN:-localhost} + ADMIN_EMAILS: ${ADMIN_EMAILS} + STORAGE_ENDPOINT: ${STORAGE_ENDPOINT} + STORAGE_REGION: ${STORAGE_REGION:-us-east-1} + STORAGE_BUCKET: ${STORAGE_BUCKET} + STORAGE_ACCESS_KEY: ${STORAGE_ACCESS_KEY} + STORAGE_SECRET_KEY: ${STORAGE_SECRET_KEY} + STORAGE_PUBLIC_BASE_URL: ${STORAGE_PUBLIC_BASE_URL} + BOT_MAX_PER_USER: ${BOT_MAX_PER_USER:-5} + NODE_ENV: production + volumes: + - uploads_data:/app/uploads + networks: + - synapsis-network + depends_on: + postgres: + condition: service_healthy + healthcheck: + test: ["CMD", "wget", "-q", "--spider", "http://localhost:3000/api/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # ============================================ + # Caddy Reverse Proxy (Automatic SSL) + # ============================================ + caddy: + image: caddy:2-alpine + container_name: synapsis-caddy + restart: unless-stopped + ports: + - "80:80" + - "443:443" + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile:ro + - caddy_data:/data + - caddy_config:/config + networks: + - synapsis-network + depends_on: + app: + condition: service_healthy + environment: + - DOMAIN=${DOMAIN:-localhost} + +# ============================================ +# Persistent Volumes +# ============================================ +volumes: + postgres_data: + driver: local + uploads_data: + driver: local + caddy_data: + driver: local + caddy_config: + driver: local + +# ============================================ +# Networks +# ============================================ +networks: + synapsis-network: + driver: bridge