feat: Docker + Caddy production deployment setup
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
node_modules
|
||||
dist
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
.git
|
||||
.gitignore
|
||||
*.log
|
||||
+12
-3
@@ -1,5 +1,14 @@
|
||||
# Скопируйте этот файл в .env и укажите ваши данные от Telegram бота
|
||||
VITE_TG_BOT_TOKEN="ваш_токен_бота_от_botfather"
|
||||
VITE_TG_CHAT_ID="ваш_chat_id_куда_отправлять_сообщения"
|
||||
# Supabase
|
||||
VITE_SUPABASE_URL=https://your-project.supabase.co
|
||||
VITE_SUPABASE_ANON_KEY=your-anon-key
|
||||
|
||||
# Telegram bot (lead form on landing page)
|
||||
VITE_TG_BOT_TOKEN=your-bot-token
|
||||
VITE_TG_CHAT_ID=your-chat-id
|
||||
|
||||
# Web Push / VAPID (generate with the node command in .env)
|
||||
VITE_VAPID_PUBLIC_KEY=your-vapid-public-key
|
||||
|
||||
# Deployment domain for Caddy (automatic HTTPS)
|
||||
# Use "localhost" for local dev, set to real domain in production
|
||||
DOMAIN=localhost
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{$DOMAIN:localhost} {
|
||||
root * /srv
|
||||
|
||||
# Gzip compression
|
||||
encode gzip
|
||||
|
||||
# SPA fallback — all routes serve index.html
|
||||
try_files {path} /index.html
|
||||
|
||||
# Cache static assets aggressively
|
||||
@static {
|
||||
path *.js *.css *.png *.jpg *.svg *.ico *.woff2 *.woff
|
||||
}
|
||||
header @static Cache-Control "public, max-age=31536000, immutable"
|
||||
|
||||
# Service worker must not be cached
|
||||
@sw {
|
||||
path /sw.js
|
||||
}
|
||||
header @sw Cache-Control "no-cache, no-store, must-revalidate"
|
||||
|
||||
file_server
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
# Stage 1: build
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
|
||||
COPY package*.json ./
|
||||
RUN npm ci --prefer-offline
|
||||
|
||||
COPY . .
|
||||
|
||||
ARG VITE_SUPABASE_URL
|
||||
ARG VITE_SUPABASE_ANON_KEY
|
||||
ARG VITE_TG_BOT_TOKEN
|
||||
ARG VITE_TG_CHAT_ID
|
||||
ARG VITE_VAPID_PUBLIC_KEY
|
||||
|
||||
ENV VITE_SUPABASE_URL=$VITE_SUPABASE_URL
|
||||
ENV VITE_SUPABASE_ANON_KEY=$VITE_SUPABASE_ANON_KEY
|
||||
ENV VITE_TG_BOT_TOKEN=$VITE_TG_BOT_TOKEN
|
||||
ENV VITE_TG_CHAT_ID=$VITE_TG_CHAT_ID
|
||||
ENV VITE_VAPID_PUBLIC_KEY=$VITE_VAPID_PUBLIC_KEY
|
||||
|
||||
RUN npm run build
|
||||
|
||||
# Stage 2: serve with Caddy
|
||||
FROM caddy:2-alpine
|
||||
COPY --from=builder /app/dist /srv
|
||||
COPY Caddyfile /etc/caddy/Caddyfile
|
||||
@@ -0,0 +1,29 @@
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
context: .
|
||||
args:
|
||||
VITE_SUPABASE_URL: ${VITE_SUPABASE_URL}
|
||||
VITE_SUPABASE_ANON_KEY: ${VITE_SUPABASE_ANON_KEY}
|
||||
VITE_TG_BOT_TOKEN: ${VITE_TG_BOT_TOKEN}
|
||||
VITE_TG_CHAT_ID: ${VITE_TG_CHAT_ID}
|
||||
VITE_VAPID_PUBLIC_KEY: ${VITE_VAPID_PUBLIC_KEY}
|
||||
environment:
|
||||
DOMAIN: ${DOMAIN:-localhost}
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "443:443/udp" # HTTP/3
|
||||
volumes:
|
||||
- caddy_data:/data # TLS certificates (persisted across restarts)
|
||||
- caddy_config:/config # Caddy config cache
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "http://localhost:80"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
Reference in New Issue
Block a user