Reverse Proxy Docker dengan Caddy: Setup Compose dengan HTTPS Otomatis
Jalankan Caddy sebagai reverse proxy Docker: satu stack compose, network bersama, reverse_proxy ke nama layanan dan HTTPS otomatis, plus kapan label caddy-docker-proxy berguna.
Singkatnya: jalankan Caddy di container tersendiri yang mem-publish port 80 dan 443, hubungkan container itu dan container aplikasi Anda ke satu network Docker bersama, lalu arahkan `reverse_proxy` ke setiap nama layanan dan port internalnya (misalnya `reverse_proxy app:3000`). Caddy me-resolve nama tersebut melalui DNS bawaan Docker dan otomatis mendapatkan sertifikat TLS untuk setiap alamat situs.
Panduan ini menunjukkan pendekatan Caddyfile biasa terlebih dahulu, lalu varian caddy-docker-proxy berbasis label, dan menjelaskan kapan masing-masing cocok di satu VPS. Jika Anda menjalankan Caddy langsung di host alih-alih di Docker, lihat panduan dasar reverse proxy Caddy.
Bagaimana komponennya saling terhubung
Hanya container Caddy yang mem-publish port ke dunia luar. Setiap container backend bergabung ke network bridge buatan pengguna (di sini bernama `web`) dan hanya mengekspos port-nya di network tersebut. Server DNS bawaan Docker, yang tersedia di network buatan pengguna, memungkinkan Caddy menjangkau `app:3000` berdasarkan nama layanan atau container, sehingga Anda tidak perlu meng-hard-code IP container yang berubah setiap kali dibuat ulang.
Menjaga backend tidak di-publish lebih penting daripada kelihatannya: Docker menulis aturan iptables sendiri, sehingga port yang di-publish dengan `ports:` bisa dijangkau dari internet meskipun ufw menyatakan port itu diblokir. Gunakan `expose:` atau tanpa pemetaan port sama sekali untuk apa pun yang seharusnya berada di belakang proxy.
| Komponen | Peran | Di-publish di host? |
|---|---|---|
| container caddy | Terminasi TLS, routing berdasarkan hostname, pengalihan HTTP ke HTTPS | Ya: 80/tcp, 443/tcp, 443/udp |
| network web | Network bridge bersama dengan DNS bawaan untuk nama layanan | Tidak |
| container aplikasi | Layanan Anda (aplikasi web, API, dashboard) | Tidak, hanya dapat dijangkau lewat Caddy |
| volume caddy_data | Sertifikat, private key, akun ACME | Tidak, tetapi harus persisten |
Langkah demi langkah: Caddyfile biasa dengan docker compose
- 01.Arahkan record A (dan record AAAA jika Anda memakai IPv6) untuk setiap hostname ke VPS sebelum menjalankan Caddy, atau penerbitan sertifikat akan gagal.
- 02.Buat network bersama sekali saja: `docker network create web`.
- 03.Buat `/opt/proxy/compose.yaml` dan `/opt/proxy/Caddyfile` seperti di bawah, lalu jalankan `docker compose up -d` di `/opt/proxy`.
- 04.Hubungkan setiap stack aplikasi ke network eksternal `web` dan jalankan dengan `docker compose up -d`.
- 05.Pantau penerbitan sertifikat pertama dengan `docker compose logs -f caddy` di `/opt/proxy`.
- 06.Setelah mengedit Caddyfile, muat ulang tanpa downtime: `docker compose exec -w /etc/caddy caddy caddy reload`.
# /opt/proxy/compose.yaml
services:
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp" # HTTP/3
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data # certificates and ACME account keys
- caddy_config:/config
networks:
- web
volumes:
caddy_data:
caddy_config:
networks:
web:
external: trueHubungkan aplikasi dan tulis Caddyfile
Setiap stack aplikasi mendeklarasikan network eksternal yang sama. Nama layanan menjadi hostname yang dihubungi Caddy. Volume `caddy_data` adalah yang tidak boleh hilang: menghapusnya memaksa Caddy meminta ulang setiap sertifikat, yang bisa terbentur rate limit ACME.
# /opt/app/compose.yaml
services:
app:
image: ghcr.io/example/app:latest
restart: unless-stopped
expose:
- "3000" # reachable on the network, NOT published on the host
networks:
- web
networks:
web:
external: true
# /opt/proxy/Caddyfile
{
email [email protected]
}
app.example.com {
reverse_proxy app:3000
}
grafana.example.com {
reverse_proxy grafana:3000
}
api.example.com {
reverse_proxy api-1:8080 api-2:8080 {
lb_policy round_robin
health_uri /healthz
health_interval 10s
}
}Backend Caddy: upstream, load balancing, dan health check
Dalam istilah Caddy, backend adalah upstream dari `reverse_proxy`. Anda bisa mencantumkan beberapa upstream dalam satu directive, memilih `lb_policy` seperti `round_robin`, `least_conn`, atau `ip_hash`, dan menambahkan health check aktif dengan `health_uri` agar container yang gagal dikeluarkan dari rotasi. Pemeriksaan pasif (`fail_duration`, `max_fails`) juga berguna jika aplikasi tidak punya endpoint health.
Secara default Caddy menyetel `X-Forwarded-For`, `X-Forwarded-Proto`, dan `X-Forwarded-Host` pada request yang di-proxy. Konfigurasikan aplikasi Anda agar memercayai rentang network proxy sehingga aplikasi melihat IP klien yang sebenarnya dan membuat tautan `https://`. WebSocket dan gRPC bekerja melalui `reverse_proxy` tanpa pengaturan tambahan; untuk gRPC tanpa enkripsi, gunakan `reverse_proxy h2c://service:50051`.
Label sebagai pengganti Caddyfile: caddy-docker-proxy
Orang yang mencari "Caddy proxy manager" biasanya menginginkan apa yang ditawarkan Nginx Proxy Manager: tambahkan container, dapatkan hostname dan sertifikat tanpa mengedit file pusat. Caddy tidak punya GUI resmi, tetapi proyek komunitas caddy-docker-proxy (github.com/lucaslorentz/caddy-docker-proxy) menghasilkan Caddyfile dari label container dan memuat ulang Caddy saat container dijalankan atau dihentikan.
Proyek ini membutuhkan akses baca ke socket Docker, yang praktis setara root di host. Mount secara read-only, selalu perbarui image proxy, dan pilih Caddyfile biasa jika Anda hanya menjalankan sedikit layanan.
services:
caddy:
image: lucaslorentz/caddy-docker-proxy:ci-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
environment:
- CADDY_INGRESS_NETWORKS=web
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- caddy_data:/data
networks:
- web
whoami:
image: traefik/whoami
networks:
- web
labels:
caddy: whoami.example.com
caddy.reverse_proxy: "{{upstreams 80}}"
volumes:
caddy_data:
networks:
web:
external: trueCaddyfile biasa vs caddy-docker-proxy
| Caddyfile biasa | Label caddy-docker-proxy | |
|---|---|---|
| Konfigurasi berada di | Satu file yang Anda versikan di git | Label yang tersebar di berbagai file compose |
| Akses socket Docker | Tidak diperlukan | Wajib (sensitif dari sisi keamanan) |
| Layanan baru | Edit Caddyfile, jalankan `caddy reload` | Tambahkan label, jalankan container |
| Image | `caddy:2` resmi | Image komunitas yang dibangun di atas Caddy |
| Debugging | Baca file secara langsung | Periksa konfigurasi yang dihasilkan di log |
| Paling cocok untuk | Setup VPS kecil dan stabil | Banyak layanan berumur pendek atau sering berubah |
Menjalankannya di VPS
Di VPS KVM NoctisNode Anda mendapat root penuh dan IPv4 dedicated, sehingga mem-publish port 80 dan 443 dari satu container Caddy dan menyembunyikan yang lainnya menjadi mudah. Wisp (1 vCPU, RAM 1 GB) cukup untuk Caddy plus beberapa container ringan; stack yang lebih berat cocok di Pulse atau Umbra. Detail penerbitan sertifikat dan mode kegagalannya dibahas di cara kerja HTTPS otomatis Caddy, dan penerusan TCP mentah atau SSH ada di proxy TCP dan SSH dengan Caddy. Amankan SSH host dengan panduan hardening SSH.
FAQ
QBagaimana cara membuat Caddy menjadi reverse proxy ke container Docker?
ATempatkan Caddy dan container tersebut di network Docker buatan pengguna yang sama dan gunakan `reverse_proxy service-name:port` di Caddyfile. Jangan gunakan `localhost`, karena di dalam container Caddy itu merujuk ke Caddy sendiri.
QMengapa Caddy mengembalikan 502 Bad Gateway untuk container saya?
ABiasanya container tidak berada di network bersama, port-nya salah (gunakan port internal container, bukan port host yang di-publish), atau aplikasi hanya listen di 127.0.0.1 di dalam container-nya. Buat aplikasi bind ke 0.0.0.0 dan periksa `docker network inspect web`.
QApakah caddy-docker-proxy aman digunakan?
ABekerja dengan baik, tetapi membutuhkan socket Docker, yang memberi kendali setara root atas host. Mount secara read-only, selalu perbarui image, dan jangan mengekspos endpoint admin Caddy.
QDi mana Caddy menyimpan sertifikat di Docker?
ADi `/data` di dalam image resmi, jadi mount named volume di sana. Kehilangannya berarti menerbitkan ulang setiap sertifikat dan mungkin terkena rate limit ACME.
QApakah ada Caddy proxy manager dengan web UI?
ACaddy sendiri tidak punya web UI resmi; konfigurasinya melalui Caddyfile, JSON, atau admin API-nya. Tool berbasis label seperti caddy-docker-proxy memberi alur kerja serupa: tambahkan container dan langsung jalan.