Con­tai­ners met el­kaar ver­bin­den: User De­fi­ned Net­works

Con­tai­ners el­kaar la­ten vin­den: User De­fi­ned Net­works

C’t Magazine - - Inhoud - Mir­ko Dö­l­le

Als je je web­ser­ver en da­ta­ba­se elk in een ei­gen Doc­ker par­keert, moet je web­ser­ver wel we­ten hoe hij de da­ta­ba­se kan be­na­de­ren. De­ze con­tai­ners wer­den voor­heen aan el­kaar ge­knoopt, maar die ma­nier van wer­ken is ver­ou­derd en komt te ver­val­len. De nieu­we ma­nier van wer­ken: User De­fi­ned Net­works met een em­bed­ded DNS-ser­ver voor je con­tai­ners, in­clu­sief na­me-re­sol­ving.

Voor el­ke ser­vi­ce een ei­gen con­tai­ner, dat is de kern van het wer­ken met Doc­ker. Als je dit zeer let­ter­lijk neemt, is het bye-bye LAMP-ser­ver met Li­nux, Apa­che, MySQL en PHP en stap je over op mi­ni­maal een web­ser­ver- plus da­ta­base­con­tai­ner. Soms wordt PHP ook nog in een ei­gen con­tai­ner ge­par­keerd. Maar het be­oog­de doel, de ser­vi­ces los van el­kaar draai­en, heeft ook zijn na­de­len: er moe­ten com­mu­ni­ca­tie­ka­na­len wor­den in­ge­steld.

Bij de tra­di­ti­o­ne­le star­re LAMP-ser­ver is de con­fi­gu­ra­tie niet zo van be­lang. De web­ser­ver en MySQL-da­ta­ba­se draai­en op de­zelf­de host en wis­se­len lo­kaal ge­ge­vens uit via de loop­back­in­ter­fa­ce of een so­c­ket. Als ze in Doc­ker-con­tai­ners zijn ge­zet gaat het om van el­kaar ge­schei­den pro­ces­sen met een ei­gen 'werk­ruim­te' en ip-adres die wel met el­kaar in con­tact moe­ten blij­ven. Als voor­beeld heb­ben we een web­ser­ver met PHPMYAd­min als da­ta­ba­se-fron­tend en een los­se MySQL-da­ta­ba­se. Ze zijn al­le­bei als klant-en-kla­re con­tai­ner-ima­ge te vin­den via Doc­ker Hub.

Start de web­ser­ver-con­tai­ner met het com­man­do

doc­ker run --na­me web­ser­ver \ -p 80:80 -d phpmyad­min/phpmyad­min

Nu wordt eerst een­ma­lig de PHPMyAd­mi­nima­ge ge­down­load van Doc­ker Hub. We ge­ven niet aan in welk net­werk de con­tai­ner moet ko­men, dus Doc­ker hangt hem aan de de­fault brid­ge met als net­wer­kran­ge 172.17.0.0/24. Daar­door krijgt de MySQL­da­ta­ba­se een ip-adres uit het sub­net van de standard brid­ge brid­ge. Wel­ke dat is, merk je pas na het op­star­ten via doc­ker net­work in­spect brid­ge, bij­voor­beeld 172.17.0.2.

Ou­de link

Je hebt in de stan­daard brid­ge geen in­vloed op het uit­ge­ven van ip-adres­sen uit de net­wer­kran­ge. Je kunt niet eens hand­ma­tig een ip-adres aan een con­tai­ner toe­wij­zen. Dat wordt een pro­bleem als je de da­ta­ba­se-con­tai­ner op­start:

doc­ker run --na­me db­ser­ver \ -e MYSQL_ROOT_PASSWORD=123456 \ -d mysql:8

Ook de­ze con­tai­ner be­landt zon­der af­wij­ken­de net­werk­con­fi­gu­ra­tie in de standard brid­ge en krijgt een ip-adres uit de ran­ge 172.170.0.0/24. Ook al blij­ven de ip-adres­sen lan­ge­re tijd het­zelf­de (al­leen een her­start van de hosts kan adres­sen hus­se­len), het door Doc­ker aan­ge­we­zen ip-adres van de da­ta­ba­se in PHPMyAd­min op de web­ser­ver zet­ten gaat niet wer­ken. Tot nu toe kon je als op­los­sing de op­tie --link ge­brui­ken:

doc­ker run --na­me web­ser­ver \ --link db­ser­ver:db -p 80:80 \ -d phpmyad­min/phpmyad­min

Op de­ze ma­nier maakt Doc­ker in de web­ser­ver­con­tai­ner een ver­wij­zing voor de host­naam db naar het ip-adres van de Doc­ker-con­tai­ner met de naam dsb­ser-

ver, zo­dat PHPMyAd­min via de host­naam db con­tact kan leg­gen met de MySQL­da­ta­ba­se. Maar daar­voor moe­ten wel al­le (PHP-)toe­pas­sin­gen van de web­ser­ver de na­me-re­sol­ving ge­brui­ken en niet er­gens een in­ge­klopt ip-adres no­dig heb­ben. Het vast­leg­gen van db als (in­ter­ne) host­naam voor de da­ta­base­con­tai­ner is te dan­ken aan het PHPMyAd­min-pro­ject. Dit soort in­for­ma­tie staat meest­al ver­meld in de los­se Doc­ker-ima­ges op Doc­ker Hub.

Maar zo­als we al aan­ga­ven, is de lin­kop­tie al een tijd­je de­pre­ca­ted, of­te­wel ver­ou­derd. Het zou bij een toe­kom­sti­ge re­lea­se zo­maar weg­ge­haald kun­nen wor­den. De User De­fi­ned Net­works zijn de ver­van­ger.

Op maat ge­maakt

Het groot­ste voor­deel van User De­fi­ned Net­works zit hem in het ont­kop­pe­len, ge­heel vol­gens de Doc­ker-men­ta­li­teit. De ver­schil­len­de net­wer­ken zijn van el­kaar ge­schei­den. De con­tai­ners die met het be­wus­te net­werk in ver­bin­ding staan zijn de eni­ge die ver­bin­ding heb­ben. Dat mo­gen ook meer­de­re net­wer­ken zijn, bij­voor­beeld bij een con­tai­ner die da­ta­ba­se­back-ups van con­tai­ners van ver­schil­len­de klan­ten ver­za­melt. De con­tai­ner heeft dan meer­de­re vir­tu­e­le net­werk­ap­pa­ra­ten.

Het op­val­lend­ste ver­schil is dat je voor­dat je een con­tai­ner start, een­ma­lig het net­werk moet aan­ma­ken:

doc­ker net­work cre­a­te web­net

Als je net als in dit voor­beeld al­leen de naam van een nieuw net­werk aan­geeft, maakt Doc­ker au­to­ma­tisch een nieuw klas­se B net­werk­sub­net als brid­ge aan, die je net als de stan­daard brid­ge (brid­ge) kunt ge­brui­ken. Con­tai­ners in dit net­werk heb­ben in­ter­net­toe­gang en zijn zelfs van bui­ten­af te be­na­de­ren, voor zo­ver port­for­wards staan in­ge­steld. En dit User De­fi­ned Net­work web­net heeft ook een zelfle­ren­de DNS-ser­ver voor het re­sol­ven van de na­men van de con­tai­ners. Om te zor­gen dat de da­ta­ba­se­ser­ver in het web­net wordt ge­start, hoef je bij het aan­roe­pen van doc­ker run al­leen maar de pa­ra­me­ter --net­work web­net toe te voe­gen:

doc­ker run --net­work web­net \ -e MYSQL_ROOT_PASSWORD=123456 \ --na­me db­ser­ver -d mysql:8 PHPMyAd­min in de web­ser­ver­con­tai­ner con­fi­gu­reer je via de om­ge­vings­va­ri­a­be­le PMA_HOST. Door die te de­cla­re­ren met -e PMA_HOST= ge­volgd door de naam van de da­ta­base­con­tai­ner, weet hij waar de da­ta­ba­se te vin­den is:

doc­ker run --net­work web­net --na­me \ web­ser­ver -e PMA_HOST=db­ser­ver \ -p 80:80 -d phpmyad­min/phpmyad­min

Als je de ali­as­func­tie van de em­bed­ded DNS-ser­ver ge­bruikt, kun je de ex­tra om­ge­vings­va­ri­a­be­le en de ex­tra pa­ra­me­ter bij het op­star­ten van de web­ser­ver weg­la­ten. Daar­mee be­nut je dat de PHPMyAd­min-con­tai­ner zo in­ge­steld staat dat de da­ta­ba­se stan­daard via de host­naam db wordt aan­ge­roe­pen. Daar­door hoef je bij het lin­ken via --link geen ex­tra pa­ra­me­ter voor de host­naam voor de da­ta­ba­se in te voe­ren. Als je bij de da­ta­base­con­tai­ner een net­werka­li­as db in­stelt, let er dan op dat PHPMyAd­min de da­ta­ba­se dank­zij de stan­daard con­fi­gu­ra­tie ook op ei­gen hout­je kan vin­den in het User De­fi­ned Net­work:

doc­ker run --net­work web­net \ -e MYSQL_ROOT_PASSWORD=123456 \ --na­me db­ser­ver --net­work-ali­as db \ -d mysql:8 Dit soort stan­daard­waar­den vind je ook bij veel an­de­re Doc­ker-ima­ges te­rug. Ali­as­sen ma­ken het mo­ge­lijk om con­tai­ners on­ge­wij­zigd di­rect van­uit Doc­ker Hub te ge­brui­ken, zon­der al­les een mak­ke­lijk her­ken­ba­re naam te hoe­ven ge­ven. De naam van de da­ta­base­con­tai­ner, die bij al­le Doc­ker­com­man­do's een rol speelt, kun je zon­der pro­ble­men de naam van een klant of ser­vi­ce ge­ven. Dank­zij de ali­as is hij al­tijd als db van­uit de web­ser­ver te be­rei­ken.

Via ali­as naar tem­pla­te

Een an­der vaak on­der­schat voor­deel is dat meer­de­re con­tai­ners in het­zelf­de net­werk de­zelf­de ali­as mo­gen krij­gen. Zo­dra er twee of meer con­tai­ners met de­zelf­de ali­as draai­en, kiest de em­bed­ded DNS­ser­ver van het User De­fi­ned Net­work bij query's een random con­tai­ner en geeft diens adres te­rug. Zo is de be­las­ting net als bij een Round-Ro­bin DNS-ser­ver over meer­de­re con­tai­ners te ver­de­len.

Het heeft ech­ter wei­nig zin om de be­las­ting te ver­de­len over meer­de­re iden­tie­ke con­tai­ners op de­zelf­de host. Een ver­za­me­ling con­tai­ners op meer­de­re no­des is daar be­ter voor ge­schikt.

Wel wordt het in­te­res­sant zo­dra er een up­gra­de van de da­ta­base­con­tai­ner ge­pland staat. Als je de bij­ge­werk­te con­tai­ner een nieu­we naam maar de­zelf­de ali­as

toe­wijst, kan die wor­den ge­start en scha­kel je daar­na met­een de ou­de uit. Query's wor­den dan au­to­ma­tisch door de nieu­we con­tai­ner be­ant­woord. Mocht die niet zo lek­ker draai­en, dan slin­ger je de ou­de weer aan die dan naad­loos weer ver­der­gaat. Op die ma­nier voor­kom je down­ti­me.

Be­ter nog: als je je ei­gen web­ser­ve­ri­ma­ge van­af het be­gin zo in­stelt dat hij steeds via de ali­as ver­bin­ding legt met de da­ta­ba­se, heb je een soort van tem­pla­teima­ge die je zon­der iets te hoe­ven wij­zi­gen voor meer­de­re klan­ten of ver­schil­len­de web­si­tes kunt ge­brui­ken. Je moet al­leen nog voor el­ke klant of el­ke web­si­te via doc­ker net­work cre­a­te en doc­ker run een nieuw User De­fi­ned Net­work en nieu­we web­ser­ver- en da­ta­base­con­tai­ner met dui­de­lij­ke naam aan­ma­ken. De con­tai­ners wis­se­len zon­der pro­ble­men da­ta uit dank­zij de ali­as. Dit maakt het be­heer mak­ke­lij­ker. Het maakt na­me­lijk niet uit bij wel­ke klant­con­tai­ner je kijkt, de da­ta­ba­se is al­tijd on­der db te vin­den.

Veel na­men

De User De­fi­ned Net­works kun­nen ook over­weg met een si­tu­a­tie waar­bij het om­ge­keer­de geldt: een con­tai­ner heeft meer­de­re ali­as­sen en ze ver­schil­len van net­werk tot net­werk. Dat is han­dig als je een web­ser­ver met CMS en PHPMyAd­min voor da­ta­ba­se­be­heer aan­biedt en drie con­tai­ners ge­bruikt: een web­ser­ver met CMS, een met PHPMyAd­min en de MySQL-da­ta­base­con­tai­ner.

Ver­wacht het CMS de da­ta­ba­se­ser­ver via de naam sql­ser­ver te kun­nen be­na­de­ren, ter­wijl PHPMyAd­min db ge­bruikt, voeg je de twee­de ali­as sim­pel­weg toe bij het star­ten van de da­ta­base­con­tai­ner:

doc­ker run --net­work web­net \ -e MYSQL_ROOT_PASSWORD=123456 \ --na­me db­ser­ver --net­work-ali­as db \ --net­work-ali­as sql­ser­ver -d mysql:8

Op de­ze ma­nier is de da­ta­base­con­tai­ner via de na­men db­ser­ver, db en sql­ser­ver te be­rei­ken.

Het wordt las­ti­ger, als een da­ta­base­con­tai­ner de ge­ge­vens van meer­de­re an­de­re con­tai­ners uit ver­schil­len­de User De­fi­ned Net­works moet ver­wer­ken, bij­voor­beeld om­dat de web­si­te van je sport­club een da­ta­ba­se ge­bruikt en je voor je ei­gen per­soon­lij­ke web­si­te geen twee­de da­ta­base­con­tai­ner wilt star­ten. In dat ge­val start je eerst de da­ta­base­con­tai­ner met al­leen een ver­bin­ding met het net­werk van je sport­club:

doc­ker run --net­work web­net \ -e MYSQL_ROOT_PASSWORD=123456 \ --na­me db­ser­ver \ --net­work-ali­as sql­ser­ver \ -d mysql:8

Om te zor­gen dat je ei­gen web­ser­ver, die bij­voor­beeld in het net­werk pri­va­tenet draait, de da­ta­base­con­tai­ner kan be­na­de­ren via de naam db, moet je het vol­gen­de com­man­do in­ge­ven na het star­ten van de da­ta­base­con­tai­ner:

doc­ker net­work con­nect --ali­as db \ pri­va­tenet db­ser­ver

Dit heeft ook tot ge­volg dat de da­ta­base­con­tai­ner van de web­ser­ver van je sport­club niet via db maar al­leen via sql­ser­ver is te be­rei­ken. Zo kan het niet per abuis tot een bot­sing tus­sen ali­as­sen ko­men om­dat er twee ver­schil­len­de dien­sten in ver­schil­len­de net­wer­ken het­zelf­de ali­as ge­brui­ken.

Con­tai­ners zijn niet al­leen door ver­schil­len­de User De­fi­ned Net­works van el­kaar te schei­den. Stan­daard staat de zo­ge­naam­de In­ter Con­tai­ner Con­nec­ti­vi­ty bin­nen al­le net­wer­ken in­ge­scha­keld. Dit is via het aan­ma­ken van een nieuw net­werk mak­ke­lijk uit te scha­ke­len:

doc­ker net­work cre­a­te -o \ 'com.doc­ker.net­work.brid­ge.ena­ble_icc—

=fal­se' iso­la­ted Al­le con­tai­ners die in het net­werk iso­la­ted zit­ten, heb­ben een wer­ken­de in­ter­net­ver­bin­ding en krij­gen van­uit Doc­ker ip-adres­sen uit het­zelf­de sub­net, maar on­der­ling com­mu­ni­ce­ren kun­nen ze niet.

De in­ter­net­ver­bin­ding wordt ge­re­geld door de net­werk­dri­ver brid­ge. De­ze wordt ge­bruikt bij het aan­ma­ken van een nieuw User De­fi­ned Net­work, ten­zij je iets an­ders aan­geeft. De ex­tra pa­ra­me­ter --in­ter­nal be­perkt de toe­gang van al­le con­tai­ners tot al­leen het lo­ka­le net­werk. Ze heb­ben zo dus geen in­ter­net­ver­bin­ding meer. De dri­ver null ver­biedt al­le net­werk­toe­gang. De­ze hoef je niet aan te ma­ken, de­ze be­staat al stan­daard on­der de naam no­ne.

Het no­ne-net­werk is voor­al han­dig voor con­tai­ners die al­leen lo­kaal werk ver­rich­ten en voor toe­pas­sin­gen die om vei­lig­heids­re­de­nen geen net­werk­toe­gang mo­gen krij­gen. Een voor­beeld is PHP bij een Nginx-web­ser­ver. PHP wordt via een Unix-so­c­ket aan Nginx ge­knoopt.

Voor het ge­val je de so­c­ket op de host aan­maakt en als vo­lu­me zo­wel de Nginx­con­tai­ner als de PHP-con­tai­ner be­nut, kun­nen de web­ser­ver en PHP zon­der net­werk­toe­gang com­mu­ni­ce­ren. Mocht een aan­val­ler een vei­lig­heids­lek ex­ploi­ten en zo de con­tro­le krij­gen over PHP of de to­ta­le con­tai­ner, dan is er wei­nig aan de hand. Hij kan niet bij an­de­re sys­te­men en de con­tai­ner is ook niet te mis­brui­ken voor DDoS-aan­val­len. Het houdt ook in dat je als ge­brui­ker een aan­tal func­ties mist, bij­voor­beeld toe­gang tot een da­ta­ba­se­ser­ver voor zo­ver de­ze ook niet via een so­c­ket of het be­stands­sys­teem wordt ge­re­geld. (avs)

Dank­zij de In­ter Con­tai­ner Con­nec­ti­vi­ty (ICC) kun­nen con­tai­ners met el­kaar ver­bin­ding ma­ken. Als je het uit­scha­kelt, is el­ke con­tai­ner vol­le­dig ge­ï­so­leerd van de ove­ri­ge con­tai­ners, maar heb­ben ze wel ge­woon in­ter­net­toe­gang.

Newspapers in Dutch

Newspapers from Netherlands

© PressReader. All rights reserved.