diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 9c4fb65..aaea4bc 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -7,11 +7,12 @@ on: env: REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} + APP_IMAGE: ghcr.io/nmemmert/letter + NOTIFIER_IMAGE: ghcr.io/nmemmert/letter-notifier jobs: docker: - name: Build & push image + name: Build & push images runs-on: ubuntu-latest permissions: contents: read @@ -30,23 +31,44 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract metadata (tags & labels) - id: meta + - name: Extract metadata — app + id: meta-app uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + images: ${{ env.APP_IMAGE }} tags: | type=ref,event=branch type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=sha,prefix=sha-,format=short - - name: Build and push + - name: Extract metadata — notifier + id: meta-notifier + uses: docker/metadata-action@v5 + with: + images: ${{ env.NOTIFIER_IMAGE }} + tags: | + type=ref,event=branch + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha,prefix=sha-,format=short + + - name: Build and push — app uses: docker/build-push-action@v6 with: context: . push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max + tags: ${{ steps.meta-app.outputs.tags }} + labels: ${{ steps.meta-app.outputs.labels }} + cache-from: type=gha,scope=app + cache-to: type=gha,mode=max,scope=app + + - name: Build and push — notifier + uses: docker/build-push-action@v6 + with: + context: ./notifier + push: true + tags: ${{ steps.meta-notifier.outputs.tags }} + labels: ${{ steps.meta-notifier.outputs.labels }} + cache-from: type=gha,scope=notifier + cache-to: type=gha,mode=max,scope=notifier diff --git a/docker-compose.yml b/docker-compose.yml index dc1c345..55cccfe 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,66 +1,49 @@ services: - - # ── Web app (nginx, port 8080) ────────────────────────────────────────────── app: - build: . - image: ghcr.io/nmemmert/letter:main + image: "ghcr.io/nmemmert/letter:main" + deploy: + resources: + reservations: + memory: 128MB + cpus: "0.00" + limits: + memory: 512MB + cpus: "1.00" + restart: no + network_mode: bridge ports: - "${APP_PORT:-8080}:80" - restart: unless-stopped + volumes: [] - # ── Monthly ntfy reminder ─────────────────────────────────────────────────── notifier: - build: ./notifier - restart: unless-stopped - env_file: - - path: .env - required: false # container still starts without a .env file + image: "ghcr.io/nmemmert/letter-notifier:main" + deploy: + resources: + reservations: + memory: 64MB + cpus: "0.00" + limits: + memory: 128MB + cpus: "0.25" + restart: no + network_mode: bridge + volumes: [] environment: - # ── ntfy connection ─────────────────────────────────────────────────── - # Required: your ntfy topic — keep it unguessable, e.g. "nate-letter-k7x2" - # Subscribe at https://ntfy.sh/ or in the ntfy mobile app - NTFY_TOPIC: ${NTFY_TOPIC:?NTFY_TOPIC is required — set it in .env} - - # ntfy server (default: ntfy.sh; set to your self-hosted URL if applicable) - NTFY_URL: ${NTFY_URL:-https://ntfy.sh} - - # Bearer token for access-controlled / private topics (leave blank for public) - NTFY_TOKEN: ${NTFY_TOKEN:-} - - # Notification priority: min | low | default | high | urgent - NTFY_PRIORITY: ${NTFY_PRIORITY:-default} - - # ── Schedule ────────────────────────────────────────────────────────── - # Cron expression — default fires at 9 AM on the 1st of every month - # Format: minute hour day-of-month month day-of-week - CRON_SCHEDULE: ${CRON_SCHEDULE:-0 9 1 * *} - - # IANA timezone for the cron schedule - TZ: ${TZ:-America/Chicago} - - # ── App ─────────────────────────────────────────────────────────────── - # URL the notification deep-links back to (shown as "Open" in ntfy) - APP_URL: ${APP_URL:-http://localhost:8080} - - # Set to "true" to fire a test notification immediately on container start - NTFY_TEST_ON_START: ${NTFY_TEST_ON_START:-false} - + - NTFY_TOPIC=${NTFY_TOPIC:-} + - NTFY_URL=${NTFY_URL:-https://ntfy.sh} + - NTFY_TOKEN=${NTFY_TOKEN:-} + - NTFY_PRIORITY=${NTFY_PRIORITY:-default} + - CRON_SCHEDULE=${CRON_SCHEDULE:-0 9 1 * *} + - TZ=${TZ:-America/Chicago} + - APP_URL=${APP_URL:-http://172.16.16.106:8080} + - NTFY_TEST_ON_START=${NTFY_TEST_ON_START:-false} depends_on: - app - # ── Local dev (Vite HMR, port 5173) — run with: docker compose --profile dev up dev - dev: - image: node:20-alpine - working_dir: /app - volumes: - - .:/app - - node_modules:/app/node_modules - ports: - - "${DEV_PORT:-5173}:5173" - environment: - NODE_ENV: development - command: sh -c "npm install && npm run dev -- --host 0.0.0.0" - profiles: [dev] - -volumes: - node_modules: +x-casaos: + title: + custom: "Annual Letter" + main: app + scheme: http + hostname: "172.16.16.106" + index: /