feat: add Docker deployment (Dockerfile, compose, Caddyfile)

Multi-stage Dockerfile builds SvelteKit then runs a lean production image. docker-compose.yml wires up MariaDB with health checks, the app, and Caddy for TLS termination. Caddyfile uses SITE_DOMAIN env var with localhost fallback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-26 12:49:42 -05:00
co-authored by Claude Sonnet 4.6
parent c6b7d4d4eb
commit b0bd8277a8
3 changed files with 73 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
{$SITE_DOMAIN:localhost} {
reverse_proxy app:3000
}
+18
View File
@@ -0,0 +1,18 @@
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:22-alpine
WORKDIR /app
COPY --from=builder /app/build ./build
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
COPY --from=builder /app/drizzle ./drizzle
COPY --from=builder /app/scripts ./scripts
ENV NODE_ENV=production
EXPOSE 3000
CMD ["node", "build"]
+52
View File
@@ -0,0 +1,52 @@
services:
db:
image: mariadb:11
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-fosterflow}
MYSQL_DATABASE: fosterflow
MYSQL_USER: fosterflow
MYSQL_PASSWORD: ${DB_PASSWORD:-fosterflow}
volumes:
- db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
app:
build: .
restart: unless-stopped
depends_on:
db:
condition: service_healthy
environment:
DATABASE_URL: mysql://fosterflow:${DB_PASSWORD:-fosterflow}@db:3306/fosterflow
SESSION_SECRET: ${SESSION_SECRET:-change-me-in-production}
PUBLIC_SITE_URL: ${PUBLIC_SITE_URL:-http://localhost:3000}
UPLOAD_DIR: /app/uploads
PORT: 3000
env_file:
- .env
ports:
- "3000:3000"
volumes:
- uploads:/app/uploads
caddy:
image: caddy:2-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
volumes:
db_data:
uploads:
caddy_data:
caddy_config: