Add Docker infrastructure with caddy-docker-proxy
Multi-stage Dockerfile (node build → caddy:2-alpine production, node dev). Compose base + dev override for prod/dev switching via .env ENVIRONMENT flag. Makefile targets: build, up, down, restart, logs, dev, prod, clean, rebuild. Caddyfile serves static Astro output with caching and compression.
This commit is contained in:
parent
364b6602c4
commit
162d485c31
10
.dockerignore
Normal file
10
.dockerignore
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.env
|
||||||
|
*.md
|
||||||
|
!README.md
|
||||||
|
Makefile
|
||||||
|
docker-compose*.yml
|
||||||
|
.astro
|
||||||
16
Caddyfile
Normal file
16
Caddyfile
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
:80 {
|
||||||
|
root * /srv
|
||||||
|
file_server
|
||||||
|
encode gzip zstd
|
||||||
|
|
||||||
|
# SPA-style fallback for clean URLs
|
||||||
|
try_files {path} {path}/ {path}/index.html =404
|
||||||
|
|
||||||
|
# Cache static assets aggressively
|
||||||
|
@static path /_astro/* /pagefind/* /favicon.svg
|
||||||
|
header @static Cache-Control "public, max-age=31536000, immutable"
|
||||||
|
|
||||||
|
# Short cache for HTML (allows quick content updates)
|
||||||
|
@html path *.html /
|
||||||
|
header @html Cache-Control "public, max-age=3600"
|
||||||
|
}
|
||||||
38
Dockerfile
Normal file
38
Dockerfile
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# --- Build stage ---
|
||||||
|
FROM node:22-slim AS build
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install dependencies first (layer caching)
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# Copy source and build
|
||||||
|
COPY . .
|
||||||
|
ENV ASTRO_TELEMETRY_DISABLED=1
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# --- Production stage ---
|
||||||
|
FROM caddy:2-alpine AS production
|
||||||
|
|
||||||
|
COPY --from=build /app/dist /srv
|
||||||
|
COPY Caddyfile /etc/caddy/Caddyfile
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s \
|
||||||
|
CMD wget -qO- http://127.0.0.1:80/ || exit 1
|
||||||
|
|
||||||
|
# --- Dev stage ---
|
||||||
|
FROM node:22-slim AS dev
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
ENV ASTRO_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
|
EXPOSE 4321
|
||||||
|
|
||||||
|
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]
|
||||||
59
Makefile
Normal file
59
Makefile
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
include .env
|
||||||
|
export
|
||||||
|
|
||||||
|
# Compose file selection based on ENVIRONMENT
|
||||||
|
ifeq ($(ENVIRONMENT),dev)
|
||||||
|
COMPOSE_FILES := -f docker-compose.yml -f docker-compose.dev.yml
|
||||||
|
else
|
||||||
|
COMPOSE_FILES := -f docker-compose.yml
|
||||||
|
endif
|
||||||
|
|
||||||
|
DC := docker compose $(COMPOSE_FILES)
|
||||||
|
|
||||||
|
.PHONY: help build up down restart logs status clean rebuild dev prod
|
||||||
|
|
||||||
|
help: ## Show this help
|
||||||
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
|
||||||
|
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'
|
||||||
|
|
||||||
|
build: ## Build container image
|
||||||
|
$(DC) build
|
||||||
|
|
||||||
|
up: ## Start services (detached)
|
||||||
|
$(DC) up -d --build
|
||||||
|
@sleep 2
|
||||||
|
$(DC) logs --tail=20
|
||||||
|
|
||||||
|
down: ## Stop services
|
||||||
|
$(DC) down
|
||||||
|
|
||||||
|
restart: ## Restart services
|
||||||
|
$(DC) down
|
||||||
|
$(DC) up -d --build
|
||||||
|
@sleep 2
|
||||||
|
$(DC) logs --tail=20
|
||||||
|
|
||||||
|
logs: ## Show service logs
|
||||||
|
$(DC) logs -f
|
||||||
|
|
||||||
|
status: ## Show running containers
|
||||||
|
$(DC) ps
|
||||||
|
|
||||||
|
clean: ## Remove containers, images, and volumes
|
||||||
|
$(DC) down --rmi local -v
|
||||||
|
|
||||||
|
rebuild: ## Full rebuild (no cache)
|
||||||
|
$(DC) build --no-cache
|
||||||
|
$(DC) up -d
|
||||||
|
@sleep 2
|
||||||
|
$(DC) logs --tail=20
|
||||||
|
|
||||||
|
dev: ## Switch to dev mode and start
|
||||||
|
@sed -i 's/^ENVIRONMENT=.*/ENVIRONMENT=dev/' .env
|
||||||
|
@echo "Switched to dev mode"
|
||||||
|
$(MAKE) restart
|
||||||
|
|
||||||
|
prod: ## Switch to prod mode and start
|
||||||
|
@sed -i 's/^ENVIRONMENT=.*/ENVIRONMENT=prod/' .env
|
||||||
|
@echo "Switched to prod mode"
|
||||||
|
$(MAKE) restart
|
||||||
21
docker-compose.dev.yml
Normal file
21
docker-compose.dev.yml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
services:
|
||||||
|
docs:
|
||||||
|
build:
|
||||||
|
target: dev
|
||||||
|
volumes:
|
||||||
|
- ./src:/app/src
|
||||||
|
- ./public:/app/public
|
||||||
|
- ./astro.config.mjs:/app/astro.config.mjs
|
||||||
|
environment:
|
||||||
|
- VITE_HMR_HOST=${DOMAIN}
|
||||||
|
labels:
|
||||||
|
caddy: ${DOMAIN}
|
||||||
|
caddy.reverse_proxy: "{{upstreams 4321}}"
|
||||||
|
caddy.reverse_proxy.flush_interval: "-1"
|
||||||
|
caddy.reverse_proxy.transport: http
|
||||||
|
caddy.reverse_proxy.transport.read_timeout: "0"
|
||||||
|
caddy.reverse_proxy.transport.write_timeout: "0"
|
||||||
|
caddy.reverse_proxy.transport.keepalive: 5m
|
||||||
|
caddy.reverse_proxy.transport.keepalive_idle_conns: "10"
|
||||||
|
caddy.reverse_proxy.stream_timeout: 24h
|
||||||
|
caddy.reverse_proxy.stream_close_delay: 5s
|
||||||
16
docker-compose.yml
Normal file
16
docker-compose.yml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
services:
|
||||||
|
docs:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
target: production
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- caddy
|
||||||
|
labels:
|
||||||
|
caddy: ${DOMAIN}
|
||||||
|
caddy.reverse_proxy: "{{upstreams 80}}"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
caddy:
|
||||||
|
external: true
|
||||||
Loading…
x
Reference in New Issue
Block a user