SSD Nodes Learn 🎉 VPS kutoka $5.50/mwezi
Mwongozo Matt ConnorNa Matt Connor · Imeboreshwa 2026-08-13

Jinsi ya kuunganisha container kwenye mtandao wa Gluetun

Container iliyo nyuma ya Gluetun haina network interface zake. Jifunze jinsi ya kuchapisha port kwenye Gluetun na kufungua subnets mahususi ili kuruhusu mawasiliano ya nje.

Nini hutokea wakati container inapojiunga na mtandao wa gluetun

Container inayoweka network_mode: service:gluetun haina network interfaces zake zenyewe. Inajiunga na network namespace ya gluetun, kwa hivyo uchapishaji wa port na sheria za firewall huacha kuwa sifa za container hiyo na kuwa sifa za huduma ya gluetun. Kila jibu hapa chini linatokana na ukweli huo mmoja.

Network namespace ni nakala binafsi ya kernel ya network stack: ina interfaces zake, routing table yake, sheria zake za firewall na listening sockets zake. Docker huipa kila container moja kwa chaguo-msingi. Unapoandika network_mode: service:gluetun, Docker huruka hatua hiyo na kuiweka container mpya ndani ya namespace ambayo gluetun tayari inaimiliki. Container hudumisha filesystem yake na faili lake la /etc/hosts, na faili hilo la pili ni muhimu baadaye.

Unaweza kuona hili moja kwa moja.

docker inspect -f '{{.HostConfig.NetworkMode}}' qbittorrent

Hiyo huchapisha container: ikifuatiwa na ID ya container ya gluetun, ambapo container ya kawaida ingechapisha bridge. Mwongozo huu unaendelea pale routing Docker traffic through a VPN with gluetun ilipoishia: tunnel inafanya kazi, na sasa hakuna kinachoweza kuwasiliana na container hiyo.

Chapisha port kwenye gluetun, si kwenye programu

Acha block ya ports: kwenye huduma inayoweka network_mode na Docker itakataa kuunda container:

Error response from daemon: conflicting options: port publishing and the container type network mode

Sababu ni ya moja kwa moja. Kuchapisha port kunamaanisha kuongeza sheria ya NAT (network address translation) inayopeleka port ya host kwenye network namespace ya container, na container hii haina namespace hiyo. Hamisha mapping kwenye huduma ya gluetun. Namba ya port haibadiliki, kwa sababu programu bado inasikiliza kwenye port hiyo ndani ya namespace iliyoshirikiwa.

services:
  gluetun:
    ports:
      - "8080:8080/tcp"   # qBittorrent web UI

  qbittorrent:
    network_mode: "service:gluetun"
    # no ports: block here

Block ya expose: kwenye huduma inayotegemea nyingine haina maana yoyote, na block ya networks: hapo ni kikwazo kikubwa: Compose inaripoti kuwa huduma inatangaza network_mode na networks ambazo haziwezi kuwepo pamoja, na inakataa kupakia faili hiyo kabisa.

Matokeo moja hujitokeza baadaye. Kila container katika namespace inashiriki nafasi moja ya port, kwa hivyo programu mbili ambazo zote hutumia 8080 kama default hugongana, na ya pili kuanza inafeli kwa kosa la address already in use. Badilisha moja wapo katika configuration yake yenyewe, kwa mfano variable ya WEBUI_PORT kwenye image ya LinuxServer qBittorrent, kisha chapisha namba mpya kwenye gluetun.

Je, kontena zilizo nyuma ya gluetun hufikiana vipi?

Ndani ya namespace, tayari zinashiriki interface ya loopback. Kontena iliyo nyuma ya gluetun hufikia kontena nyingine iliyo karibu nayo kupitia 127.0.0.1:<port> bila kuhusisha mtandao wa Docker.

Kutoka nje ya namespace, kontena hiyo haina jina. DNS iliyopachikwa ya Docker hutatua jina la huduma (service name) kwenda kwenye anwani ya huduma hiyo katika mtandao uliotengenezwa na mtumiaji, na kontena hii haina anwani kwenye mtandao wowote. Kwa hivyo, kontena ya kawaida kama Sonarr haifikii mteja wa torrent kupitia http://qbittorrent:8080. Inamfikia kupitia http://gluetun:8080, kwa sababu socket inasikiliza kwenye namespace ya gluetun, kwenye anwani ya gluetun. Hilo huwashangaza watu wanaojua jinsi Docker Compose networks na service names zinavyofanya kazi na kutarajia utaratibu wa kawaida wa majina kutumika. Pia hufanya kazi bila kuchapisha (publish) chochote kwenye host, kwa kuwa kontena zote mbili ziko kwenye mtandao mmoja wa Compose.

Kagua DNS kabla ya kufanya utatuzi wa kitu kingine chochote. Gluetun huendesha resolver yake yenyewe na kuandika upya /etc/resolv.conf katika kontena yake, lakini /etc/resolv.conf ni faili ya kila kontena, kwa hivyo ile iliyoandikwa na gluetun si ile inayosomwa na programu yako.

docker exec qbittorrent cat /etc/resolv.conf

Ninawezaje kufikia huduma inayofanya kazi kwenye Docker host?

Tumia host.docker.internal. Inahitaji mipangilio miwili katika maeneo mawili tofauti, kwa sababu kuna vitu viwili tofauti vilivyoharibika.

Jina huja kwanza. /etc/hosts ni kwa kila container, kwa hivyo ingizo la extra_hosts ni la container ya programu, si la gluetun.

  prowlarr:
    network_mode: "service:gluetun"
    extra_hosts:
      - "host.docker.internal:host-gateway"

host-gateway ni thamani maalum ambayo Docker huibadilisha na anwani ya ndani ya host yenyewe. Kwenye usakinishaji wa kawaida wa Linux Docker, hiyo ni anwani ya bridge ya docker0, ambayo kwa kawaida ni 172.17.0.1. Thibitisha anwani yako kwa kutumia ip -4 addr show docker0 kwenye VPS. Docker Desktop hutatua jina hili yenyewe, ndiyo maana miongozo iliyoandikwa kwenye laptop huruka mstari wa extra_hosts na faili hiyo hiyo hushindwa kufanya kazi kwenye seva.

Njia (route) huja ya pili. Kuongeza jina huambia container anwani ipi itumike. Paketi bado hutoka kupitia njia chaguo-msingi ya gluetun, ambayo ni tunnel, na firewall ya gluetun huizuia. Dalili yake ni muunganisho unaokwama na kisha kuisha muda (timeout), badala ya kukataliwa. Kukataliwa kunamaanisha paketi ilifika na kitu kikajibu hapana. Timeout inamaanisha haikufika kabisa.

  gluetun:
    environment:
      - FIREWALL_OUTBOUND_SUBNETS=172.17.0.1/32

Kisha hakikisha huduma ya host inasikiliza (listening) kwenye anwani hiyo. Seva ya PostgreSQL iliyofungwa kwenye 127.0.0.1 pekee haiwezi kufikiwa kutoka kwa container yoyote, iwe na tunnel au la, kwa sababu 127.0.0.1 ndani ya namespace ni loopback ya namespace hiyo yenyewe. Ifunge kwenye 172.17.0.1 badala yake: itakubali miunganisho kutoka kwa containers huku ikibaki nje ya interface ya umma. Thibitisha kwa kutumia ss -lntp | grep 5432 kwenye host.

Kile ambacho FIREWALL_OUTBOUND_SUBNETS hubadilisha kwa hakika

Nyaraka za gluetun zinaielezea kama orodha ya subnets zilizotenganishwa kwa koma ambazo gluetun na containers zinazoshiriki network stack yake zinaruhusiwa kufikia, na inabainisha kuwa inahusisha mabadiliko ya firewall na routing. Sehemu zote mbili ni muhimu. Gluetun huongeza route kwa kila subnet iliyoorodheshwa kupitia Docker bridge gateway, ili pakiti za anwani hizo ziondoke kupitia eth0 badala ya kupitia tunnel. Pia hufungua firewall kwa ajili yao, kwa sababu vinginevyo gluetun huzuia traffic ya kutoka ambayo haielekei kwenye VPN server.

Andika thamani hiyo bila nafasi (spaces) baada ya koma.

      - FIREWALL_OUTBOUND_SUBNETS=172.17.0.1/32,192.168.1.0/24,100.64.7.9/32

Kuna sifa mbili ambazo ni rahisi kuzisahau. Hii ni mipangilio ya kiwango cha namespace, kwa hivyo inahusu kila container iliyo nyuma ya gluetun, si ile uliyokuwa ukiifikiria pekee. Na ni kwa ajili ya traffic ya kutoka pekee: inasimamia miunganisho ambayo container huanzisha. Miunganisho inayofika kwenye port iliyochapishwa (published port) hufuata njia tofauti na haihitaji kuingizwa hapa.

Kufikia web UI kutoka kwa peer wa Tailscale

Tailscale huipa kila mashine anwani katika 100.64.0.0/10, masafa yaliyotengwa kwa ajili ya carrier grade NAT. Maelekezo haya mawili yanahitaji kazi tofauti.

Inbound ndiyo rahisi zaidi. Kuchapisha 8080:8080 kwenye gluetun hufunga port hiyo kwenye anwani zote za host, na interface ya tailscale0 ya host ni mojawapo, kwa hivyo peer hufungua http://<machine-name>:8080 na kufikia container. Gluetun haihusiki katika njia hiyo, kwa sababu sheria ya NAT ya Docker iko kwenye host, nje ya namespace.

Ili kufanya UI ifikike kupitia tailnet pekee, funga port iliyochapishwa kwenye anwani ya Tailscale ya host badala ya kila anwani.

    ports:
      - "100.101.102.103:8080:8080/tcp"

Tafuta anwani hiyo kwa kutumia tailscale ip -4 kwenye host. Kufunga (binding) ni udhibiti thabiti zaidi kuliko sheria ya firewall hapa, kwa sababu port haifunguliwi kabisa kwenye interface ya umma. Pia huepuka tatizo lililo katika Docker kuchapisha port moja kwa moja kupita ufw.

Outbound ndipo FIREWALL_OUTBOUND_SUBNETS inaporejea. Ikiwa container inapaswa kupiga simu kwa peer, ongeza anwani ya peer huyo, na upendelee /32 kwa kila peer badala ya /10 nzima. Majina ya MagicDNS hayatatatuliwa ndani ya container, kwa sababu container haitumii resolver ya host, kwa hivyo tumia anwani ya namba ya 100.x au iweke kwa kutumia mstari wa extra_hosts. Vivyo hivyo hutumika unapoendesha seva yako ya kudhibiti Tailscale ukitumia Headscale.

Faili kamili la compose kwa muundo wa kawaida

Mteja wa kupakua (download client) aliye nyuma ya VPN, violesura viwili vya wavuti (web UIs) vinavyojibu kwenye tailnet pekee, na kontena moja linalosoma database ya PostgreSQL inayoendeshwa kwenye seva mwenyeji (host).

services:
  gluetun:
    image: qmcgaw/gluetun:latest
    container_name: gluetun
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun:/dev/net/tun
    ports:
      - "127.0.0.1:8000:8000/tcp"        # gluetun control server, host only
      - "100.101.102.103:8080:8080/tcp"  # qBittorrent UI, tailnet only
      - "100.101.102.103:9696:9696/tcp"  # Prowlarr UI, tailnet only
    volumes:
      - ./gluetun:/gluetun
    environment:
      - VPN_SERVICE_PROVIDER=mullvad
      - VPN_TYPE=wireguard
      - WIREGUARD_PRIVATE_KEY=${WIREGUARD_PRIVATE_KEY}
      - WIREGUARD_ADDRESSES=${WIREGUARD_ADDRESSES}
      - SERVER_CITIES=Amsterdam
      - FIREWALL_OUTBOUND_SUBNETS=172.17.0.1/32,100.64.7.9/32
      - TZ=Europe/Amsterdam
    restart: unless-stopped

  qbittorrent:
    image: lscr.io/linuxserver/qbittorrent:latest
    network_mode: "service:gluetun"
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Amsterdam
      - WEBUI_PORT=8080
    volumes:
      - ./qbittorrent:/config
      - /srv/downloads:/downloads
    depends_on:
      gluetun:
        condition: service_healthy
    restart: unless-stopped

  prowlarr:
    image: lscr.io/linuxserver/prowlarr:latest
    network_mode: "service:gluetun"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Amsterdam
      - PROWLARR__POSTGRES__HOST=host.docker.internal
      - PROWLARR__POSTGRES__PORT=5432
      - PROWLARR__POSTGRES__USER=prowlarr
      - PROWLARR__POSTGRES__PASSWORD=${PROWLARR_DB_PASSWORD}
      - PROWLARR__POSTGRES__MAINDB=prowlarr-main
      - PROWLARR__POSTGRES__LOGDB=prowlarr-log
    volumes:
      - ./prowlarr:/config
    depends_on:
      gluetun:
        condition: service_healthy
    restart: unless-stopped

Soma faili hili ili uone muundo badala ya majina ya bidhaa. Violesura vyote viwili vimechapishwa kwenye gluetun na kufungwa kwenye anwani ya tailnet ya host, kwa hivyo vinajibu kupitia Tailscale pekee na si mahali pengine. Prowlarr pekee ndiyo inayobeba mstari wa extra_hosts, kwa sababu Prowlarr ndiyo kontena linalotatua host.docker.internal. FIREWALL_OUTBOUND_SUBNETS inataja anwani mbili za kipekee: anwani ya Docker bridge ya host, ili Prowlarr iweze kufungua muunganisho wa database, na peer mmoja wa tailnet.

Seva ya PostgreSQL haipo kwenye faili hili kwa makusudi. Inaendeshwa kwenye VPS kama huduma ya kawaida ya mfumo inayosikiliza kwenye 172.17.0.1:5432. Hiyo ni layering sawa na arr stack kwenye Docker Compose, huku database ikiwa nje ya Docker.

Weka ufunguo wa siri (private key) wa WireGuard nje ya faili la compose. .env inasoma kutoka kwenye faili la ${WIREGUARD_PRIVATE_KEY} lililo kando yake, muundo ulioshughulikiwa katika faili za env na siri kwa Docker Compose. Kifungu cha condition: service_healthy kinatumia healthcheck ambayo image ya gluetun inakuja nayo, kwa hivyo hakuna kinachoanza hadi tunnel itoe taarifa kuwa iko tayari. Compose healthchecks zinaelezea muundo wa jumla.

Kuchapisha kwenye kila anwani badala ya tailnet pekee

Ondoa kiambishi cha anwani na vifungo vya port kwenye 0.0.0.0, ambavyo vinajumuisha IP ya umma ya VPS. Fanya hivi tu ukiwa nyuma ya firewall unayoimiliki, na usome dokezo la ufw hapo juu kwanza.

    ports:
      - "8080:8080/tcp"

Thibitisha kuwa handaki bado linapitisha trafiki

Tekeleza ombi lilelile mara mbili, mara moja ukiwa ndani ya namespace na mara nyingine ukiwa kwenye host, kisha ulinganishe matokeo.

docker run --rm --network=container:gluetun curlimages/curl:latest -s https://api.ipify.org
curl -s https://api.ipify.org

Ombi la kwanza linapaswa kuonyesha anwani ya kutoka (exit address) ya mtoa huduma wako wa VPN. La pili linapaswa kuonyesha anwani ya VPS yako. Ikiwa zinafanana, trafiki ya container haipiti kwenye handaki, na kila marekebisho katika mwongozo huu hayana maana hadi hapo tatizo hilo litakaporekebishwa.

Jedwali la uelekezaji (routing table) linaonyesha kile kinachopita nje ya handaki na kile kisichopita.

docker run --rm --network=container:gluetun alpine:3.22 ip route show

Njia chaguo-msingi (default route) inapaswa kuelekeza kwenye kiolesura cha handaki, tun0. Chini yake unapaswa kuona njia moja kwa kila ingizo katika FIREWALL_OUTBOUND_SUBNETS, ikielekeza kwenye gateway ya Docker bridge. Njia nyingine yoyote inayotoka kupitia eth0 ni trafiki inayokwepa VPN.

Seva ya udhibiti ya Gluetun inaripoti anwani hiyo hiyo ya IP ya umma kwenye port 8000, katika /v1/publicip/ip. Matoleo mapya yanahitaji usanidi wa uthibitishaji (authentication) kwa njia za seva ya udhibiti, kwa hivyo sanidi hilo kabla ya kuitegemea.

Uvujaji unaosababishwa na subnet isiyo sahihi

FIREWALL_OUTBOUND_SUBNETS ni tundu unalotoboa kwenye firewall kwa makusudi, kwa hivyo ukubwa wa tundu hilo ndio ukubwa wa hatari. Kuna njia nne za kulifanya liwe kubwa kupita kiasi:

  • 0.0.0.0/0 hutuma kila kitu nje ya tunnel. Ukaguzi wa IP mbili hapo juu hubaini hili katika jaribio la kwanza, kwa sababu zitarudisha anwani ileile.
  • Masafa mapana kuliko lengwa. Kufungua 10.0.0.0/8 ili kufikia mashine moja kwenye 10.0.1.7 pia hufungua kila anwani ambayo peer wa torrent anaweza kutangaza ndani ya masafa hayo. Andika 10.0.1.7/32.
  • Masafa yanayoingiliana na anwani za tunnel yenyewe. Nyaraka za gluetun huonya kuwa hii huifanya gluetun kutuma trafiki ya VPN kupitia bridge badala yake, jambo ambalo huvunja port forwarding. Hakikisha thamani yako ya WIREGUARD_ADDRESSES kabla ya kufungua masafa yoyote ya kibinafsi.
  • 100.64.0.0/10 kwa ajili ya Tailscale. Hiyo ni takriban anwani milioni nne zilizofunguliwa ili peer mmoja aweze kufikiwa. Orodhesha peers unaohitaji kama entries za /32.

Kumbuka kuwa mpangilio huu unahusu namespace nzima. Kufungua subnet ili indexer iweze kufikia huduma ya host hufungua subnet hiyo hiyo kwa torrent client inayoshiriki namespace hiyo. Rudia ukaguzi wa IP ya umma baada ya kila mabadiliko kwenye variable hii, kwa sababu huo ndio mtihani pekee unaoonyesha kama mabadiliko yamefanya kile ulichokusudia.

Nini kinaharibika unapowasha upya gluetun

gluetun inamiliki namespace, kwa hivyo mzunguko wa maisha wa gluetun ndio mzunguko wa maisha wa namespace hiyo. Kuanzisha container inayotegemea gluetun wakati gluetun imezimwa kunashindwa mara moja:

Error response from daemon: cannot join network of a non running container

Kuwasha upya gluetun bila kuondoa container nyingine ni hitilafu isiyoonekana wazi. Container zinazotegemea gluetun zinaendelea kufanya kazi wakati namespace zilizounganishwa nazo zinajengwa upya chini yake, hivyo docker ps inaripoti kuwa kila kitu ni sawa ilhali hakuna kinachojibu. Baada ya mabadiliko yoyote kwenye huduma ya gluetun, tengeneza upya kundi zima badala ya kuwasha upya sehemu moja tu.

docker compose up -d --force-recreate

Hali hiyo inatumika pia kwa masasisho ya image. Kuvuta image mpya ya gluetun na kutengeneza upya huduma hiyo pekee kunaziacha huduma nyingine zikielekeza kwenye namespace ambayo haipo tena.

FAQ

Kwa nini Docker inasema "port publishing and the container type network mode"?

Kwa sababu kizuizi cha ports: bado kipo kwenye huduma inayoweka pia network_mode: service:gluetun. Kuchapisha (publish) port huongeza sheria ya NAT inayoelekeza port ya host kwenye network namespace ya container, na container iliyo katika hali hii haina namespace hiyo. Futa kizuizi cha ports: kutoka kwenye huduma hiyo na uongeze mapping inayofanana kwenye huduma ya gluetun. Namba ya port inabaki ileile, kwa sababu programu bado inaisikiliza ndani ya namespace iliyoshirikiwa.

Je, container nyingine zinafikiaje huduma iliyo nyuma ya gluetun?

Container zilizo ndani ya namespace moja hufikiana kupitia 127.0.0.1. Container zilizo nje yake hutumia jina la huduma ya gluetun, kwa hivyo http://gluetun:8080 hufanya kazi ambapo http://qbittorrent:8080 haifanyi. Container ya programu haina anwani kwenye network yoyote ya Docker, kwa hivyo seva ya DNS iliyopachikwa haina cha kutatua (resolve) kwa jina lake. Hakuna haja ya kuchapisha port kwa ajili ya hili, mradi container zote mbili zinashiriki network moja ya Compose.

Niweke nini kwenye FIREWALL_OUTBOUND_SUBNETS?

Anwani pekee ambazo container iliyo nyuma ya gluetun lazima ianzishe muunganisho kwazo, zikiwa zimeandikwa kwa usahihi iwezekanavyo. Mashine moja ni /32. Ingizo mbili za kawaida ni Docker host kwenye 172.17.0.1/32 na /32 moja kwa kila Tailscale peer unayoiita. Usiongeze kamwe 0.0.0.0/0, na usiongeze kamwe masafa (range) yanayoingiliana na anwani za tunnel ya VPN yako. Miunganisho ya ndani (inbound) kwenye port iliyochapishwa haihitaji ingizo lolote hapa.

Kwa nini container haiwezi kutatua (resolve) majina yangu ya Tailscale MagicDNS?

MagicDNS hufanya kazi kwa kuelekeza resolver ya host kwenye seva ya DNS ya Tailscale, na container haitumii resolver ya host. Inatumia chochote kinachosemwa na /etc/resolv.conf yake yenyewe, ambayo nyuma ya gluetun ni usanidi wa DNS wa gluetun. Thibitisha kwa docker exec <container> cat /etc/resolv.conf. Tumia anwani ya namba 100.x ya peer, au funga jina hilo kwa ingizo la extra_hosts kwenye container hiyo.

Ninawezaje kuthibitisha kuwa trafiki bado inapita kwenye VPN?

Tekeleza ombi moja kutoka ndani ya namespace na ombi hilohilo kutoka kwenye host, kisha linganisha majibu. docker run --rm --network=container:gluetun curlimages/curl:latest -s https://api.ipify.org inapaswa kurudisha anwani ya kutoka (exit address) ya mtoa huduma wako wa VPN, wakati curl -s https://api.ipify.org kwenye VPS inarudisha anwani ya VPS. Majibu mawili yanayofanana yanamaanisha kuwa tunnel haibebi trafiki ya container. Fanya ukaguzi huu tena baada ya kila mabadiliko kwenye FIREWALL_OUTBOUND_SUBNETS.