Jak używać Traefik jako zaawansowanego reverse proxy Jak konfigurować service discovery Jak używać labels w kontenerach Jak monitorować aplikacje przez dashboard
- Jak używać Traefik jako zaawansowanego reverse proxy
- Jak konfigurować service discovery
- Jak używać labels w kontenerach
- Jak monitorować aplikacje przez dashboard
podman info
podman-compose --version
docker compose version
# Zaktualizuj system
sudo apt update && sudo apt upgrade -y
# Zainstaluj Podman
sudo apt install podman -y
# Zainstaluj podman-compose (potrzebne do docker-compose.yml)
pip3 install podman-compose
# Lub alternatywnie docker-compose
sudo apt install docker-compose-plugin -y
# Zaktualizuj system
sudo dnf upgrade --refresh -y
# Zainstaluj Podman
sudo dnf install podman -y
# Zainstaluj podman-compose (potrzebne do docker-compose.yml)
pip3 install --user podman-compose
# Upewnij się, że ~/.local/bin jest w PATH (jeśli nie, dodaj do ~/.bashrc lub ~/.zshrc)
export PATH=$HOME/.local/bin:$PATH
# (Opcjonalnie) Zainstaluj docker-compose-plugin z Dockerem
sudo dnf install dnf-plugins-core -y
sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
sudo dnf install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
# (Opcjonalnie) Włącz Docker jeśli został zainstalowany
sudo systemctl enable --now docker
mkdir -p ~/traefik-setup/{sklep,blog,api,portfolio}
cd ~/traefik-setup
nano docker-compose.yml
version: '3.8'
networks:
web:
driver: bridge
services:
# Traefik - reverse proxy z dashboard
traefik:
image: traefik:v3.0
container_name: traefik
restart: unless-stopped
command:
# Włącz API i dashboard
- "--api.insecure=true"
- "--api.dashboard=true"
# Konfiguracja dostawców
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=web"
# Entrypoints (porty wejściowe)
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
# SSL z Let's Encrypt
- "--certificatesresolvers.myresolver.acme.httpchallenge=true"
- "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.myresolver.acme.email=twoj@email.com"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
# Przekierowanie HTTP na HTTPS
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
ports:
- "80:80"
- "443:443"
- "8082:8080" # Dashboard
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./letsencrypt:/letsencrypt"
networks:
- web
labels:
- "traefik.enable=true"
# Dashboard
- "traefik.http.routers.dashboard.rule=Host(`dashboard.twoja-domena.pl`)"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.tls.certresolver=myresolver"
# Sklep Flask App
sklep:
build: ./sklep
container_name: sklep
restart: unless-stopped
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.sklep.rule=Host(`sklep.twoja-domena.pl`)"
- "traefik.http.routers.sklep.entrypoints=websecure"
- "traefik.http.routers.sklep.tls.certresolver=myresolver"
- "traefik.http.services.sklep.loadbalancer.server.port=5000"
# Blog Flask App
blog:
build: ./blog
container_name: blog
restart: unless-stopped
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.blog.rule=Host(`blog.twoja-domena.pl`)"
- "traefik.http.routers.blog.entrypoints=websecure"
- "traefik.http.routers.blog.tls.certresolver=myresolver"
- "traefik.http.services.blog.loadbalancer.server.port=5000"
# API Flask App
api:
build: ./api
container_name: api
restart: unless-stopped
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`api.twoja-domena.pl`)"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls.certresolver=myresolver"
- "traefik.http.services.api.loadbalancer.server.port=5000"
# CORS dla API
- "traefik.http.routers.api.middlewares=cors"
- "traefik.http.middlewares.cors.headers.accesscontrolallowmethods=GET,OPTIONS,PUT,POST,DELETE"
- "traefik.http.middlewares.cors.headers.accesscontrolalloworigin=*"
- "traefik.http.middlewares.cors.headers.accesscontrolmaxage=100"
- "traefik.http.middlewares.cors.headers.addvaryheader=true"
# Portfolio Flask App
portfolio:
build: ./portfolio
container_name: portfolio
restart: unless-stopped
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.portfolio.rule=Host(`portfolio.twoja-domena.pl`)"
- "traefik.http.routers.portfolio.entrypoints=websecure"
- "traefik.http.routers.portfolio.tls.certresolver=myresolver"
- "traefik.http.services.portfolio.loadbalancer.server.port=5000"
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/')
def home():
return jsonify({
"message": "Witaj w moim sklepie!",
"version": "1.0",
"endpoints": ["/", "/produkty", "/kategorie"]
})
@app.route('/produkty')
def produkty():
return jsonify({
"produkty": [
{"id": 1, "nazwa": "Laptop", "cena": 2999},
{"id": 2, "nazwa": "Telefon", "cena": 1299}
]
})
@app.route('/kategorie')
def kategorie():
return jsonify({
"kategorie": ["Elektronika", "Ubrania", "Książki"]
})
if __name__ == '__main__':
app.run(debug=True)
Flask==2.3.3
gunicorn==21.2.0
flask-cors==4.0.0
FROM python:3.11-slim
WORKDIR /app
# Kopiuj requirements i zainstaluj zależności
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Kopiuj aplikację
COPY . .
EXPOSE 5000
# Używaj Gunicorn do produkcji
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "2", "app:app"]
version: '3.8'
networks:
web:
driver: bridge
services:
traefik:
image: traefik:v3.0
container_name: traefik
restart: unless-stopped
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
- "8082:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- web
sklep:
build: ./sklep
container_name: sklep
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.sklep.rule=PathPrefix(`/sklep`)"
- "traefik.http.services.sklep.loadbalancer.server.port=5000"
blog:
build: ./blog
container_name: blog
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.blog.rule=PathPrefix(`/blog`)"
- "traefik.http.services.blog.loadbalancer.server.port=5000"
api:
build: ./api
container_name: api
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=PathPrefix(`/api`)"
- "traefik.http.services.api.loadbalancer.server.port=5000"
portfolio:
build: ./portfolio
container_name: portfolio
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.portfolio.rule=PathPrefix(`/portfolio`)"
- "traefik.http.services.portfolio.loadbalancer.server.port=5000"
Do automatycznych testów środowiska możesz użyć playbooka:
ansible-playbook ansible/test.yml
Testuje on:
- dostępność dashboardu Traefika (domyślnie na http://localhost:8083/dashboard/ lub http://localhost:8081/dashboard/)
- dostępność usług projekt1 i projekt2 przez Traefik
- nagłówek Server dla dashboardu Traefika
up:
podman-compose -f docker-compose.yml up -d
down:
podman-compose -f docker-compose.yml down
logs:
podman-compose -f docker-compose.yml logs
test:
ansible-playbook ansible/test.yml
ps:
podman ps -a
restart:
podman-compose -f docker-compose.yml down && podman-compose -f docker-compose.yml up -d
- Jeśli dashboard nie działa na
/dashboard/
, sprawdź porty i ścieżki w traefik.yml. - Sprawdź logi Traefika:
make logs
- Sprawdź, czy backendy odpowiadają na
/projekt1
i/projekt2
.
nano ~/manage-traefik.sh
#!/bin/bash
case $1 in
start)
echo "🚀 Uruchamianie wszystkich serwisów..."
cd ~/traefik-setup
docker-compose up -d
;;
stop)
echo "🛑 Zatrzymywanie wszystkich serwisów..."
cd ~/traefik-setup
docker-compose down
;;
restart)
echo "🔄 Restart wszystkich serwisów..."
cd ~/traefik-setup
docker-compose restart
;;
rebuild)
echo "🔨 Rebuild aplikacji: $2"
cd ~/traefik-setup
docker-compose build $2
docker-compose up -d $2
;;
logs)
echo "📋 Logi serwisu: $2"
cd ~/traefik-setup
docker-compose logs -f $2
;;
status)
echo "📊 Status wszystkich serwisów:"
cd ~/traefik-setup
docker-compose ps
;;
dashboard)
echo "🖥️ Dashboard dostępny na:"
echo "http://$(curl -s ifconfig.me):8082"
;;
*)
echo "Użycie: $0 {start|stop|restart|rebuild|logs|status|dashboard}"
echo "Przykłady:"
echo " $0 start"
echo " $0 rebuild sklep"
echo " $0 logs api"
;;
esac
chmod +x ~/manage-traefik.sh
./manage-traefik.sh start # Uruchom wszystko
./manage-traefik.sh rebuild sklep # Przebuduj sklep
./manage-traefik.sh logs api # Zobacz logi API
./manage-traefik.sh dashboard # Pokaż URL dashboard
# W docker-compose.yml możesz skalować serwisy:
sklep:
# ... existing config
deploy:
replicas: 3
labels:
# Traefik automatycznie load-balancuje między replikami
- "traefik.http.services.sklep.loadbalancer.server.port=5000"
# Dodaj middleware do limitowania requestów
labels:
- "traefik.http.routers.api.middlewares=api-ratelimit"
- "traefik.http.middlewares.api-ratelimit.ratelimit.burst=100"
- "traefik.http.middlewares.api-ratelimit.ratelimit.average=50"
# Wygeneruj hasło
sudo apt install apache2-utils
htpasswd -nb admin admin123
# Output: admin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/
labels:
- "traefik.http.routers.dashboard.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$ruca84Hq$$mbjdMZBAG.KWn7vfN/SNK/"
nano ~/backup-traefik.sh
#!/bin/bash
BACKUP_DIR=~/backups/$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
echo "📦 Tworzenie backup..."
# Backup konfiguracji
cp -r ~/traefik-setup $BACKUP_DIR/
# Backup certyfikatów SSL
cp -r ~/traefik-setup/letsencrypt $BACKUP_DIR/ 2>/dev/null || true
# Backup volumes (jeśli masz dane)
docker-compose -f ~/traefik-setup/docker-compose.yml exec sklep tar -czf /tmp/sklep-data.tar.gz /app/data 2>/dev/null || true
echo "✅ Backup zapisany w: $BACKUP_DIR"
# Sprawdź sieć
docker network ls
docker network inspect traefik-setup_web
# Sprawdź labels
docker inspect sklep | grep traefik
# Sprawdź logi Traefika: `make logs`
# Sprawdź plik certyfikatów
ls -la letsencrypt/
# Sprawdź czy port 8082 jest otwarty
sudo netstat -tlnp | grep 8082
# Sprawdź konfigurację
docker-compose exec traefik traefik version
# Zobacz wszystkie routery
curl -s http://localhost:8082/api/http/routers | jq
# Zobacz wszystkie serwisy
curl -s http://localhost:8082/api/http/services | jq
# Status Traefik
curl -s http://localhost:8082/api/overview
Funkcja | Traefik | Caddy |
---|---|---|
Konfiguracja | Labels w YAML | Prosty Caddyfile |
Dashboard | ✅ Pełny dashboard | ❌ Brak |
Load Balancing | ✅ Zaawansowany | |
Middleware | ✅ Bogaty zestaw | |
Learning Curve | 🔴 Stroma | 🟢 Płaska |
Service Discovery | ✅ Automatyczny | ❌ Manual |
Wybierz Traefik gdy:
- Masz wiele mikrousług
- Potrzebujesz load balancing
- Chcesz dashboard do monitorowania
- Planujesz skalowanie poziome
- Potrzebujesz zaawansowane middleware
Zostań z Caddy gdy:
- Masz proste aplikacje (jak Twoje 4 projekty Flask)
- Chcesz szybko postawić serwer
- Nie potrzebujesz zaawansowanych funkcji
- Jesteś początkującym
# Ustaw rekordy A w swoim DNS:
# sklep.twoja-domena.pl → IP_SERWERA
# blog.twoja-domena.pl → IP_SERWERA
# api.twoja-domena.pl → IP_SERWERA
# portfolio.twoja-domena.pl → IP_SERWERA
# dashboard.twoja-domena.pl → IP_SERWERA
cd ~/traefik-setup
# Zmień email w docker-compose.yml na swój
nano docker-compose.yml
# Znajdź: "--certificatesresolvers.myresolver.acme.email=twoj@email.com"
# Uruchom z pełną konfiguracją
docker-compose up -d
# Sprawdź logi SSL
docker-compose logs traefik | grep acme
# Sprawdź czy certyfikaty zostały wydane
curl -I https://sklep.twoja-domena.pl
curl -I https://api.twoja-domena.pl
# Dashboard z SSL
open https://dashboard.twoja-domena.pl
# Dodaj do docker-compose.yml:
prometheus:
image: prom/prometheus
container_name: prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.prometheus.rule=Host(`prometheus.twoja-domena.pl`)"
- "traefik.http.routers.prometheus.entrypoints=websecure"
- "traefik.http.routers.prometheus.tls.certresolver=myresolver"
grafana:
image: grafana/grafana
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin123
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.grafana.rule=Host(`grafana.twoja-domena.pl`)"
- "traefik.http.routers.grafana.entrypoints=websecure"
- "traefik.http.routers.grafana.tls.certresolver=myresolver"
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'traefik'
static_configs:
- targets: ['traefik:8082']
sudo ufw allow ssh
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable
sudo apt install fail2ban
# Konfiguracja dla Traefik
sudo nano /etc/fail2ban/filter.d/traefik-auth.conf
[Definition]
failregex = ^<HOST> \- \S+ \[\] \"(GET|POST|HEAD).*\" 401
ignoreregex =
sudo nano /etc/fail2ban/jail.local
[traefik-auth]
enabled = true
port = http,https
filter = traefik-auth
logpath = /var/log/traefik/access.log
maxretry = 3
bantime = 3600
name: Deploy to VPS
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy to server
uses: appleboy/ssh-action@v0.1.7
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd ~/traefik-setup
git pull origin main
docker-compose build sklep
docker-compose up -d sklep
echo "✅ Deployment completed!"
HOST: IP_TWOJEGO_SERWERA
USERNAME: junior
SSH_KEY: (twój klucz prywatny SSH)
nano ~/status-check.sh
#!/bin/bash
echo "🔍 Sprawdzanie statusu aplikacji..."
services=("sklep" "blog" "api" "portfolio" "traefik")
base_url="https://twoja-domena.pl"
for service in "${services[@]}"; do
if [ "$service" = "traefik" ]; then
url="https://dashboard.twoja-domena.pl"
else
url="https://$service.twoja-domena.pl"
fi
status=$(curl -s -o /dev/null -w "%{http_code}" "$url")
if [ "$status" = "200" ]; then
echo "✅ $service: OK"
else
echo "❌ $service: ERROR ($status)"
# Restart kontenera
cd ~/traefik-setup
docker-compose restart $service
fi
done
echo "📊 Zasoby serwera:"
echo "CPU: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | awk -F'%' '{print $1}')%"
echo "RAM: $(free | grep Mem | awk '{printf("%.1f%%", $3/$2 * 100.0)}')"
echo "Dysk: $(df -h / | awk 'NR==2{print $5}')"
crontab -e
# Dodaj:
*/5 * * * * ~/status-check.sh >> ~/monitoring.log 2>&1
✅ Zaawansowany reverse proxy
✅ Service discovery
✅ Dashboard do monitorowania
✅ Load balancing
✅ Middleware (CORS, Auth, Rate limiting)
✅ Automatyczne SSL
✅ Metryki i monitoring
- Docker/Podman - konteneryzacja
- Traefik - advanced reverse proxy
- YAML - konfiguracja infrastructure as code
- SSL/TLS - zarządzanie certyfikatami
- Monitoring - Prometheus + Grafana
- CI/CD - GitHub Actions
- Networking - Docker networks
- Security - middleware, fail2ban
- Kubernetes - orkiestracja kontenerów
- Helm Charts - pakiety Kubernetes
- ArgoCD - GitOps deployment
- Service Mesh - Istio/Linkerd
- Observability - ELK Stack
Komponent | Koszt/miesiąc |
---|---|
VPS Basic | 2 EUR |
Domena | ~1 EUR |
Łącznie | ~3 EUR |
Za cenę kawy masz:
- Professional deployment setup
- Dashboard monitoring
- Automatic SSL
- Load balancing
- CI/CD ready environment
✅ Enterprise-grade features
✅ Scalable architecture
✅ Rich ecosystem
⚠️ Steep learning curve
⚠️ More complex setup
✅ Zero-config SSL
✅ Simple setup
✅ Perfect for small projects
⚠️ Limited advanced features
⚠️ Manual service discovery
Verdict dla Juniora:
- Start z Caddy - naucz się podstaw
- Przejdź na Traefik - gdy potrzebujesz więcej
Oba są świetne! Wybór zależy od potrzeb projektu! 🚀
Właśnie opanowałeś jeden z najpopularniejszych narzędzi DevOps! Traefik to standard w wielu firmach technologicznych.
Jesteś gotowy na:
- Mid-level DevOps positions
- Microservices architecture
- Cloud-native development
- Kubernetes orchestration
Keep learning! 🚀
Dashboard Traefika w środowisku produkcyjnym jest domyślnie zabezpieczony hasłem (basic auth):
- Dostęp do panelu jest możliwy tylko przez domenę
traefik.devopsterminal.com
po HTTPS. - Do logowania wymagany jest login i hasło (domyślnie:
admin
/changeme
). - Hasło jest przechowywane jako hash bcrypt w labelu:
- "traefik.http.middlewares.auth.basicauth.users=admin:$$2y$$05$$5HXxP9X8wJqTgYz5jK5u8uJq5VZ5QkXJ5zQ9X8wJqTgYz5jK5u8uJ"
- Middleware
auth
jest przypisany tylko do dashboardu, nie do backendów.
- Wygeneruj nowy hash bcrypt (np. na https://bcrypt-generator.com/).
- Podmień wartość labela w
docker-compose.prod.yml
:- "traefik.http.middlewares.auth.basicauth.users=admin:<nowy_hash>"
- Zrestartuj stack (
make restart-prod
lub przez systemd).
Uwaga:
- Nie udostępniaj dashboardu publicznie bez hasła!
- Możesz dodatkowo ograniczyć dostęp po adresie IP lub przez VPN, dodając kolejne middleware.