chore(devops): docker-compose dev + prod, Dockerfiles, nginx, Makefile

- backend/Dockerfile: Python 3.12 slim, non-root user, WeasyPrint system deps
- backend/Dockerfile.dev: dev variant with hot-reload support
- frontend/Dockerfile: Node 20 alpine build + nginx:alpine serve
- frontend/nginx.conf: SPA routing + /api proxy to backend:8000
- docker-compose.yml: production with healthcheck
- docker-compose.dev.yml: dev with volume mounts and hot-reload
- Makefile: dev, build, up, down, logs, migrate, test, shell, prod targets
- .dockerignore for backend and frontend

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 17:19:12 +02:00
parent 1ab109b1d4
commit 6f82c56995
9 changed files with 184 additions and 0 deletions

7
frontend/.dockerignore Normal file
View File

@@ -0,0 +1,7 @@
node_modules
dist
.git
.gitignore
*.md
.env
.env.*

12
frontend/Dockerfile Normal file
View File

@@ -0,0 +1,12 @@
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json .
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

18
frontend/nginx.conf Normal file
View File

@@ -0,0 +1,18 @@
server {
listen 80;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://backend:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60s;
}
}