feat: Portainer-compatible stack — no build step, bind-mount web service, LF-enforced shell scripts

This commit is contained in:
Lago
2026-04-17 18:41:41 +02:00
parent 73aa72b7ee
commit 5865f796ce
3 changed files with 31 additions and 17 deletions
+2
View File
@@ -0,0 +1,2 @@
* text=auto
*.sh text eol=lf
+20 -17
View File
@@ -3,13 +3,12 @@ name: mc-cars
############################################################ ############################################################
# MC Cars - fully Dockerized self-hosted Supabase + web # MC Cars - fully Dockerized self-hosted Supabase + web
# #
# Portability contract: # Host deployment root:
# - ALL runtime state lives under ./data (bind mounts). # - ALL bind mounts resolve under /mnt/user/appdata/mc-cars.
# - ALL config lives under this folder (supabase/, frontend/, .env). # - Runtime state lives under /mnt/user/appdata/mc-cars/data.
# - Copying the "MC Cars" folder to another host and running # - Config lives under /mnt/user/appdata/mc-cars/{supabase,frontend}.
# docker compose up -d # - Deploy this stack from that host folder so Docker sees the same
# reproduces the stack bit-for-bit. No named volumes, no # absolute paths on every restart.
# absolute paths, no external dependencies.
############################################################ ############################################################
networks: networks:
@@ -43,9 +42,9 @@ services:
POSTGRES_DB: ${POSTGRES_DB} POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes: volumes:
- ./data/db:/var/lib/postgresql/data - /mnt/user/appdata/mc-cars/data/db:/var/lib/postgresql/data
- ./supabase/migrations/00-run-init.sh:/docker-entrypoint-initdb.d/00-run-init.sh:ro - /mnt/user/appdata/mc-cars/supabase/migrations/00-run-init.sh:/docker-entrypoint-initdb.d/00-run-init.sh:ro
- ./supabase/migrations/01-init.sql:/sql/01-init.sql:ro - /mnt/user/appdata/mc-cars/supabase/migrations/01-init.sql:/sql/01-init.sql:ro
ports: ports:
- "5432:5432" - "5432:5432"
networks: [mccars] networks: [mccars]
@@ -140,7 +139,7 @@ services:
ENABLE_IMAGE_TRANSFORMATION: "true" ENABLE_IMAGE_TRANSFORMATION: "true"
IMGPROXY_URL: http://imgproxy:5001 IMGPROXY_URL: http://imgproxy:5001
volumes: volumes:
- ./data/storage:/var/lib/storage - /mnt/user/appdata/mc-cars/data/storage:/var/lib/storage
networks: [mccars] networks: [mccars]
logging: { driver: json-file, options: { max-size: "10m", max-file: "3" } } logging: { driver: json-file, options: { max-size: "10m", max-file: "3" } }
@@ -154,7 +153,7 @@ services:
IMGPROXY_USE_ETAG: "true" IMGPROXY_USE_ETAG: "true"
IMGPROXY_ENABLE_WEBP_DETECTION: "true" IMGPROXY_ENABLE_WEBP_DETECTION: "true"
volumes: volumes:
- ./data/storage:/var/lib/storage - /mnt/user/appdata/mc-cars/data/storage:/var/lib/storage
networks: [mccars] networks: [mccars]
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
@@ -208,8 +207,8 @@ services:
ADMIN_EMAIL: ${ADMIN_EMAIL} ADMIN_EMAIL: ${ADMIN_EMAIL}
ADMIN_PASSWORD: ${ADMIN_PASSWORD} ADMIN_PASSWORD: ${ADMIN_PASSWORD}
volumes: volumes:
- ./supabase/migrations/post-boot.sql:/sql/post-boot.sql:ro - /mnt/user/appdata/mc-cars/supabase/migrations/post-boot.sql:/sql/post-boot.sql:ro
- ./supabase/migrations/02-leads.sql:/sql/02-leads.sql:ro - /mnt/user/appdata/mc-cars/supabase/migrations/02-leads.sql:/sql/02-leads.sql:ro
entrypoint: ["sh","-c"] entrypoint: ["sh","-c"]
command: command:
- | - |
@@ -272,7 +271,7 @@ services:
KONG_NGINX_PROXY_PROXY_BUFFER_SIZE: 160k KONG_NGINX_PROXY_PROXY_BUFFER_SIZE: 160k
KONG_NGINX_PROXY_PROXY_BUFFERS: 64 160k KONG_NGINX_PROXY_PROXY_BUFFERS: 64 160k
volumes: volumes:
- ./supabase/kong.yml:/home/kong/kong.yml:ro - /mnt/user/appdata/mc-cars/supabase/kong.yml:/home/kong/kong.yml:ro
ports: ports:
- "54321:8000/tcp" - "54321:8000/tcp"
- "54443:8443/tcp" - "54443:8443/tcp"
@@ -311,10 +310,10 @@ services:
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# Public website (nginx + static assets). Anon key injected at boot. # Public website (nginx + static assets). Anon key injected at boot.
# No build step — Portainer-compatible (image + bind mounts).
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
web: web:
build: image: nginx:1.27-alpine
context: ./frontend
container_name: mccars-web container_name: mccars-web
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
@@ -322,6 +321,10 @@ services:
environment: environment:
SUPABASE_URL: ${SUPABASE_PUBLIC_URL} SUPABASE_URL: ${SUPABASE_PUBLIC_URL}
SUPABASE_ANON_KEY: ${ANON_KEY} SUPABASE_ANON_KEY: ${ANON_KEY}
volumes:
- /mnt/user/appdata/mc-cars/frontend:/usr/share/nginx/html:ro
- /mnt/user/appdata/mc-cars/frontend/nginx.conf:/etc/nginx/conf.d/default.conf:ro
- /mnt/user/appdata/mc-cars/frontend/99-config.sh:/docker-entrypoint.d/99-config.sh:ro
ports: ports:
- "8080:80" - "8080:80"
networks: [mccars] networks: [mccars]
+9
View File
@@ -0,0 +1,9 @@
#!/bin/sh
set -eu
cat > /usr/share/nginx/html/config.js <<EOF
window.MCCARS_CONFIG = {
SUPABASE_URL: "${SUPABASE_URL:-http://localhost:8000}",
SUPABASE_ANON_KEY: "${SUPABASE_ANON_KEY:-}"
};
EOF
exec nginx -g "daemon off;"