SSD Nodes Learn
Mwongozo Matt ConnorNa Matt Connor · Imeboreshwa 2026-07-24

Traefik v3 na Docker Compose: Apps 5 kwenye IP 1

Jifunze kutumia Traefik v3 na Docker Compose kuendesha apps 5 kwa IP moja. Tumia Host rule na Let's Encrypt bila kukumbana na makosa ya acme.json.

IP moja, programu tano, port 443 moja

VPS yako ina anwani moja ya IPv4 ya umma na port moja ya TCP 443. Unataka kuweka Gitea, nakala ya majaribio ya programu yako, dashboard ya ndani, ukurasa wa hali ya mfumo (status page), na mlengemaji wa webhook — hostnames tano, sanduku moja. Reverse proxy ni mchakato unaomiliki :80 na :443, unasoma header ya Host kwenye kila ombi, na kulipeleka kwenye container sahihi. Traefik hufanya hivyo, na hupata na kuhuisha cheti kwa kila hostname bila wewe kuendesha certbot kwa mkono.

Tofauti kati ya Traefik na nginx server {} block ni mahali ambapo usanidi wake unapotoka. Kwa nginx, unahariri faili na kuwasha upya (reload), na mzunguko wa cheti unabaki kuwa kazi inayojitegemea — mtindo unaofuata unapo utoaji wa cheti cha Let's Encrypt kwa kutumia certbot kwenye nginx, ambapo timer ya kuhuisha ipo nje kabisa ya web server. Docker provider ya Traefik huangalia mtiririko wa matukio ya Docker na husoma labels kwenye container zako: anza container yenye label ya sheria ya Host() na inaweza kufikiwa ndani ya sekunde moja; iache na njia hiyo itatoweka. Hilo pia ni tatizo. Usanidi unaoishi kwenye labels upo sehemu tano kwa wakati mmoja, na label isiyo sahihi haitoi taarifa — container haitafikiwa tu, na Traefik haitoi ujumbe wowote.

Nomino nne

  • Entrypoints ni sockets zinazosikiliza. Utatengeneza mbili: web kwenye :80 na websecure kwenye :443.
  • Routers hulinganisha ombi (Host(...)) na kuliunganisha na huduma. Cheti huombwa kwa kila router, kupitia tls.certresolver.
  • Services ni upande wa nyuma (backend) — kontena na port inayosikiliza ndani ya mtandao wa Docker.
  • Middlewares hukaa kati ya router na service: uthibitishaji wa msingi (basic auth), orodha ya IP zinazokubaliwa, ubadilishaji wa header, na uelekezaji (redirects).

Usanidi wa kudumu (entrypoints, providers, ACME) hupitishwa kwenye mstari wa amri (command line) wa Traefik au kwenye traefik.yml, na kubadilisha usanidi huu kunamaanisha kuwasha upya Traefik. Usanidi wa kidunika (routers, services, middlewares) hutoka kwenye lebo za kontena na unajisasisha bila kuwasha upya. Kuchanganya mambo haya mawili ndiyo chanzo cha kawaida cha tatizo la "flag yangu haifanyi kazi".

Faili ya compose

Mtandao mmoja wa Docker unaoitwa proxy ndio msingi. Traefik inaweza kufikia kontena ikiwa zote mbili zipo kwenye mtandao huo.

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, kisha docker compose logs -f traefik. Kila programu inayoongezwa ni nakala ya bloku ya gitea ikiwa na jina lake la router, Host() yake, na port yake ya ndani. Usakinishaji wa Nextcloud kwenye Docker kwa kutumia TLS na backups unaingia kwa njia hiyo hiyo — ondoa port zake zilizochapishwa, iunganishe na proxy, na uache lebo za router zishughulikie jina la host na cheti.

Maelezo matano hapa ni muhimu.

exposedByDefault=false hufanya kontena isiweze kuonekana na Traefik hadi iwe na traefik.enable=true. Ikiachwa bila lebo hiyo, kila kontena utakazowasha — ikiwemo postgres ya muda uliyotumia kukagua kitu — itatengenezwa njia (route) yake.

providers.docker.network=proxy inaambia Traefik ni mtandao gani utumike ikiwa kontena limeunganishwa kwenye mitandao kadhaa. Ikiachwa, Traefik inaweza kuchagua IP isiyo sahihi ya kontena, jambo linalosababisha kosa la 502 ambalo linaonekana kama hitilafu ya programu.

loadbalancer.server.port=3000 ni port iliyo ndani ya kontena; Gitea husikiliza kwenye 3000 hapo. Kumbuka kuwa hakuna kontena ya programu inayochapisha port yoyote — Traefik pekee ndiyo inayofanya hivyo.

Uelekezaji (redirect) kwenye entrypoint ya web hubadilisha maombi ya plaintext kuwa 308 kwenda HTTPS. Port 80 inabaki wazi: ACME HTTP challenge inaihitaji, na binadamu wanaotypa jina la host bila protokali pia wanaihitaji.

$$ iliyozidishwa kwenye hash ya basic-auth ni njia ya Compose ya kuingiza alama (escaping), siyo makosa ya uandishi. Itengeneze kwa kutumia htpasswd -nbB admin 'your-password' (package apache2-utils), kisha zidisha kila $.

Cheti, na mtego wa acme.json

tlschallenge=true inachagua TLS-ALPN-01: Let's Encrypt inajiunga na seva yako kwenye port 443 na Traefik inajibu changamoto (challenge) ndani ya TLS handshake. Njia mbadala ni HTTP-01, kwenye port 80 — badilisha mstari wa tlschallenge kwenye orodha ya command: ya Traefik kwa mistari hii miwili:

      - --certificatesresolvers.le.acme.httpchallenge=true
      - --certificatesresolvers.le.acme.httpchallenge.entrypoint=web

Zote zinafanya kazi. Zote zinahitaji DNS ya umma kwa hostname iwe imeelekezwa kwenye VPS yako — mamlaka ya cheti (CA) inatafuta jina na kujiunga kutoka nje. Unda rekodi ya A (na AAAA) kwanza, thibitisha kwa kutumia dig +short git.example.com, kisha anza Traefik.

Sasa kuna mtego unaopoteza watu muda wao mwingi. Traefik huhifadhi funguo ya akaunti ya ACME na kila cheti kilichotolewa kwenye acme.json moja. Ikiwa faili hiyo inaweza kusomwa na kundi au kila mtu (world-readable), Traefik itatoa ujumbe unaofanana na huu na itasimama:

error: unable to get ACME account: permissions 644 for /letsencrypt/acme.json are too open, please use 600

Suluhisho bora ni lile lililopo juu: tumia bind-mount kwenye directory na uruhusu Traefik iunde faili yenyewe ikiwa na ukomo (mode) sahihi. Ikiwa uliunda acme.json kwa kutumia touch, umask yako ilifanya iwe 644. Irekebishe kwenye host:

chmod 600 ./letsencrypt/acme.json
docker compose restart traefik

Hifadhi (backup) directory hiyo kwa kutumia app volumes zako. Kupoteza faili hii kunaweza kuhimiliwa — vyeti vitatolewa upya — lakini kutoa vyeti vya hostnames tano kwa wakati mmoja kutakufanya ufikie mipaka ya matumizi (rate limits).

Tumia staging CA wakati unafanya majaribio. Ondoa alama ya commented kwenye mstari wa caserver, hakikisha kila njia (route) inafanya kazi, kisha weka tena alama ya commented na ufute acme.json ili vyeti vya uzalishaji (production) viombwe upya. Let's Encrypt ya uzalishaji inaruhusu vyeti vinavyofanana vitano kwa wiki kwa seti sawa ya hostnames, na inazuia uthibitishaji unaofeli mara kwa mara kwa jina lilelile. Staging hutoa vyeti visivyoaminika — kivinjari chako kitatoa onyo, na onyo hilo ndiyo ishara kwamba imefanya kazi — ikiwa na mipaka inayojeruhi zaidi.

Dashboard ni sehemu ya udhibiti, siyo demo

Miongozo mingi ya kuanza haraka huweka --api.insecure=true, ambayo hutoa dashboard kwenye port 8080 bila uthibitisho wa utambulisho. Hii ni hatari kwenye seva yenye IP ya umma, kwani inatoa muundo wa routing, majina ya host, majina ya middleware, na port za backend kwa mtu yeyote anayefanya scanning.

Lebo kwenye huduma ya traefik hapo juu ndiyo mbadala: dashboard inayopitishwa kama programu nyingine yoyote, kwa jina halisi la host, kupitia TLS, na nyuma ya basicauth. service=api@internal ndiyo inayounganisha router na API ya ndani ya Traefik. Imarisha zaidi kwa kutumia orodha ya kuruhusu IP (IP allow-list), inayotumika kuanzia kushoto kwenda kulia. Ikiwa anwani ya ofisi yako ni ya muda (dynamic), weka kiwango cha subnet inayotolewa na WireGuard VPN unayojiwekea kwenye VPS hiyo hiyo na ufikie dashboard kupitia njia hiyo tu:

- traefik.http.middlewares.office.ipallowlist.sourcerange=10.0.0.7/32
- traefik.http.routers.dashboard.middlewares=office,dashboard-auth

Docker socket ni root

/var/run/docker.sock ni API inayoweza kutengeneza container inayofunga / kutoka kwenye host. Ufikiaji wake ni sawa na kuwa na ruhusa ya root kwenye mashine, na Traefik inauhitaji ili kusoma labels.

Weka :ro kwenye mount, lakini fahamu faida yake: inafanya socket file iwe read-only. Haizuia maombi ya POST kwenye Docker API kupitia socket hiyo. Hatua bora ya usalama ni kutompa Traefik socket hiyo, bali weka proxy ya kuchuja katikati:

  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:
      - proxy

Ondoa volume ya socket kwenye Traefik na uelekeze provider kwenye proxy:

--providers.docker.endpoint=tcp://dockerproxy:2375

Traefik itabaki na uwezo wa kusoma containers na networks, lakini itapoteza uwezo wa kutengeneza kitu chochote.

Firewall, ports, na sheria ambayo kila mtu hukosea

Port mbili zimefunguliwa, pamoja na SSH:

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Port zilizochapishwa na Docker hupita ufw. Docker huweka sheria zake za iptables, ambazo hutumika kabla ya mnyororo wa ufw. Kwa sababu hiyo, container iliyoanzishwa na ports: ["3000:3000"] inaweza kufikiwa kutoka kwenye internet hata kama ufw imewekwa kuzuia (deny). Ulinzi huu ni wa kimuundo, si mpangilio wa firewall: chapisha port kutoka Traefik pekee, na upe container nyingine zote networks: [proxy] na hakuna kingine. Ikiwa kitu lazima kifike kwenye host, kishikize kwenye loopback — "127.0.0.1:3000:3000".

Troubleshooting: makosa utakayoyaona

404 page not found, inayotolewa na Traefik. Hakuna router iliyoendana. Kwa uwezekano mkubwa: container haina traefik.enable=true (ikiwa exposedByDefault=false imewekwa); sheria ya Host() haiendani na jina uliloandika; jina la router kwenye label moja ni tofauti na jina la router kwenye label nyingine (routers.gitea.rule na routers.gitea.entrypoints lazima ziwe neno moja); au uliweka hostname ndani ya alama za nukuu badala ya backticks. Traefik v3 inahitaji backticks ndani ya matchers.

502 Bad Gateway. Router iliendana lakini backend haipatikani. Mara nyingi container haipo kwenye network ya proxy — kagua docker inspect -f '{{json .NetworkSettings.Networks}}' gitea. Sababu nyingine ni loadbalancer.server.port isiyo sahihi: uliweka port iliyochapishwa, au app inasikiliza sehemu nyingine. Log inaonyesha jaribio: dial tcp 172.18.0.5:8080: connect: connection refused.

Browser inaonya, na cheti kinatolewa kwa TRAEFIK DEFAULT CERT. Hakuna cheti kwa hostname hiyo na Traefik imetoa cheti chake cha self-signed. Soma mistari ya ACME:

unable to obtain ACME certificate for domains "git.example.com" ...
acme: error: 400 ... DNS problem: NXDOMAIN looking up A for git.example.com

DNS bado haielekezi kwenye box. Rekebisha rekodi, subiri muda wa TTL, washa upya Traefik.

Invalid response from http://git.example.com/.well-known/acme-challenge/... kwenye HTTP challenge: port 80 haifikii Traefik kutoka nje — mara nyingi ni firewall ya kiwango cha mtoa huduma mbele ya VPS, si ufw.

Cheti hazitozi, na DNS yako iko Cloudflare ikiwa na orange cloud imewashwa. Cloudflare inafunga TLS kwenye edge yake na TLS-ALPN-01 haiwezi kukamilika kupitia hiyo. Weka rekodi kuwa DNS-only wakati unatoa cheti, au badilisha kwenda DNS-01 challenge ukitumia API token. DNS-01 ndiyo pia challenge pekee inayotoa wildcards.

Redirect loop. Kitu fulani mbele ya Traefik tayari kinafunga TLS na kutuma plaintext kwenda :80; entrypoint redirect inairudisha kwenye HTTPS. Ondoa moja kati ya redirects hizo mbili.

Kuifanya iendelee kufanya kazi

Unit ya Docker lazima iwe imewashwa wakati wa boot (systemctl is-enabled docker), na restart: unless-stopped hurudisha stack baada ya kuwasha upya mfumo. Kwa udhibiti kamili, unit ndogo ya systemd inayorun docker compose -f /srv/edge/compose.yml up -d ikiwa na RemainAfterExit=yes hukupa systemctl status edge na udhibiti wa mpangilio.

Tumia tag maalum ya Traefik (traefik:v3.5, usitumie latest). Uboreshaji kutoka v2 kwenda v3 ulibadilisha sintaksi ya sheria na majina ya provider, na latest isiyodhibitiwa itajibu upya konfigirei ambayo haielewi tena. Boresha kwa makusudi: soma maelezo ya uhamishaji, badilisha tag, docker compose up -d traefik, na uangalie logi. Ikiwa bado unatumia tag ya v2, mwongozo wa uhamishaji wa Traefik v2 kwenda v3 unaelezea kila mabadiliko ya jina, hali ya utangamano, na kurudisha nyuma (rollback) inayohifadhi vyeti vyako.

Hifadhi nakala (back up) ya ./letsencrypt na volume ya data ya kila app. Traefik haina hali nyingine ambayo huwezi kuijenga upya kutoka kwenye compose file.

Nini kinachovunjika unapoongeza ukubwa

Kizuizi cha kwanza si uwezo wa usindikaji (throughput), bali ni sanduku moja: Traefik moja kwenye VPS moja ni sehemu moja ya hitilafu (single point of failure) kwa programu tano, na acme.json ni hifadhi ya faili — mifumo miwili ya Traefik inayoiandika itaharibu faili hiyo. Kuongeza ukubwa (scaling out) kunamaanisha kuhamisha hifadhi ya cheti nje ya faili, au kumalizia TLS mahali pengine.

Cha pili ni miunganisho ya muda mrefu. Server-sent events, pakiaji kubwa, na wateja waliopolepole hukutana na muda wa kusubiri wa kuingia (entrypoint's responding timeouts); --entryPoints.websecure.transport.respondingTimeouts.readTimeout na ndugu zake writeTimeout na idleTimeout ndio vitufe vya kurekebisha. WebSockets hupita bila usanidi wowote wa ziada.

Cha tatu ni diski. --accesslog=true huandika kwenye stdout, na driver ya json-file ya Docker huweka hiyo kwafuu bila kikomo isipozuiwa. Weka logging.options.max-size kwenye huduma ya Traefik, au uandike logi ya ufikiaji (access log) kwenye faili na uifanye irotate.

Hakuna kati ya haya inayohitaji mratibu (orchestrator). Inahitaji tu seva unayodhibiti, yenye IP halisi na bandari (ports) 80 na 443 zilizofunguliwa kwa ulimwengu — VPS moja ndogo ndiyo orodha nzima ya mahitaji.

FAQ

Je, bado ninahitaji certbot ikiwa ninatumia Traefik?

Hapana. ACME resolver ya Traefik huomba na kuhuisha cheti kwa kila hostname inayopitisha, na huhifadhi vyote katika acme.json. Certbot bado ni chombo sahihi wakati nginx au seva nyingine inafanya TLS yenyewe; kuendesha vyote kwenye hostname zilezile kutatumia tu ukomo wa Let's Encrypt (rate limits).

Kwa nini container yangu inatoa 404 kupitia Traefik?

404 inayotolewa na Traefik inamaanisha hakuna router iliyofanana na ombi hilo. Hakikisha container ina traefik.enable=true (ni lazima pindi exposedByDefault=false inapowekwa), thamani ya Host() inafanana na jina uliloandika, na jina la router ni sawa katika kila label ya app hiyo. Traefik v3 pia inahitaji backticks ndani ya matcher, siyo quotes.

Kuna tofauti gani kati ya 404 na 502 hapa?

404 inamaanisha routing haikufanyika; 502 inamaanisha router ilifanana na ombi lakini backend ilikataa muunganisho. Sababu za kawaida za 502 ni container ambayo haijaunganishwa kwenye network ya proxy, na loadbalancer.server.port inayoelekeza kwenye port iliyochapishwa badala ya port ambayo app inasikiliza ndani ya container. Access log huonyesha anwani kamili ambayo Traefik iliunganisha.

Je, kuunganisha Docker socket kama read-only inatosha?

Flag ya :ro hufanya faili ya socket kuwa read-only, siyo API inayozingatia — POST bado hupitia hapo, na ufikiaji wa Docker API ni sawa na kuwa na root kwenye host. Mpangilio wenye nguvu zaidi ni container ya docker-socket-proxy iliyoonyeshwa hapo juu, ambayo huonyesha tu usomaji wa container na network kwa Traefik na huzuia uandishi kabisa.

Je, Traefik inaweza kutoa wildcard certificate?

Ni kupitia tu DNS-01 challenge, ukiwa na API token kwa ajili ya mtoa huduma wako wa DNS. TLS-ALPN-01 na HTTP-01 kila kimoja huhakiki hostname moja tu na haziwezi kutoa wildcard. DNS-01 pia ndiyo suluhisho wakati CDN kama Cloudflare inafanya TLS mbele ya VPS yako na challenge nyingine mbili hazikamiliki.

#traefik#docker-compose#reverse-proxy#tls#lets-encrypt#vps