Containere svarer på kontor-LAN-et, og slutter å svare i det øyeblikket bedrifts-VPN-en kobler til. Ingenting i containeren er endret: ingen omstart, ingen oppdatering av image, ingen konfigurasjonsendring. Det som er endret, er vertens rutingtabell, der en rute som tunnelen la til nå dekker adressen Docker delte ut. Før du endrer et subnett eller ber om et VPN-unntak, legg begge adresseplanene side ved side, fordi reparasjonene koster svært ulikt med tid.

Les ruten før du endrer konfigurasjonen

Start med nettverket Docker faktisk bygde. IPAM-blokken er adresseplanen, og subnettet er linjen som betyr noe:

docker network inspect project_default --format '{{json .IPAM.Config}}'
# [{"Subnet":"172.18.0.0/16","Gateway":"172.18.0.1"}]

Compose tildeler et /16 til hvert nye prosjekt som standard, så to tjenester kan ligge innenfor et område på 65,536 adresser. Det er denne bredden som gjør overlapp vanlig: et tilfeldig valgt /16 er stort nok til å sluke et nettsted du når gjennom tunnelen, og ingen merker det før tunnelen kommer opp.

Sammenlign så rutevalget for én containeradresse, én gang med tunnelen nede og én gang med den oppe:

ip route get 172.18.0.7
# 172.18.0.7 dev br-3f2a9c src 172.18.0.1

To svarformer fører til ulike steder. Hvis utskriften navngir tun0, wg0 eller en annen tunellenhet, er et VPN-prefiks minst like spesifikt som bro-ruten, og pakken når aldri frem til containeren. Hvis den fortsatt navngir broen, kan verten nå containeren, og feilen din er filtrering, DNS eller en returvei som svikter bare i én retning.

Hvorfor en /16-kollisjon er lett å treffe

Docker henter bro-nettverk fra de private poolene, og standardpoolen kommer fra 172.16.0.0/12-blokken i /16-biter. Bedriftsnettverk bruker ofte samme private rom, og en fjernaksess-VPN skyver disse prefiksene til hver klient som kobler til. Når begge sider mener de eier 172.18.0.0/16, holder én rutingtabell to motstridende krav.

Prefikslengden avgjør vinneren, ikke rekkefølgen rutene står i. En tunnel som skyver 10.0.0.0/8, slår ikke en bro-rute på 172.18.0.0/16, fordi /8 er mindre spesifikk. En tunnel som skyver 172.18.0.0/16, eller 172.18.5.0/24 inni den, gjør det. Derfor virker én laptop på kontornettet og feiler på hotell-Wi-Fi med samme VPN: klienten mottar ulike prefikser.

Den samme tabellen styrer den andre retningen. En container som trenger en intern vert på 10.8.4.20, sender pakken til bro-gatewayen sin, og verten ruter den deretter inn i tunnelen. Den veien virker vanligvis fordi verten utfører NAT, men den feiler når bedriftssiden bare godtar laptopens VPN-adresse, eller når reversstifiltrering dropper det asymmetriske svaret.

Sammenlign de tre reparasjonene

Det finnes bare tre veier ut, og de skiller seg i hvem som må godkjenne dem og hva som ryker mens du bruker en av dem.

RepairWho owns itWhat it costs
Renumber the container networkYouRecreates the network, restarts services, invalidates literal addresses in configs and scripts
Exclude your range from the tunnelNetwork teamChanges what every laptop sees, needs a change request and a client profile update
Reach the service through a published portYou and the clientOne port only, no direct container-to-container routing across the tunnel

Omnummerering er den eneste reparasjonen du kan fullføre uten en sak, og derfor stopper de fleste skriverier der. Den er billig på et ungt prosjekt og dyr når et migreringsverktøy eller en lagret tilkoblingsstreng peker på en litterær adresse. Tell de referansene før du redigerer YAML, ikke etterpå.

Et unntak fra tunnelen er det reneste svaret når overlappen ligger i et område bedriften din faktisk eier. Det er også det tregeste, og det er ubrukelig for en innleid konsulent som ikke kan endre klientprofilen. En publisert port eller en liten revers-proxy unngår diskusjonen: klienten snakker med en adresse tunnelen allerede ruter riktig, og bare den porten må være tilgjengelig.

Fest et område med vilje

For ett enkelt prosjekt, deklarer subnettet i compose-filen så prosjektet slutter å hente fra den delte poolen:

networks:
  default:
    ipam:
      config:
        - subnet: 10.201.7.0/24

Ta det området fra et register teamet ditt vedlikeholder, ikke fra et eksempel du fant mens du søkte. Sjekk det mot prefiksene VPN-en skyver, hjemmenettverkene folk jobber fra, og de andre containernettverkene på samme vert. Planlegg så gjenopprettelsen, fordi et eksisterende nettverk beholder det gamle subnettet: docker compose down, deretter up -d. docker network rm nekter mens endepunkter er tilkoblet, og enhver ipv4_address-oppføring i filen må ligge innenfor det nye området.

For nettverk Docker oppretter selv, sett en daemon-pool i /etc/docker/daemon.json:

{
  "default-address-pools": [
    { "base": "10.201.0.0/16", "size": 24 },
    { "base": "10.202.0.0/16", "size": 24 }
  ]
}

Poolen gjelder nettverk som opprettes etter at daemonen starter på nytt, og broer som allerede finnes, beholder adressene sine. Det er praktisk og lett å glemme, så behandle et gammelt prosjekt som fortsatt overlappende til noen gjenoppretter nettverket. Dockers nettverksdokumentasjon for motoren beskriver tildelingsreglene hvis du må forsvare poolen i en gjennomgang.

Linux-broen og Docker Desktop feiler ulikt

På en Linux-vert ligger containerne på broer i vertens navnerom. Én tabell avgjør alt, så sammenligningen over er hele historien: les bro-ruten, les tunnelruten, og se hvilken som vinner for en ekte containeradresse.

Docker Desktop plasserer containere bak en VM med sin egen NAT. Verten har ingen rute til containeradressen i det hele tatt; den når tjenesten gjennom en publisert port, vanligvis bundet til 127.0.0.1. En VPN-klient kan derfor bryte tjenesten uten noen subnett-overlapp, enten ved å installere en rute for VM-ens interne område eller ved å blokkere loopback-trafikk mens tunnelen er tilkoblet. Hvis ip route get på verten rapporterer ingen rute for containeradressen, er det forventet og ikke feilen.

Den praktiske konsekvensen er hvor du ser først. På Linux, start med rutingtabellen. På Desktop, start med den publiserte porten og brannmurreglene til VPN-klienten, og sjekk deretter om VM-ens interne subnett kolliderer med noe tunnelen skyver.

Verifiser med tunnelen oppe

Koble til VPN-en to ganger før du kaller det fikset, fordi en profil som skyver ruter ved tilkobling og trekker dem tilbake ved frakobling kan se riktig ut etter første forsøk. Kjør så kontrollene klienten faktisk kjører:

  1. ip route get fra verten, med containerens virkelige adresse.
  2. En forespørsel fra en annen container, for å bevise at tjenesten selv er frisk.
  3. curl -sv http://127.0.0.1:8080/ fra klienten med tunnelen oppe, deretter traceroute -n til containeradressen fra en maskin på LAN-et.
  4. sysctl net.ipv4.conf.all.rp_filter hvis forespørselen når verten men svaret forsvinner.

Til slutt, skriv det valgte området inn i samme register som du brukte til å velge det, med dato og prosjektet som eier det. Den neste overlappen kommer fra et prosjekt ingen dokumenterte, og det eneste forsvaret er at området ble reservert med vilje i stedet for trukket tilfeldig.

Relaterte artikler