Traefik v3 आणि Docker Compose वापरून 5 apps
Traefik v3 वापरून एकाच IP वर 5 apps कशा चालवायच्या ते शिका. Host rule आणि Let's Encrypt TLS सोबत acme.json मधील त्रुटी कशा टाळायच्या हे जाणून घ्या.
एक IP, पाच apps, एक port 443
तुमच्या VPS कडे एकच public IPv4 address आणि एकच TCP port 443 आहे. तुम्हाला त्यावर Gitea, तुमच्या app ची staging copy, एक internal dashboard, एक status page आणि एक webhook receiver हवे आहेत — एकच box आणि पाच hostnames. Reverse proxy ही अशी प्रक्रिया आहे जी :80 आणि :443 ports नियंत्रित करते, प्रत्येक request वर Host header वाचते आणि तो योग्य container कडे सोपवते. Traefik हे काम करते, आणि तुम्हाला certbot मॅन्युअली न चालवता प्रत्येक hostname साठी certificate मिळवून देते आणि त्याचे renewal करते.
Traefik आणि nginx server {} block मधील मुख्य फरक म्हणजे त्याची configuration कुठून येते. nginx मध्ये तुम्हाला file edit करून reload करावी लागते, आणि certificate lifecycle ही एक वेगळी प्रक्रिया असते — जसे की तुम्ही nginx वर certbot वापरून Let's Encrypt certificates issue करणे तेव्हा असते, जिथे renewal timer पूर्णपणे web server च्या बाहेर असतो. Traefik चा Docker provider Docker event stream वर लक्ष ठेवतो आणि तुमच्या containers मधील labels वाचतो: जर तुम्ही Host() rule label असलेला container सुरू केला, तर तो एका सेकंदात routable होतो; तो थांबवला की तो route निघून जातो. यात एक अडचण देखील आहे. Labels मध्ये असलेली configuration एकाच वेळी पाच ठिकाणी असते, आणि चुकीचा label असल्यास कोणतीही error येत नाही — container फक्त route होत नाही आणि Traefik काहीही सांगत नाही.
चार संज्ञा (Nouns)
- Entrypoints हे listening sockets आहेत. तुम्हाला दोन परिभाषित करावे लागतील:
:80वरwebआणि:443वरwebsecure. - Routers विनंती (
Host(...)) मॅच करतात आणि ती service ला जोडतात.tls.certresolverद्वारे प्रत्येक router साठी certificates मागवले जातात. - Services हे backend आहेत — एक container आणि Docker network च्या आत तो ज्या port वर listen करतो तो.
- Middlewares हे router आणि service च्या मध्ये असतात: basic auth, IP allow-lists, header rewrites, redirects.
Static configuration (entrypoints, providers, ACME) Traefik च्या command line वर किंवा traefik.yml मध्ये दिली जाते; यामध्ये बदल करण्यासाठी Traefik रीस्टार्ट करावा लागतो. Dynamic configuration (routers, services, middlewares) container labels मधून येते आणि ती hot-reload होते. या दोन्हीमधील फरक न समजल्यामुळे सहसा "माझा flag काम करत नाहीये" अशी समस्या उद्भवते.
The compose file
proxy नावाचे एक shared Docker network मुख्य आधार आहे. Traefik एखाद्या container ला तेव्हाच reach करू शकतो जेव्हा दोन्ही त्यावर असतात.
name: edge
networks:
proxy:
name: proxy
services:
traefik:
image: traefik:v3.5
restart: unless-stopped
command:
- --providers.docker=true
- --providers.docker.exposedByDefault=false
- --providers.docker.network=proxy
- --entryPoints.web.address=:80
- --entryPoints.websecure.address=:443
- --entryPoints.web.http.redirections.entryPoint.to=websecure
- --entryPoints.web.http.redirections.entryPoint.scheme=https
- --certificatesresolvers.le.acme.email=you@example.com
- --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
- --certificatesresolvers.le.acme.tlschallenge=true
# while you iterate, point at staging so a mistake costs nothing:
# - --certificatesresolvers.le.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
- --api.dashboard=true
- --log.level=INFO
- --accesslog=true
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
networks:
- proxy
labels:
- traefik.enable=true
- traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)
- traefik.http.routers.dashboard.entrypoints=websecure
- traefik.http.routers.dashboard.tls.certresolver=le
- traefik.http.routers.dashboard.service=api@internal
- traefik.http.routers.dashboard.middlewares=dashboard-auth
- traefik.http.middlewares.dashboard-auth.basicauth.users=admin:$$apr1$$REPLACE$$THIS
gitea:
image: gitea/gitea:1 # major-only pin keeps this demo copy-pasteable; pin an exact release in production
restart: unless-stopped
volumes:
- ./gitea:/data
networks:
- proxy
labels:
- traefik.enable=true
- traefik.http.routers.gitea.rule=Host(`git.example.com`)
- traefik.http.routers.gitea.entrypoints=websecure
- traefik.http.routers.gitea.tls.certresolver=le
- traefik.http.services.gitea.loadbalancer.server.port=3000आधी docker compose up -d, त्यानंतर docker compose logs -f traefik. प्रत्येक अतिरिक्त app हा gitea block ची एक copy असते, ज्यामध्ये स्वतःचे router name, स्वतःचे Host() आणि स्वतःचे internal port असते. Nextcloud install running in Docker with TLS and backups देखील याच पद्धतीने सेट करता येते — त्याचे published ports काढून टाका, त्याला proxy ला जोडा, आणि hostname व certificate साठी router labels चा वापर करा.
येथे पाच महत्त्वाचे तपशील आहेत.
exposedByDefault=false मुळे container जोपर्यंत traefik.enable=true धारण करत नाही तोपर्यंत Traefik ला दिसत नाही. जर तुम्ही ते वगळले, तर तुम्ही सुरू केलेले प्रत्येक container — अगदी काही तपासण्यासाठी वापरलेले throwaway postgres देखील — त्यासाठी एक route तयार केला जातो.
providers.docker.network=proxy Traefik ला सांगते की जेव्हा एखादा container अनेक networks ला जोडलेला असतो, तेव्हा कोणते network वापरावे. जर तुम्ही ते वगळले, तर Traefik चुकीचा container IP निवडू शकते, ज्यामुळे application fault सारखी दिसणारी 502 error येते.
loadbalancer.server.port=3000 हा container आतला port आहे; Gitea तिथे 3000 वर listen करते. लक्षात घ्या की कोणताही app container port publish करत नाही — फक्त Traefik करते.
web entrypoint वरील redirect plaintext requests ला HTTPS कडे 308 redirect करते. Port 80 तरीही खुला राहतो: ACME HTTP challenge साठी त्याची गरज असते, तसेच फक्त hostname टाईप करणाऱ्या युजर्ससाठीही त्याची गरज असते.
basic-auth hash मधील दुहेरी $$ ही Compose escaping आहे, ती typo नाही. ती htpasswd -nbB admin 'your-password' (package apache2-utils) वापरून तयार करा, आणि नंतर प्रत्येक $ दुप्पट करा.
प्रमाणपत्र आणि acme.json ची अडचण
tlschallenge=true TLS-ALPN-01 निवडते: Let's Encrypt तुमच्या सिस्टमला 443 पोर्टवर जोडते आणि Traefik TLS handshake मध्ये चॅलेंजला उत्तर देते. दुसरा पर्याय HTTP-01 आहे, जो पोर्ट 80 वर चालतो — यासाठी Traefik च्या command: यादीतील tlschallenge ओळ बदलून खालील दोन ओळी वापरा:
- --certificatesresolvers.le.acme.httpchallenge=true
- --certificatesresolvers.le.acme.httpchallenge.entrypoint=webदोन्ही पद्धती काम करतात. दोन्हीसाठी, होस्टनेमसाठी असलेला public DNS आधी तुमच्या VPS कडे निर्देशित (point) असणे आवश्यक आहे — certificate authority नाव रिझॉल्व्ह करते आणि बाहेरून कनेक्शन प्रस्थापित करते. आधी A (आणि AAAA) रेकॉर्ड तयार करा, dig +short git.example.com ने त्याची खात्री करा, आणि नंतर Traefik सुरू करा.
आता अशी अडचण, ज्यामुळे लोकांचा बराच वेळ वाया जातो. Traefik त्याची ACME account key आणि प्रत्येक जारी केलेले प्रमाणपत्र एका acme.json मध्ये ठेवते. जर ती फाईल group- किंवा world-readable असेल, तर Traefik याप्रमाणे एक ओळ प्रिंट करते आणि थांबते:
error: unable to get ACME account: permissions 644 for /letsencrypt/acme.json are too open, please use 600यावर सोपा उपाय वर दिल्याप्रमाणे आहे: directory ला bind-mount करा आणि Traefik ला योग्य mode सह ती फाईल स्वतः तयार करू द्या. जर तुम्ही acme.json फाईल touch ने तयार केली असेल, तर तुमच्या umask मुळे तिचे permission 644 झाले असेल. होस्टवर ती दुरुस्त करा:
chmod 600 ./letsencrypt/acme.json
docker compose restart traefikतुमच्या app volumes सह त्या directory चा बॅकअप घ्या. ती फाईल गमावली तरी चालते — प्रमाणपत्रे पुन्हा मिळवता येतात — परंतु एकाच वेळी पाच होस्टनेम्स पुन्हा इश्यू केल्यास तुम्ही rate limits मध्ये अडकू शकता.
काम पूर्ण होईपर्यंत staging CA वापरा. caserver ओळ uncomment करा, सर्व routes व्यवस्थित चालतील याची खात्री करा, त्यानंतर ती पुन्हा comment करा आणि acme.json डिलीट करा जेणेकरून production प्रमाणपत्रे नवीन पद्धतीने मागवली जातील. Production Let's Encrypt एकाच होस्टनेम्सच्या संचासाठी दर आठवड्याला पाच duplicate प्रमाणपत्रे देण्यास परवानगी देते, आणि एकाच नावासाठी वारंवार अयशस्वी व्हॅलिडेशनवर मर्यादा (throttle) घालते. Staging मध्ये untrusted प्रमाणपत्रे मिळतात — तुमचा ब्राउझर चेतावणी देईल, आणि ती चेतावणी म्हणजे तुमचे काम यशस्वी झाले याचा संकेत आहे — याचे limits खूप लवचिक असतात.
डॅशबोर्ड ही एक कंट्रोल सरफेस आहे, डेमो नाही
बहुतेक quickstarts मध्ये --api.insecure=true सेट केले जाते, जे पोर्ट 8080 वर कोणत्याही authentication शिवाय डॅशबोर्ड सर्व्ह करते. ज्या मशीनला public IP आहे आणि जो routing topology, hostnames, middleware names आणि backend ports स्कॅन करणाऱ्या कोणालाही उपलब्ध करून देतो, अशा ठिकाणी हे धोकादायक आहे.
वरील traefik सर्व्हिस मधील लेबल्स हा एक पर्याय आहेत: डॅशबोर्ड इतर कोणत्याही ॲपप्रमाणे, रिअल hostname वर, TLS द्वारे आणि basicauth च्या मागे राउट केला जातो. service=api@internal राउटरला Traefik च्या built-in API शी जोडण्याचे काम करते. IP allow-list वापरून सुरक्षा अधिक मजबूत करा, जी डावीकडून उजवीकडे लागू केली जाते. जर तुमचा ऑफिसचा पत्ता dynamic असेल, तर रेंज तुम्ही स्वतः host केलेल्या WireGuard VPN कडून मिळणाऱ्या subnet वर सेट करा आणि डॅशबोर्ड फक्त त्या tunnel द्वारे एक्सेस करा:
- traefik.http.middlewares.office.ipallowlist.sourcerange=10.0.0.7/32
- traefik.http.routers.dashboard.middlewares=office,dashboard-authThe Docker socket is root
/var/run/docker.sock हे एक API आहे जे host मधून / mount करणारा container तयार करू शकते. याचा वापर करणे म्हणजे machine वर root प्रमाणेच अधिकार मिळवणे होय; Traefik ला labels वाचण्यासाठी याची आवश्यकता असते.
Mount मध्ये :ro वापरा, परंतु त्याचे परिणाम समजून घ्या: यामुळे socket file फक्त read-only होते. यामुळे Docker API कडे जाणारे POST requests थांबत नाहीत. खरा उपाय म्हणजे Traefik ला socket थेट न देणे आणि मध्ये एक filtering proxy वापरणे:
dockerproxy:
image: tecnativa/docker-socket-proxy # pin the current tag
restart: unless-stopped
environment:
CONTAINERS: 1
NETWORKS: 1
POST: 0
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- proxyTraefik मधून socket volume काढून टाका आणि provider ला proxy कडे निर्देशित करा:
--providers.docker.endpoint=tcp://dockerproxy:2375Traefik कडे containers आणि networks साठी फक्त read access राहील, आणि नवीन काहीही तयार करण्याची क्षमता निघून जाईल.
Firewall, ports, आणि सर्वांकडून होणारी एक चूक
दोन ports उघडे आहेत, plus SSH:
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enableDocker चे published ports ufw बायपास करतात. Docker स्वतःचे iptables rules समाविष्ट करते, जे ufw च्या chains च्या आधी तपासले जातात. त्यामुळे जरी ufw मध्ये deny rule असेल, तरी ports: ["3000:3000"] ने सुरू केलेला container इंटरनेटवरून एक्सेस करता येतो. ही समस्या firewall configuration ची नसून संरचनेची (structural) आहे: फक्त Traefik कडून ports publish करा, आणि इतर सर्व containers साठी networks: [proxy] वापरा. जर एखाद्या गोष्टीला host पर्यंत पोहोचणे आवश्यक असेल, तर त्याला loopback ला bind करा — "127.0.0.1:3000:3000".
Troubleshooting: errors you will actually see
404 page not found, Traefik कडून सर्व्ह केली जाते. कोणताही router मॅच झाला नाही. संभाव्यतेनुसार: कंटेनरमध्ये traefik.enable=true नाही (exposedByDefault=false सेट केल्याशिवाय); Host() rule तुम्ही टाईप केलेल्या नावाशी मॅच होत नाही; एका label मधील router नाव आणि दुसऱ्या label मधील router नाव वेगळे आहे (routers.gitea.rule आणि routers.gitea.entrypoints हे एकच शब्द असणे आवश्यक आहे); किंवा तुम्ही hostname साठी backticks ऐवजी quotes वापरले आहेत. Traefik v3 मध्ये matchers च्या आत backticks वापरणे आवश्यक आहे.
502 Bad Gateway. router मॅच झाला पण backend उपलब्ध नाही. बहुतेक वेळा कंटेनर proxy network वर नसतो — docker inspect -f '{{json .NetworkSettings.Networks}}' gitea तपासा. दुसरा संभाव्य दोष चुकीचा loadbalancer.server.port आहे: तुम्ही published port दिले आहे, किंवा app इतरत्र listen करत आहे. लॉगमध्ये ही माहिती मिळते: dial tcp 172.18.0.5:8080: connect: connection refused.
ब्राउझर वॉर्निंग देते, आणि certificate TRAEFIK DEFAULT CERT साठी जारी केले जाते. त्या hostname साठी कोणतेही certificate उपलब्ध नाही आणि Traefik ने त्याचे self-signed placeholder सर्व्ह केले आहे. ACME च्या ओळी वाचा:
unable to obtain ACME certificate for domains "git.example.com" ...
acme: error: 400 ... DNS problem: NXDOMAIN looking up A for git.example.comDNS अजूनही या बॉक्सकडे पॉइंट करत नाहीये. रेकॉर्ड फिक्स करा, TTL पूर्ण होण्याची वाट पहा, आणि Traefik रीस्टार्ट करा.
HTTP challenge मध्ये Invalid response from http://git.example.com/.well-known/acme-challenge/...: बाहेरून port 80 Traefik पर्यंत पोहोचत नाहीये — सहसा VPS च्या समोर असलेल्या provider-level firewall मुळे हे घडते, ufw मुळे नाही.
Certificates जारी होत नाहीत, आणि तुमचे DNS Cloudflare वर 'orange cloud' सह आहे. Cloudflare त्याच्या edge वर TLS टर्मिनेट करते आणि TLS-ALPN-01 त्याद्वारे पूर्ण होऊ शकत नाही. सर्टिफिकेट जारी करत असताना रेकॉर्ड 'DNS-only' वर सेट करा, किंवा API token सह DNS-01 challenge वापरा. Wildcards जारी करण्यासाठी DNS-01 हा एकमेव challenge आहे.
Redirect loop. Traefik च्या समोर काहीतरी आधीच TLS टर्मिनेट करते आणि :80 वर plaintext फॉरवर्ड करते; entrypoint redirect ते पुन्हा HTTPS कडे पाठवते. या दोन redirects पैकी एक काढून टाका.
Keeping it running
Docker चा unit boot-enabled (systemctl is-enabled docker) असणे आवश्यक आहे, आणि restart: unless-stopped मुळे reboot नंतर stack पुन्हा सुरू होतो. अधिक स्पष्ट नियंत्रणासाठी, RemainAfterExit=yes सह docker compose -f /srv/edge/compose.yml up -d चालवणारा एक छोटा systemd unit वापरल्यास तुम्हाला systemctl status edge आणि ordering control मिळेल.
Traefik tag पिन करा (traefik:v3.5, latest नको). v2-to-v3 upgrade मुळे rule syntax आणि provider names बदलले आहेत; unattended latest मुळे अशी config reload होऊ शकते जी आता सिस्टमला समजणार नाही. upgrade मुळे विचारपूर्वक करा: migration notes वाचा, tag बदला, docker compose up -d traefik करा आणि log तपासा. जर तुम्ही अजूनही v2 tag वापरत असाल, तर the Traefik v2 to v3 migration guide मध्ये प्रत्येक rename, compatibility mode आणि certificates सुरक्षित ठेवणारा rollback प्रक्रिया दिली आहे.
./letsencrypt आणि प्रत्येक app चा data volume बॅकअप घ्या. Traefik मध्ये compose file मधून पुन्हा तयार करता येणार नाही असा कोणताही इतर state साठवलेला नसतो.
मोठ्या प्रमाणावर (at scale) काय समस्या येतात
पहिली मर्यादा throughput ची नाही, तर एकाच मशीनची आहे: एका VPS वर एक Traefik असणे हे पाच apps साठी single point of failure आहे. तसेच, acme.json हे flat-file storage आहे — जर दोन Traefik instances ने त्यात लिहिण्याचा प्रयत्न केला, तर डेटा corrupt होईल. Scaling out करण्यासाठी, certificate storage फाईलमधून बाहेर हलवणे किंवा TLS कोठेतरी वेगळ्या ठिकाणी terminate करणे आवश्यक आहे.
दुसरी समस्या long-lived connections ची आहे. Server-sent events, मोठे uploads आणि slow clients मुळे entrypoint च्या responding timeouts ची समस्या उद्भवू शकते; --entryPoints.websecure.transport.respondingTimeouts.readTimeout आणि त्याचे writeTimeout व idleTimeout siblings हे याचे नियंत्रण करणारे knobs आहेत. WebSockets साठी कोणत्याही अतिरिक्त configuration ची गरज नाही.
तिसरी समस्या disk ची आहे. --accesslog=true stdout वर writes करते, आणि Docker चा json-file driver मर्यादा न ठेवल्यास तो डेटा कायमस्वरूपी साठवून ठेवतो. Traefik service वर logging.options.max-size सेट करा, किंवा access log फाईलमध्ये लिहून त्याचे rotation करा.
यापैकी कशासाठीही orchestrator ची गरज नाही. परंतु, तुमच्या नियंत्रणाखाली असलेला एक server आवश्यक आहे, ज्याला real IP आणि जगासाठी खुले असलेले 80 आणि 443 ports असावेत — एक छोटा VPS हीच संपूर्ण dependency list आहे.
FAQ
मी Traefik वापरत असल्यास मला अजूनही certbot ची गरज आहे का?
नाही. Traefik चा ACME resolver प्रत्येक hostname साठी certificate request आणि renew करतो, आणि ते सर्व acme.json मध्ये स्टोअर करतो. जेव्हा nginx किंवा इतर एखादा server स्वतः TLS terminate करतो, तेव्हा certbot योग्य साधन आहे; एकाच hostname साठी दोन्ही वापरल्यास Let's Encrypt च्या rate limits संपू शकतात.
Traefik द्वारे माझा container 404 error का दाखवत आहे?
Traefik कडून येणारा 404 error म्हणजे कोणताही router त्या request ला match झाला नाही. container मध्ये traefik.enable=true आहे की नाही ते तपासा (एकदा exposedByDefault=false सेट केल्यावर हे अनिवार्य आहे), Host() ची value तुम्ही टाईप केलेल्या नावाशी जुळते की नाही ते तपासा, आणि त्या app च्या प्रत्येक label साठी router name एकच असल्याची खात्री करा. Traefik v3 मध्ये matcher मध्ये quotes ऐवजी backticks वापरणे आवश्यक आहे.
येथे 404 आणि 502 मधील फरक काय आहे?
404 म्हणजे routing झालेच नाही; 502 म्हणजे router ने match केले परंतु backend ने connection नाकारले. 502 चे सामान्य कारण म्हणजे container proxy network ला जोडलेला नसणे, किंवा loadbalancer.server.port मध्ये app च्या अंतर्गत listening port ऐवजी published port वापरणे. access log मध्ये Traefik ने डायल केलेल्या अचूक address ची माहिती मिळते.
Docker socket ला read-only mount करणे पुरेसे आहे का?
:ro flag मुळे socket file read-only होते, परंतु त्यामागचा API नाही — POST requests अजूनही त्यावरून जातात, आणि Docker API access म्हणजे host वर root access होय. अधिक सुरक्षित पर्याय म्हणजे वर दिलेला docker-socket-proxy container, जो Traefik ला फक्त container आणि network reads देतो आणि writes पूर्णपणे ब्लॉक करतो.
Traefik wildcard certificate जारी करू शकते का?
फक्त DNS-01 challenge द्वारे, तुमच्या DNS provider च्या API token सह. TLS-ALPN-01 आणि HTTP-01 हे प्रत्येक single hostname validate करतात आणि wildcard तयार करू शकत नाहीत. जेव्हा Cloudflare सारखे CDN तुमच्या VPS च्या समोर TLS terminate करते आणि इतर दोन challenges यशस्वी होत नाहीत, तेव्हा DNS-01 हा योग्य पर्याय आहे.