Jinsi ya kuunganisha Docker container kwenye VPN
Je, port zako zinapotea unapotumia Gluetun? Hii hutokea kwa sababu ya shared network namespace. Jifunze kusanidi Docker Compose ili kurudisha muunganisho wako kwa usahihi.
Kwa nini port hupotea unapoelekeza Docker containers kupitia VPN
Ili kuelekeza Docker containers kupitia VPN, unakabidhi container moja njia ya tunnel, kisha unaunganisha nyingine kwenye network namespace yake kwa kutumia network_mode: "service:gluetun". Muunganiko huo ndio sehemu inayowashangaza watu. Container iliyounganishwa haina tena network yake yenyewe, hivyo port zake zilizochapishwa na jina la huduma ya Docker hupotea pamoja nayo. Chapisha port kwenye container ya VPN badala yake, na containers nyingine zitafikia programu hiyo kwa kutumia jina la container ya VPN.
Ukiacha block ya ports: kwenye container iliyounganishwa, Docker itakataa kuunda container hiyo kabisa:
Error response from daemon: conflicting options: port publishing and the container type network modeZana inayotumika hapa ni Gluetun, container inayounganisha na mtoa huduma wa VPN (virtual private network) wa kibiashara kupitia WireGuard au OpenVPN na ina firewall yake yenyewe. Release v3.41.3 ndiyo ya sasa kufikia Agosti 2026. Mifano hii inatumia Mullvad na WireGuard, kwa hivyo unahitaji akaunti na ufunguo kutoka kwa mtoa huduma wako. Ikiwa ungependa kumalizia tunnel kwenye maunzi unayomiliki, kuendesha seva yako ya WireGuard kwenye VPS hujenga upande mwingine, na wg-easy katika Docker huifunga hiyo kwenye kiolesura cha wavuti.
Kazi halisi ya network_mode: "service:gluetun"
Kila container ya Docker kwa kawaida hupata network namespace yake yenyewe: ina interface zake, jedwali la routing, sheria za firewall na soketi zinazosikiliza. Hali ya service: huruka hatua hiyo na kuanzisha container ndani ya namespace ya gluetun. Namespace moja inamaanisha anwani moja ya IP, na hilo hubadilisha mambo sita.
- App haina anwani yake yenyewe. Anwani yake ni ile ya gluetun.
- App haijaunganishwa kwenye network yoyote ya Docker, kwa hivyo jina la huduma yake halisajiliwi na halitatuliwi kamwe. Container nyingine lazima zitumie
gluetun. - Container zilizo ndani ya namespace hiyo hufikiana kupitia
localhost. - Container mbili katika namespace moja haziwezi kusikiliza kwenye port moja. Nyaraka za Gluetun ziko wazi kuhusu hili: hakuna njia mbadala.
- Uwezo (capabilities) ni wa container, si wa namespace. Gluetun inashikilia
NET_ADMINna/dev/net/tunkwa sababu inaunda interface ya tunnel. Container iliyounganishwa haiyarithi. - Compose hukataa faili yoyote ambapo huduma moja imeweka
network_modenanetworkskwa wakati mmoja. Unganisha gluetun kwenye network zako, na app itafuata huko.
Kuanzisha upya gluetun hukata muunganisho wa kila kitu kilichounganishwa nayo. Hiyo ni tabia iliyoandikwa kwenye nyaraka, na ndiyo sababu gluetun huanzisha upya mchakato wa VPN ndani ya container badala ya kuzima wakati muunganisho unaposhindwa. Baada ya kuanzisha upya au kuunda upya gluetun mwenyewe, anzisha upya container zilizounganishwa nayo.
Faili la compose linalofanya kazi
services:
gluetun:
image: qmcgaw/gluetun:v3
container_name: gluetun
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
environment:
- VPN_SERVICE_PROVIDER=mullvad
- VPN_TYPE=wireguard
- SERVER_CITIES=Amsterdam
- TZ=Europe/Amsterdam
env_file:
- ./gluetun.env
volumes:
- ./gluetun:/gluetun
ports:
- 127.0.0.1:8080:8080/tcp
restart: unless-stopped
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:latest
container_name: qbittorrent
network_mode: "service:gluetun"
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Amsterdam
- WEBUI_PORT=8080
volumes:
- ./qbittorrent:/config
- ./downloads:/downloads
depends_on:
gluetun:
condition: service_healthy
restart: unless-stoppedTag ya :v3 ndiyo toleo jipya zaidi la stable katika mfululizo wa v3. Tag ya :latest inaelekeza kwenye commit ya mwisho ya branch ya master, ambayo ndiyo toleo la maendeleo, kwa hivyo tumia :v3 kwenye mashine ambayo hutaki kuifanyia debugging siku ya Jumanne.
WEBUI_PORT=8080 lazima ilingane na port iliyochapishwa, kwa sababu qBittorrent inajifunga ndani ya namespace ya gluetun na sheria ya kuchapisha hupeleka trafiki ya host kwenye port 8080 huko. Badilisha namba moja bila kubadilisha nyingine na port haitaitikia chochote. 127.0.0.1:8080:8080 huweka kiolesura cha wavuti kwenye anwani ya loopback ya host. 8080:8080 tupu huchapisha kwenye kila interface na kuandika sheria yake ya firewall, ambayo ndiyo njia ambayo Docker published ports slip straight past ufw.
Iwashe, kisha iangalie kwa utaratibu huu:
docker compose up -d
docker compose ps
docker compose logs gluetun | tail -30docker compose ps inapaswa kuonyesha gluetun kama healthy na qbittorrent kama running. Kisha thibitisha anwani ya kutoka (exit address) ukiwa ndani ya namespace, ambayo ndiyo ukaguzi unaoamua kila kitu kingine:
docker run --rm --network=container:gluetun alpine:3.22 sh -c "apk add wget && wget -qO- https://ipinfo.io"Sehemu ya ip katika JSON hiyo inapaswa kuwa anwani ya mtoa huduma wako wa VPN. Ikiwa ni anwani ya seva yako mwenyewe, programu haiko ndani ya tunnel, na hakuna kitu hapa chini kitafanya kazi kama ilivyoelezwa.
Weka funguo nje ya faili ya compose
gluetun.env huhifadhi vitambulisho, na haipaswi kuingizwa kwenye git:
WIREGUARD_PRIVATE_KEY=wOEI9rqqbDwnN8/Bpp22sVz48T71vJ4fYmFWujulwUU=
WIREGUARD_ADDRESSES=10.64.222.21/32Thamani zote mbili zinatoka kwenye faili ya usanidi ya WireGuard unayotengeneza katika eneo la akaunti ya mtoa huduma wako. Weka faili hiyo katika mode 600. Kuwa mkweli kuhusu faida unayopata: ufunguo hauingii kwenye hazina yako (repository), lakini docker inspect gluetun bado huchapisha kila variable ya mazingira kwa yeyote anayeweza kufikia Docker socket. Faili za mazingira na siri katika Docker Compose inashughulikia chaguo imara zaidi.
Jinsi container iliyo nje ya tunnel inavyowasiliana na iliyo ndani
Mwelekeo wote miwili hufanya kazi, na kila mmoja hutumia jina tofauti. Container hizi mbili zinahitaji mtandao wa Docker unaoshirikiwa, ambao ni mtandao wa gluetun, kwa sababu container iliyounganishwa haina mtandao wake. Jinsi mitandao ya Docker Compose inavyounganishwa inaelezea mipangilio ya kawaida.
Kutoka nje kwenda ndani, tumia jina la gluetun na port ambayo programu inasikiliza. Container ya reverse proxy hufikia interface ya wavuti ya qBittorrent kupitia gluetun:8080. Hakuna ingizo la ports: linalohitajika kwa hilo, kwa sababu trafiki kati ya container hubaki kwenye mtandao wa Docker na haigusi kamwe port ya host.
Kutoka ndani kwenda nje, tumia jina la huduma ya container nyingine, kwa mfano postgres:5432. Gluetun imekuwa ikitatua majina ya container nyingine kutoka ndani ya namespace yake tangu v3.41, kwa hivyo tumia toleo hilo au jipya zaidi ikiwa jina linakataa kutatuliwa.
Firewall ya gluetun huamua nani anaweza kufungua muunganisho kwake. Trafiki kutoka kwenye mtandao wa Docker wa gluetun yenyewe inaruhusiwa. Mteja aliye kwenye subnet tofauti, kompyuta kwenye LAN yako au container kwenye mtandao mwingine wa bridge, atakataliwa hadi utakapoitaja subnet hiyo:
FIREWALL_OUTBOUND_SUBNETS=192.168.1.0/24Maana iliyoandikwa ni sahihi: subnet zilizotenganishwa kwa koma ambazo Gluetun na container zinazoshiriki stack yake ya mtandao zinaruhusiwa kufikia.
Miunganisho ya ndani kutoka kwenye Internet ni tatizo tofauti. Peers wa mteja wa torrent hufika kutoka upande wa VPN, kwa hivyo kuchapisha port 6881 kwenye host hakuwasaidii. Unahitaji port iliyopitishwa (forwarded port) kutoka kwa mtoa huduma wako, na port hiyo iorodheshwe kwenye FIREWALL_VPN_INPUT_PORTS, ambayo inaruhusu port kutoka upande wa seva ya VPN. Hii ndiyo sehemu ambayo stack za media zilizojengwa kwa Docker Compose nyingi huacha ikiwa haifanyi kazi.
Kill switch: nini hutokea wakati tunnel inapokatika
Muundo huu unakuwa mgumu pale unaposhindwa kufanya kazi. Container iliyounganishwa haina njia mbadala ya mawasiliano. Njia yake pekee ya kutoka nje ya mashine ni kupitia namespace inayoshiriki, kwa hivyo tunnel inaposhuka hakuna njia nyingine ya kutumia. Firewall ya Gluetun inatekeleza sheria hiyo hiyo kutoka upande wa pili: trafiki ya kutoka nje lazima ipite kwenye tunnel au kwenda kwenye endpoint ya seva ya VPN, na kila kitu kingine kinakataliwa. Hakuna muda ambapo pakiti zinaweza kuvuja kupitia interface ya kawaida wakati mteja anapojaribu kuunganisha upya.
Gluetun hufuatilia muunganisho wake wenyewe. Kila dakika hutuma ICMP echo (ping) kwenye anwani zilizopo katika HEALTH_ICMP_TARGET_IPS, ambazo kwa kawaida ni 1.1.1.1,8.8.8.8. Kila baada ya dakika tano, hufanya TCP na TLS (transport layer security) dial kamili kwenda HEALTH_TARGET_ADDRESSES, ambayo kwa kawaida ni cloudflare.com:443,github.com:443. Pale majaribio hayo yanaposhindwa, huanzisha upya VPN ndani ya container na kuandika logi:
WARN [vpn] restarting VPN because it failed to pass the healthcheck: periodic check: dialing: dial tcp4: lookup cloudflare.com: i/o timeoutSoma logi za container iliyounganishwa kwa kuzingatia utaratibu huo. Mistari kama connection refused, operation not permitted na i/o timeout ndani ya programu ni matokeo ya tunnel iliyokufa, siyo sababu zake. Nyaraka za Gluetun zinasema hili waziwazi, kwa sababu watu huripoti matokeo hayo na kuyatafuta kwa saa nyingi.
HEALTH_RESTART_VPN=on ndiyo chaguo-msingi na inapaswa kubaki ikiwa imewashwa. Iizime tu wakati unapotatua hitilafu moja mahususi, kwa sababu ikiwa imezimwa, tunnel iliyokufa itabaki hivyo bila kujiimarisha.
Kupanga: kuzuia stack kuanza kabla ya tunnel kuwa tayari
Image hii inakuja na Docker healthcheck:
HEALTHCHECK --interval=5s --timeout=5s --start-period=10s --retries=1 CMD /gluetun-entrypoint healthcheckAmri hiyo huendesha nakala ya pili ya muda mfupi ya gluetun ambayo huuliza seva ya afya ya ile inayofanya kazi kwenye http://127.0.0.1:9999/. Tunnel inayofanya kazi hujibu 200 OK. Tunnel iliyoharibika hujibu 500 Internal server error ikiwa na ujumbe wa hitilafu, na container huwekwa alama ya kutokuwa na afya baada ya kufeli mara moja.
condition: service_healthy ndiyo inayongojea hali hiyo. depends_on: [gluetun] ya kawaida husubiri tu container kuanza, jambo linalotokea sekunde kadhaa kabla ya handshake kukamilika, kwa hivyo programu huanza kwenye mtandao uliokufa na mara nyingi hukata tamaa kwenye jaribio lake la kwanza la muunganisho. Healthchecks katika Docker Compose inaelezea sintaksia na sehemu za muda.
Kikomo kimoja huwasumbua watu. Compose hutathmini sharti hilo mara moja, wakati wa kuunda container. Haizuii au kuanzisha upya programu baadaye ikiwa gluetun itakuwa na afya mbaya. Ujirekebishaji wa ndani wa gluetun hushughulikia hali hiyo, ndiyo maana huanzisha upya mchakato wa VPN badala ya container yenyewe.
Kagua uvujaji wa DNS kabla ya kuamini usanidi
DNS (domain name system) ndiyo njia ya uvujaji inayobaki hata baada ya tunnel kusanidiwa kwa usahihi. Gluetun huendesha resolver yake ndani ya namespace na kusambaza maombi kupitia DoT (DNS over TLS) kwenda Cloudflare kwa chaguo-msingi: DNS_UPSTREAM_RESOLVER_TYPE=dot na DNS_UPSTREAM_RESOLVERS=cloudflare. Acha mipangilio yote miwili kama ilivyo ili utafutaji wako uwe umesimbwa na kupita ndani ya tunnel.
Mpangilio unaovunja usalama huu ni DNS_UPSTREAM_PLAIN_ADDRESSES. Watu huutumia wakati jina linashindwa kutatuliwa (resolve) na wanataka router yao au resolver ya mtoa huduma wao ijibu badala yake. Nyaraka za Gluetun zinaeleza gharama yake waziwazi: trafiki yote ya DNS haitapita kwenye VPN tunnel na itavuja nje yake. Trafiki yako inabaki kuwa ya faragha. Orodha yako ya hostnames haibaki kuwa ya faragha. Toleo la WireGuard la kosa hili linafafanuliwa katika DNS inayoacha kufanya kazi kupitia WireGuard tunnel.
Ili kuijaribu, weka HTTPPROXY=on kwenye gluetun na uchapishe 8888:8888/tcp, kisha elekeza kivinjari kwenye proxy hiyo na uendeshe jaribio la uvujaji wa DNS. Matokeo yanapaswa kutaja mtoa huduma wako au Cloudflare, kamwe si router ya nyumbani kwako. Nyaraka za Gluetun zenyewe zinaonya kuwa baadhi ya majaribio ya uvujaji huripoti matokeo yasiyo ya kawaida, kwa sababu resolver iliyo ndani ya namespace ni mpatanishi wa kuhifadhi data (caching intermediary) badala ya seva inayojibu mwishoni. Chukulia nchi isiyo sahihi au resolver ya ISP wako kama ishara halisi ya tatizo.
Kuongeza Tailscale kando ya VPN sidecar, na ni ipi inayoshinda
Tailscale ni mtandao wa overlay ulioundwa juu ya WireGuard kwa ajili ya kufikia mashine zako, na watu huutumia kando ya VPN ya mtoa huduma ili kudumisha njia ya kiutawala (admin path) ya kuingia kwenye stack. Huduma hizi mbili mara chache hugongana, kwa sababu inayostahili kueleweka. Nyaraka za Tailscale zinaeleza hali ya kawaida: inafanya kazi kama mtandao wa overlay, inaelekeza trafiki kati ya vifaa vinavyotumia Tailscale pekee, na haigusi trafiki yako ya umma ya Internet.
Kwa hiyo jibu linategemea mpangilio mmoja.
- Tailscale katika container yake yenyewe, usanidi wa kawaida: haioni trafiki ya nje ya programu. Gluetun hubeba trafiki yote. Tailscale hufikia programu kwenye
gluetun:8080, kama vile container nyingine yoyote ya nje. - Tailscale iliyounganishwa kwenye namespace ya gluetun kwa kutumia
network_mode: "service:gluetun": inahitajicap_addyake yenyewe yanet_adminnanet_raw, kwa sababu uwezo (capabilities) hauji na namespace. Katika hali ya kawaida ya userspace networking,TS_USERSPACEikiwa imewashwa, tailscaled haitengenezi interface yoyote na inafanya kazi kama SOCKS5 au HTTP proxy, kwa hivyo haiwezi kubadilisha uelekezaji (routing). Gluetun bado hubeba kila kitu. - Hali hiyo hiyo, ikiwa na
TS_USERSPACE=false: tailscaled hutengeneza kifaa cha tunnel na kuweka routes, lakini kwa ajili ya range ya tailnet100.64.0.0/10pekee pamoja na subnet routes zozote unazotangaza kwaTS_ROUTES. Trafiki ya umma bado hutoka kupitia gluetun. - Yoyote kati ya hayo hapo juu ikiwa na exit node iliyochaguliwa,
sudo tailscale set --exit-node=<exit-node-ip>: Tailscale inachukua default route na kushinda. Usichanganye hiyo na gluetun. Default route moja, mmiliki mmoja.
Athari moja huonekana wakati Tailscale inapoendeshwa ndani ya tunnel. Peers zake huona anwani ya mtoa huduma wa VPN, kwa hivyo tarajia itumie relays mara nyingi zaidi. tailscale status huonyesha relay "..." kando ya peer badala ya direct wakati hilo limetokea. Muunganisho hufanya kazi na huwa polepole. Ikiwa overlay ndiyo kitu pekee ulichohitaji, tofauti kati ya WireGuard ya kawaida na Tailscale ndiyo sehemu bora ya kuanzia.
Nini kinaharibika, na ujumbe utakaouona
Docker inakataa kuunda container ya programu. Error response from daemon: conflicting options: port publishing and the container type network mode inamaanisha kuwa ports: block bado ipo kwenye huduma iliyounganishwa. Ihamishie kwenye gluetun.
Compose inakataa faili zima. Huduma haiwezi kuweka network_mode na networks kwa wakati mmoja. Weka networks kwenye gluetun.
Container nyingine haiwezi kutatua (resolve) programu. curl: (6) Could not resolve host: qbittorrent ni tabia sahihi, kwa sababu container iliyounganishwa haikujiunga na mtandao wowote na haikujisajili kwa jina. Tumia gluetun na port husika.
Container ya pili iliyounganishwa haitaki kuanza. Michakato miwili katika namespace moja haiwezi kutumia (bind) port moja, na inayoshindwa itaripoti kuwa anwani tayari inatumika. Badilisha port ya ndani ya programu, au endesha gluetun ya pili.
Programu haina mtandao baada ya kugusa gluetun. Kuanzisha upya au kuunda upya gluetun kunakata muunganisho kwa kila kitu kilichounganishwa nayo. Anzisha upya container hizo.
Kurasa ndogo zinapakia na kubwa zinakwama. Hiyo ni MTU (maximum transmission unit). Tunnel inaongeza mzigo (overhead), na kitu fulani kwenye njia kinakata pakiti kubwa bila kutuma ujumbe wa kosa. Punguza WIREGUARD_MTU, jaribu 1400, kisha 1320.
Gluetun haiwi "healthy". Ukaguzi wa kuanza (startup check) unataja watuhumiwa wa kwanza: WARN [vpn] restarting VPN because it failed to pass the healthcheck: startup check: dialing: dial tcp4: lookup cloudflare.com: i/o timeout. Angalia kama ufunguo (key) umekwisha muda wake, kisha angalia kama orodha ya seva imepitwa na wakati, kisha angalia kama firewall ya host yako inazuia UDP inayotoka nje.
FAQ
Kwa nini ports zilizochapishwa za container yangu ziliacha kufanya kazi nyuma ya Gluetun?
Kwa sababu network_mode: "service:gluetun" huweka container ndani ya network namespace ya gluetun, na namespace moja huwa na anwani moja ya IP na seti moja ya ports zinazosikiliza. App inaendelea kusikiliza, lakini sheria ya kuchapisha (publish rule) lazima iwepo kwenye container inayomiliki namespace hiyo. Hamisha orodha ya ports: kwenye huduma ya gluetun. Ikiwa utaiacha kwenye huduma iliyoambatishwa, Docker haitaiunda hata kidogo: Error response from daemon: conflicting options: port publishing and the container type network mode.
Ninawezaje kufikia container iliyo ndani ya VPN tunnel kutoka kwa container iliyo nje yake?
Tumia jina la huduma ya gluetun na port ambayo app inasikiliza, kwa mfano gluetun:8080. Container iliyoambatishwa haina network yoyote ya Docker, kwa hivyo jina lake haliwezi kutatuliwa (resolve). Hakuna haja ya kuchapisha chochote kwa ajili ya mawasiliano kati ya container na container. Kwa upande mwingine, container iliyo ndani ya namespace hufikia container ya nje kwa kutumia jina lake la huduma, kama vile postgres:5432, kwenye Gluetun v3.41 na matoleo mapya zaidi. Mteja aliye kwenye subnet tofauti, kama vile laptop iliyo kwenye LAN yako, huzuiliwa na firewall ya gluetun hadi utakapoongeza subnet hiyo kwenye FIREWALL_OUTBOUND_SUBNETS.
Je, Gluetun hufanya kazi kama kill switch wakati VPN inapokatika?
Ndiyo, na kwa sababu mbili kwa wakati mmoja. Container iliyoambatishwa haina njia (route) nyingine isipokuwa ile iliyo kwenye namespace iliyoshirikiwa, kwa hivyo tunnel iliyokufa huiacha bila njia ya kutoka kwenye mashine. Firewall ya Gluetun pia huruhusu trafiki ya nje kupitia tunnel pekee na kuelekea kwenye endpoint ya seva ya VPN. Gluetun kisha huanzisha upya VPN kwa ndani, ikirekodi WARN [vpn] restarting VPN because it failed to pass the healthcheck, badala ya kuzima, kwa sababu kila container iliyoambatishwa hupoteza mtandao wake wakati gluetun yenyewe inapoanzishwa upya.
Tailscale na Gluetun kwenye stack moja: ni ipi inayobeba trafiki ya nje?
Gluetun, katika kila usanidi isipokuwa mmoja. Tailscale husafirisha trafiki kati ya vifaa kwenye tailnet yako kwa chaguo-msingi na huiacha trafiki ya umma peke yake. Katika hali ya userspace ya picha ya container (container image), haitengenezi interface yoyote, kwa hivyo haiwezi kuathiri routing. Kwa TS_USERSPACE=false, inasakinisha njia za 100.64.0.0/10 na subnets ulizotangaza pekee. Isipokuwa ni exit node: sudo tailscale set --exit-node=<exit-node-ip> hufanya Tailscale kuwa njia chaguo-msingi, na hapo ndipo inashinda. Chagua bidhaa moja kumiliki njia chaguo-msingi badala ya kuzipanga zote mbili pamoja.