Розгортання проєкту

Повний цикл контейнеризації та виведення в інтернет по HTTPS без відкриття вхідних портів (80/443). Трафік іде через захищений тунель Cloudflare до reverse-proxy (Caddy) та бекенду.

Етап 1: Мережева інфраструктура (Cloudflare)

  1. Домен: Паркуємо домен на Cloudflare (зміна NS-записів у реєстратора).
  2. HTTPS: У панелі Cloudflare перейди до SSL/TLS ➜ Edge Certificates та увімкни Always Use HTTPS. Режим шифрування (Overview) має бути Flexible або Full.
  3. Тунель: Перейди до Zero Trust ➜ Networks ➜ Tunnels, створи новий тунель. Збережи токен тунелю. У вкладці Public Hostname додай домен і вкажи Service: http://frontend:80.

Етап 2: Структура директорій

Проєктна структура
project_root/
├── .env                # СТВОРИТИ (з токеном тунелю)
├── backend/
│   ├── requirements.txt
│   ├── ...
│   └── Dockerfile      
├── frontend/
│   ├── package.json
│   ├── ...
│   ├── Caddyfile       
│   └── Dockerfile      
└── docker-compose.yml  

Етап 3: .env файл

.env
TUNNEL_TOKEN=твій_токен_від_cloudflare

Етап 4: Backend Dockerfile

Важливо: Бекенд (Uvicorn/Gunicorn/Flask) має слухати 0.0.0.0. Прив'язка до localhost закриє доступ для Caddy.
backend/Dockerfile
FROM python:3.11-slim
WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

# Приклад команди запуску. ЗАМІНИ НА СВОЮ.
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Етап 5: Frontend (Caddy)

Створи файл роутингу, який вирішує проблему CORS:

frontend/Caddyfile
:80 {
    # Роздача статики SPA
    root * /srv
    file_server
    try_files {path} /index.html

    # Проксіювання API-запитів до бекенду
    handle /api/* {
        reverse_proxy backend:8000
    }
}

Створи багатоетапний Dockerfile:

frontend/Dockerfile
# Етап збірки Node.js
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Етап вебсервера (Caddy)
FROM caddy:alpine
COPY --from=builder /app/dist /srv
COPY Caddyfile /etc/caddy/Caddyfile
EXPOSE 80

Етап 6: Docker Compose & Volumes

Увага: Дані всередині контейнера є тимчасовими. Для збереження файлів (бази SQLite, uploads, logs) використовуй volumes. У Python коді зберігай персистентні дані виключно в директорії /app/data.
docker-compose.yml
version: '3.8'

services:
  backend:
    build: ./backend
    restart: unless-stopped
    volumes:
      # Іменований том монтуємо в папку /app/data всередині контейнера
      - backend_data:/app/data

  frontend:
    build: ./frontend
    restart: unless-stopped
    depends_on:
      - backend

  cloudflared:
    image: cloudflare/cloudflared:latest
    command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}
    restart: unless-stopped
    depends_on:
      - frontend

# Оголошення тома для збереження даних
volumes:
  backend_data:

Етап 7: Запуск

Terminal
docker compose up -d --build

Переконайся, що статус тунелю Healthy, і перевір домен.