Traefik v3 Docker Compose میں 5 ایپس کیسے چلائیں
Traefik v3 اور Docker Compose کے ذریعے ایک ہی IP پر 5 ایپس چلائیں۔ Host rule اور Let's Encrypt کے استعمال اور acme.json کی غلطیوں سے بچنے کا طریقہ سیکھیں۔
ایک IP، پانچ ایپس، ایک پورٹ 443
آپ کے VPS کے پاس ایک ہی پبلک IPv4 ایڈریس اور ایک ہی TCP پورٹ 443 ہے۔ آپ اس پر Gitea، اپنی ایپ کی ایک Staging copy، ایک internal dashboard، ایک status page اور ایک webhook receiver چلانا چاہتے ہیں — یعنی ایک ہی سرور پر پانچ hostnames۔ Reverse proxy وہ عمل ہے جو :80 اور :443 کو کنٹرول کرتا ہے، ہر ریکوئسٹ پر Host header پڑھتا ہے اور اسے صحیح container تک پہنچاتا ہے۔ Traefik یہی کام کرتا ہے، اور یہ ہر hostname کے لیے خودکار طریقے سے certificate حاصل اور رینیو کرتا ہے، جس کے لیے آپ کو دستی طور پر certbot چلانے کی ضرورت نہیں ہوتی۔
Traefik اور nginx server {} block میں بنیادی فرق اس کی configuration کا ذریعہ ہے۔ nginx میں آپ فائل ایڈٹ کرتے ہیں اور اسے reload کرتے ہیں، جبکہ certificate lifecycle ایک الگ کام رہتا ہے — یہ وہی طریقہ ہے جو آپ nginx پر certbot کے ذریعے Let's Encrypt certificates جاری کرنے کے لیے استعمال کرتے ہیں، جہاں renewal timer مکمل طور پر web server سے الگ ہوتا ہے۔ Traefik کا Docker provider Docker event stream پر نظر رکھتا ہے اور آپ کے containers سے labels پڑھتا ہے: اگر آپ ایک Host() rule label والا container شروع کرتے ہیں تو وہ ایک سیکنڈ کے اندر routable ہو جاتا ہے؛ اگر آپ اسے روک دیتے ہیں تو وہ route ختم ہو جاتا ہے۔ یہی اس کا ایک نقصان بھی ہے۔ Labels میں موجود configuration ایک ہی وقت میں پانچ مختلف جگہوں پر ہوتی ہے، اور غلط label ہونے پر کوئی ایرر نہیں آتا — container بس route نہیں ہوتا، اور Traefik کوئی پیغام نہیں دیتا۔
چار اسم (Nouns)
- Entrypoints لسننگ ساکٹس (listening sockets) ہیں۔ آپ دو تعریف کریں گے:
:80پرwebاور:443پرwebsecure۔ - Routers ایک ریکوئسٹ (
Host(...)) کو میچ کرتے ہیں اور اسے سروس کے ساتھ منسلک کرتے ہیں۔ ہر روٹر کے لیےtls.certresolverکے ذریعے سرٹیفکیٹس کی درخواست کی جاتی ہے۔ - Services بیک اینڈ (backend) ہیں — ایک کنٹینر اور وہ پورٹ جس پر وہ Docker نیٹ ورک کے اندر لسن کرتا ہے۔
- Middlewares روٹر اور سروس کے درمیان کام کرتے ہیں: basic auth، IP allow-lists، ہیڈر ری رائٹس (header rewrites)، اور ری ڈائریکٹس (redirects)۔
اسٹیٹک کنفیگریشن (entrypoints, providers, ACME) Traefik کی کمانڈ لائن یا traefik.yml میں دی جاتی ہے، اور اسے تبدیل کرنے کے لیے Traefik کو ری اسٹارٹ کرنا ضروری ہے۔ ڈائنامک کنفیگریشن (routers, services, middlewares) کنٹینر لیبلز سے آتی ہے اور اسے hot-reload کیا جاتا ہے۔ ان دونوں کے درمیان فرق نہ سمجھنا "میرا فلیگ کام نہیں کر رہا" جیسی عام غلطی کی وجہ بنتا ہے۔
The compose file
proxy نامی ایک مشترکہ Docker network بنیادی حیثیت رکھتا ہے۔ Traefik کسی کنٹینر تک صرف اسی صورت میں پہنچ سکتا ہے جب وہ دونوں اسی نیٹ ورک پر موجود ہوں۔
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۔ ہر اضافی ایپ gitea بلاک کا ایک نسخہ ہوتی ہے جس کا اپنا router name، اپنا Host() اور اپنا internal port ہوتا ہے۔ Nextcloud install running in Docker with TLS and backups بھی اسی طرح کام کرتا ہے — اس کے published ports ختم کریں، اسے proxy کے ساتھ منسلک کریں، اور hostname اور certificate کے لیے router labels کا استعمال کریں۔
یہاں پانچ اہم تفصیلات ہیں۔
exposedByDefault=false کنٹینر کو Traefik سے تب تک پوشیدہ رکھتا ہے جب تک اس میں traefik.enable=true موجود نہ ہو۔ اگر آپ اسے چھوڑ دیں تو آپ کے ہر کنٹینر کے لیے — بشمول اس postgres کے جو آپ نے صرف چیک کرنے کے لیے چلایا تھا — ایک روٹ خود بخود بن جائے گا۔
providers.docker.network=proxy Traefik کو بتاتا ہے کہ جب کوئی کنٹینر کئی نیٹ ورکس سے منسلک ہو تو اسے کون سا نیٹ ورک استعمال کرنا چاہیے۔ اگر اسے استعمال نہ کیا گیا تو Traefik غلط کنٹینر IP منتخب کر سکتا ہے، جس کے نتیجے میں 502 error آئے گا جو کہ ایپلی کیشن کی خرابی معلوم ہوتا ہے۔
loadbalancer.server.port=3000 کنٹینر کے اندر کا port ہے؛ Gitea وہاں 3000 پر لسن (listen) کرتا ہے۔ غور کریں کہ کوئی بھی ایپ کنٹینر port پبلش نہیں کرتا — صرف Traefik کرتا ہے۔
web entrypoint پر موجود redirect عام ٹیکسٹ درخواستوں کو HTTPS کے لیے 308 پر تبدیل کر دیتا ہے۔ Port 80 پھر بھی کھلا رہتا ہے: ACME HTTP challenge کو اس کی ضرورت ہوتی ہے، اور ان صارفین کو بھی جو صرف hostname ٹائپ کرتے ہیں۔
basic-auth hash میں موجود ڈبل $$ Compose کا escaping طریقہ ہے، یہ کوئی ٹائپو نہیں ہے۔ اسے 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دونوں طریقے کام کرتے ہیں۔ دونوں کے لیے ضروری ہے کہ ہوسٹ نیم (hostname) کا پبلک DNS پہلے سے آپ کے VPS کی طرف اشارہ کر رہا ہو — سرٹیفکیٹ اتھارٹی نام کو Resolve کرتی ہے اور باہر سے رابطہ کرتی ہے۔ پہلے A (اور AAAA) ریکارڈ بنائیں، dig +short git.example.com کے ذریعے تصدیق کریں، پھر Traefik شروع کریں۔
اب وہ مسئلہ جو لوگوں کا وقت ضائع کرتا ہے۔ Traefik اپنا ACME اکاؤنٹ کی (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 نے اسے 644 کر دیا ہوگا۔ ہوسٹ پر اسے درست کریں:
chmod 600 ./letsencrypt/acme.json
docker compose restart traefikاس directory کا بیک اپ اپنے app volumes کے ساتھ رکھیں۔ اسے کھونا کوئی بڑا مسئلہ نہیں ہے — سرٹیفکیٹس دوبارہ جاری کیے جا سکتے ہیں — لیکن ایک ساتھ پانچ ہوسٹ نیمز کو دوبارہ جاری کرنے سے آپ rate limits کا شکار ہو سکتے ہیں۔
ٹیسٹنگ کے دوران staging CA استعمال کریں۔ caserver لائن سے کمنٹ ختم کریں، تمام routes کو درست کریں، پھر اسے دوبارہ کمنٹ کر دیں اور acme.json کو ڈیلیٹ کر دیں تاکہ پروڈکشن سرٹیفکیٹس نئے سرے سے طلب کیے جا سکیں۔ پروڈکشن Let's Encrypt ایک ہی ہوسٹ نیم سیٹ کے لیے فی ہفتہ پانچ duplicate سرٹیفکیٹس کی اجازت دیتا ہے، اور ایک ہی نام کے لیے بار بار فیل ہونے والی validations کو throttles کرتا ہے۔ Staging غیر قابل اعتماد سرٹیفکیٹس جاری کرتا ہے — آپ کا براؤزر وارننگ دے گا، اور وہ وارننگ اس بات کا اشارہ ہے کہ یہ کام کر گیا ہے — اس کے limits بہت زیادہ لچکدار ہوتے ہیں۔
ڈیش بورڈ ایک کنٹرول سطح ہے، ڈیمو نہیں
زیادہ تر quickstarts میں --api.insecure=true سیٹ کیا جاتا ہے، جو بغیر کسی authentication کے port 8080 پر ڈیش بورڈ فراہم کرتا ہے۔ اگر آپ کے پاس public IP والا سرور ہے، تو یہ آپ کے routing topology، hostnames، middleware names اور backend ports کو ہر اس شخص کو فراہم کر دے گا جو اسے scan کرے گا۔
اوپر دیے گئے traefik سروس کے labels ایک متبادل پیش کرتے ہیں: ڈیش بورڈ کو کسی بھی دوسرے app کی طرح rout کیا جائے گا، ایک اصل hostname پر، TLS کے ذریعے، اور basicauth کے پیچھے۔ service=api@internal وہ چیز ہے جو router کو Traefik کے built-in API سے جوڑتی ہے۔ اسے مزید محفوظ بنانے کے لیے IP allow-list کا استعمال کریں، جسے بائیں سے دائیں (left to right) لاگو کیا جاتا ہے۔ اگر آپ کے office کا address dynamic ہے، تو range کو اس subnet پر سیٹ کریں جو a WireGuard VPN you self-host on the same VPS سے حاصل ہوتا ہے، اور ڈیش بورڈ تک رسائی صرف tunnel کے ذریعے حاصل کریں:
- traefik.http.middlewares.office.ipallowlist.sourcerange=10.0.0.7/32
- traefik.http.routers.dashboard.middlewares=office,dashboard-authDocker socket root کے برابر ہے
/var/run/docker.sock ایک API ہے جو ایسا container بنا سکتا ہے جو host سے / کو mount کرتا ہے۔ اس تک رسائی کا مطلب 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, aur woh rule jo har koi ghalat samajhta hai
Do ports open hain, plus SSH:
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enableDocker ke published ports ufw ko bypass kar dete hain. Docker apne khud ke iptables rules insert karta hai, jo ufw chains se pehle evaluate hote hain. Is wajah se agar koi container ports: ["3000:3000"] ke saath start kiya gaya ho, to ufw deny hone ke bawajood woh internet se reachable hota hai. Yeh masla firewall configuration ka nahi balkay structural hai: sirf Traefik se ports publish karein, aur baaki tamam containers ko networks: [proxy] dein aur kuch nahi. Agar kisi cheez ka host tak pahunchna zaroori ho, to usay loopback par bind karein — "127.0.0.1:3000:3000".
Troubleshooting: errors you will actually see
404 page not found, Traefik کی طرف سے فراہم کیا گیا۔ کوئی router میچ نہیں ہوا۔ امکانات کی ترتیب یہ ہے: container میں traefik.enable=true موجود نہیں ہے (exposedByDefault=false سیٹ ہونے کے باوجود)؛ Host() rule آپ کے ٹائپ کیے گئے نام سے میچ نہیں کرتا؛ ایک label میں router کا نام دوسرے سے مختلف ہے (routers.gitea.rule اور routers.gitea.entrypoints ایک ہی لفظ ہونے چاہئیں)؛ یا آپ نے hostname کو backticks کے بجائے quotes میں لکھا ہے۔ Traefik v3 کے matchers میں backticks کا ہونا ضروری ہے۔
502 Bad Gateway. ایک router میچ ہوا لیکن backend تک رسائی ممکن نہیں تھی۔ تقریباً ہمیشہ container proxy network پر موجود نہیں ہوتا — docker inspect -f '{{json .NetworkSettings.Networks}}' gitea چیک کریں۔ دوسرا ممکنہ سبب غلط loadbalancer.server.port ہے: آپ نے published port فراہم کیا ہے، یا app کہیں اور listen کر رہا ہے۔ log میں کوشش کا نام درج ہے: dial tcp 172.18.0.5:8080: connect: connection refused.
Browser وارننگ دیتا ہے، اور 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 ابھی اس box کی طرف point نہیں کر رہا۔ record کو درست کریں، TTL کا انتظار کریں، اور Traefik کو restart کریں۔
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 مکمل نہیں ہو سکتا۔ certificate جاری کرتے وقت record کو DNS-only پر سیٹ کریں، یا API token کے ساتھ DNS-01 challenge استعمال کریں۔ DNS-01 واحد challenge ہے جو wildcards جاری کرتا ہے۔
Redirect loop. Traefik کے سامنے کوئی چیز پہلے ہی TLS ختم کر کے :80 پر plaintext بھیج رہی ہے؛ entrypoint redirect اسے واپس HTTPS پر بھیج دیتا ہے۔ ان دو redirects میں سے کسی ایک کو ختم کریں۔
Keeping it running
Docker unit ko boot-enabled (systemctl is-enabled docker) hona chahiye, aur restart: unless-stopped reboot ke baad stack ko wapas lata hai. Behtar control ke liye, RemainAfterExit=yes ke saath docker compose -f /srv/edge/compose.yml up -d chalane wala ek chota systemd unit aapko systemctl status edge aur ordering control deta hai.
Traefik tag ko pin karein (traefik:v3.5, kabhi bhi latest nahi). v2-to-v3 upgrade ne rule syntax aur provider names ko badal diya hai, aur bina kisi hidayat ke latest us config ko reload kar dega jo ab samajh mein nahi aati. Upgrade soch samajh kar karein: migration notes parhein, tag ko update karein, docker compose up -d traefik, aur log check karein. Agar aap abhi bhi v2 tag par hain, to the Traefik v2 to v3 migration guide har rename, compatibility mode, aur certificate bachane wale rollback ki tafseel batata hai.
./letsencrypt aur har app ke data volume ka backup lein. Traefik mein koi aisa state nahi hota jise compose file se dobara na banaya ja sake.
Scaling کے دوران کیا مسائل آتے ہیں
پہلی رکاوٹ throughput نہیں ہے، بلکہ single box ہے: ایک VPS پر ایک Traefik instance 5 apps کے لیے single point of failure ہے، اور acme.json flat-file storage ہے — اگر دو Traefik instances اسے write کریں گے تو data corrupt ہو جائے گا۔ Scaling out کا مطلب ہے certificate storage کو file سے ہٹا کر کہیں اور منتقل کرنا، یا TLS کو کہیں اور terminate کرنا۔
دوسرا مسئلہ long-lived connections ہے۔ Server-sent events، بڑے uploads، اور slow clients entrypoint کے responding timeouts سے ٹکراتے ہیں؛ --entryPoints.websecure.transport.respondingTimeouts.readTimeout اور اس کے writeTimeout اور idleTimeout siblings ہی ان کو control کرنے کے tools ہیں۔ WebSockets بغیر کسی extra configuration کے pass through ہو جاتے ہیں۔
تیسرا مسئلہ disk ہے۔ --accesslog=true stdout پر write کرتا ہے، اور Docker کا json-file driver اسے ہمیشہ کے لیے محفوظ رکھتا ہے جب تک کہ اسے cap نہ کیا جائے۔ Traefik service پر logging.options.max-size set کریں، یا access log کو ایک file میں write کریں اور اسے rotate کریں۔
ان میں سے کسی بھی کام کے لیے orchestrator کی ضرورت نہیں ہے۔ آپ کو صرف ایک ایسے server کی ضرورت ہے جو آپ کے کنٹرول میں ہو، جس کا real IP ہو اور ports 80 اور 443 دنیا کے لیے open ہوں — ایک single چھوٹا VPS ہی تمام dependencies کی فہرست ہے۔
FAQ
کیا مجھے Certbot کی ضرورت ہے اگر میں Traefik استعمال کر رہا ہوں؟
نہیں. Traefik کا ACME resolver ہر اس hostname کے لیے certificate کی درخواست اور تجدید کرتا ہے جسے وہ route کرتا ہے، اور یہ تمام data acme.json میں محفوظ کرتا ہے۔ اگر nginx یا کوئی اور server خود TLS terminate کرتا ہے تو Certbot بہترین ٹول ہے۔ ایک ہی hostname کے لیے دونوں کا استعمال کرنے سے Let's Encrypt کی rate limits ختم ہو سکتی ہیں۔
Traefik کے ذریعے میرا container 404 کیوں دے رہا ہے؟
Traefik کی طرف سے 404 کا مطلب ہے کہ کوئی بھی router اس request سے match نہیں ہوا۔ چیک کریں کہ container میں traefik.enable=true موجود ہے (جب exposedByDefault=false set ہو تو یہ لازمی ہے)، Host() کی value آپ کے لکھے ہوئے نام کے مطابق ہے، اور اس app کے تمام labels میں router کا نام ایک جیسا ہے۔ Traefik v3 میں matcher کے اندر quotes کے بجائے backticks استعمال کرنا ضروری ہے۔
یہاں 404 اور 502 میں کیا فرق ہے؟
404 کا مطلب ہے کہ routing ہوئی ہی نہیں؛ 502 کا مطلب ہے کہ router نے match کیا لیکن backend نے connection مسترد کر دیا۔ 502 کی عام وجوہات میں وہ container شامل ہے جو proxy network سے منسلک نہیں ہے، اور وہ loadbalancer.server.port جو app کے container کے اندر والے port کے بجائے published port پر point کر رہا ہے۔ access log اس exact address کا نام بتاتا ہے جس پر Traefik نے dial کیا تھا۔
کیا Docker socket کو read-only mount کرنا کافی ہے؟
:ro flag socket file کو read-only بناتا ہے، اس کے پیچھے موجود API کو نہیں۔ POST requests اب بھی اس کے ذریعے جاتی ہیں، اور Docker API تک رسائی کا مطلب 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 ہی حل ہے۔