Oprettelse af Docker-billeder. Forstå Docker. Hovedkomponenterne i Docker

Docker er det mest almindelige containeriseringssystem, der giver dig mulighed for at køre den nødvendige software til udvikling i containere uden at installere det på det lokale system. Som en del af dette materiale vil vi analysere docker container management.

Docker består af flere komponenter:
  1. Billede- et sæt software konfigureret af udviklerne, som downloades fra den officielle hjemmeside
  2. Beholder- billedimplementering - en enhed på serveren oprettet fra den, containeren behøver ikke at være en nøjagtig kopi og kan justeres ved hjælp af Dockerfilen
  3. Bind- det område på disken, som containeren bruger, og hvor dataene er gemt. Efter sletning af beholderen forbliver softwaren ikke, dataene kan bruges i fremtiden

Et netværk er bygget over hele strukturen på en særlig måde, som giver dig mulighed for at videresende porte på den ønskede måde og gøre containeren tilgængelig udefra (som standard fungerer den på en lokal IP-adresse) gennem en virtuel bro. I dette tilfælde kan containeren være tilgængelig både for verden og til én adresse.

Docker container management: grundlæggende funktioner

Installer Docker på Ubuntu eller Debian-serveren, hvis den ikke allerede er installeret i henhold til instruktionerne. Det er bedre at køre kommandoer som en uprivilegeret bruger via sudo

At køre den enkleste container vil vise, at alt fungerer

Grundlæggende kommandoer til håndtering af containere

Du kan vise alle aktive beholdere på denne måde

Med knappen -a vil alle beholdere blive vist, inklusive inaktive

Dicker tildeler navne til containere tilfældigt, om nødvendigt kan du angive navnet direkte

docker run --navn hello-world

Vi starter en container ved navn my-linux-container baseret på ubuntu-billedet og går til containerkonsollen med angivelse af bash-skallen

docker run -it --name my-linux-container ubuntu bash

For at forlade containeren og vende tilbage til værtssystemet skal du køre

Alle billeder, som containere er baseret på, downloades automatisk fra hub.docker.com, når containeren først oprettes, dem, der allerede findes lokalt, kan ses ved at køre docker-billeder

Oprettelse af en container fra et allerede downloadet billede vil være meget hurtigere (næsten øjeblikkeligt)

Når du forlader containeren med exit, stopper den, så dette ikke sker, kan du afslutte med en tastaturgenvej CTRL+A+P

Du kan fjerne alle beholdere, der ikke er aktive

docker rm $(docker ps -a -f status=exited -q)

Eller slet dem én efter én

I stedet for en identifikator i den sidste kommando, kan du angive et navn

I docker administreres containere med et lille antal intuitive kommandoer:

docker container start ID

docker container stop ID

docker container genstart ID

docker container-id

Sidstnævnte er især nyttigt, det viser alle oplysninger om containeren, konfigurationsfiler og anvendte diskpartitioner. Hele listen over kommandoer kan nemt findes i hjælpen eller på det officielle Docker-websted.

Byg dit eget Docker-billede og brug en Dockerfil

Billeder oprettes normalt ud fra eksisterende ved hjælp af yderligere muligheder, der er angivet i Dockerfilen

FRA ubuntu
CMD ekko "hej verden"

Nu laves et nyt billede baseret på standarden ubuntu

Vi bygger billedet ved at give det et navn (prikken i slutningen af ​​kommandoen betyder, at den aktuelle mappe bruges, og derfor Dockerfilen i den)

docker build -t my-ubuntu .

docker billeder vil nu vise det nyoprettede my-ubuntu billede

Du kan køre det, det vil sende til konsollen Hej Verden og dette er den eneste forskel fra standardbilledet

Normalt er der brug for mere komplekse regler, for eksempel skal vi inkludere python3 i billedet - lad os flytte til en ny mappe og oprette en Dockerfile

FRA ubuntu
CMD apt-get update && apt-get install python3

Alle instruktioner er skrevet på én linje

docker build -t my-ubuntu-with-python3 .

Vi starter beholderen med at gå indenfor

docker run -it my-ubuntu-with-python3 bash

Indeni, som root, skal du udføre dpkg -l | grep python3, vil kommandoen vise, at pakken er til stede i systemet, hvilket betyder succes

Det faktum, at Docker virkelig er et must-have-værktøj for en udvikler og administrator af ethvert stort projekt. Men selvom dette ikke er tilfældet, skal du stadig kende Docker: i den nærmeste fremtid vil det være overalt, fra en desktop Linux-distribution til en pulje af servere på AWS. Og det bedste er, at det er ret nemt at håndtere Docker, hvis du selvfølgelig forstår korrekt, hvordan det fungerer.

Velegnet til en verden af ​​virtuelle miljøer

Docker er baseret på navnerum og cgroups-teknologier (den første giver isolering, den anden - gruppering af processer og begrænsning af ressourcer), så med hensyn til virtualisering er det ikke meget anderledes end LXC / OpenVZ, vi kender, og der er ikke meget at tale om om her. Den samme native hastighed, de samme isolationsmetoder baseret på Linux-kernens mekanismer. Et niveau op er dog en helt anden historie. Det smukke ved Docker er, at det giver dig mulighed for at implementere et komplet virtuelt miljø og køre en applikation i det lige så nemt som at genstarte en webserver.

Lad os abstrahere detaljerne i specifikke distributioner og forestille os, at vi har et rent CentOS, og vi vil køre en bestemt kommando i det i et fuldstændig virtuelt miljø uden adgang til hovedsystemet. Skal du downloade distributionsbilleder, implementere dem til systemet og opsætte et virtuelt miljø? Slet ikke, alt du skal gøre er at køre to kommandoer:

$ sudo yum installer docker-io $ sudo docker run -t ubuntu:nyeste /usr/bin/top

Og det er det hele. Vi har lige kørt det øverste værktøj inde i en container med et miljø baseret på den seneste version af Ubuntu, der er tilgængelig i øjeblikket, med output til den aktuelle terminal. Og alt dette med en simpel kommando (installation tæller ikke). Ikke dårligt, ikke? Generelt kan vi endda "gå ind i" denne container og gøre alt, hvad der normalt gøres med et nyinstalleret system:

$ sudo docker run -t -i ubuntu:nyeste /bin/bash # apt-get update # apt-get install nginx #

Som du kan se, er alt OK med netværket, så vi kan opdatere systemet, installere og konfigurere enhver software. Det ligner lidt magi, men det er faktisk meget enkelt. Docker er en slags apt-get i containerverdenen, kun i stedet for pakker er der filsystembilleder, og i stedet for officielle Debian/Ubuntu-depoter er der et cloudlager kaldet Docker Hub.

Da vi lavede "docker run...", gjorde systemet følgende:

  1. Docker-værktøjet kontaktede dockerd-dæmonen på vores lokale maskine, sagde hej for os og bad os om at køre den seneste version af Ubuntu (dette er angivet med det seneste tag i kommandoen) i en isoleret container.
  2. Dockerd-dæmonen tjekkede sin notesbog, gik til mappen /var/lib/docker og fandt ud af, at der ikke var noget filsystembillede fra den seneste Ubuntu på vores maskine, så den besluttede at henvende sig til Docker Hub for at finde ud af, om et sådant billede var der.
  3. Efter at have talt med Docker Hub, sikrede han sig, at billedet stadig eksisterer, og bad om at sende det til os.
  4. Efter at have opnået det ønskede billede, monterede dockerd sit filsystem, lavede en chroot ind i det og kørte kommandoen specificeret i det sidste argument, hvilket begrænsede dets "omfang" ved at bruge navneområder (faktisk afskærede dens adgang til hovedfilsystemet, værtssystemet processer, IPC og andre , låste den i sandkassen), men overførte enhedsfilerne fra den nuværende terminal til den (-t-flaget), så vores top kunne tegne sin pseudo-grafiske grænseflade.

Højdepunktet ved denne model er, at Docker Hub er åben for alle, og alle kan forberede deres eget billede (mere om det senere) og publicere det til installation på en anden maskine og/eller en anden person. I skrivende stund er mere end 45.000 billeder blevet offentliggjort på Docker Hub til alle lejligheder, lige fra billeder af bare distributioner til billeder med forudkonfigurerede server- og desktopapplikationer, der kører i et minimalistisk Linux-miljø.

Hvad hvis vi vil køre Firefox i et virtuelt miljø? Der er ikke noget nemmere, åbn Docker Hub i browseren, klik på Gennemse og søg og kør i firefox. En liste over resultater vises på skærmen. Vi ser, kennethkl / firefox ser ud til at være ret velegnet. Vi klikker på den og ser info om, hvordan man starter det hele. Forfatteren fortæller os, at vi skal udføre følgende kommando:

$ sudo docker run -d --name firefox -e DISPLAY=$DISPLAY \ -v /tmp/.X11-unix:/tmp/.X11-unix kennethkl/firefox

Vi forsøger. Ja, faktisk, efter en kort download af billedet får vi standard Firefox på skærmen. I det samme eksempel kan du i øvrigt se fire nyttige muligheder for docker run-kommandoen:

  • -d - "dæmoniserer" containeren, det vil sige, afbryder blot Docker fra det virtuelle miljøs STDOUT og tillader det at køre i baggrunden;
  • --name - navnet på beholderen, som den vil modtage i stedet for en identifikator;
  • -e - giver dig mulighed for at "viderestille" en miljøvariabel til den virtuelle maskine;
  • -v videresender den angivne fil eller mappe (format /fil/on/host/system:/file/in/virtuel maskine eller simpelthen /file/on/host/system, hvis stierne matcher).

I dette tilfælde er variablen og filen nødvendige, så Firefox kan få adgang til den lokale maskines skærm. Dette er ret usikkert, da enhver proces i containeren ikke kun vil kunne køre enhver software på dit skrivebord, men også for eksempel opsnappe tastetryk eller markørbevægelser. Men det vil for eksempel gøre.

Der er også en nemmere måde at søge efter Docker-billeder ved hjælp af docker-søgekommandoen:

$ sudo docker søgning nginx

INFO

Enhver Docker-bruger kan køre deres egen private hub. Det kaldes "registret" og fås som et færdigt billede. Alt du skal gøre er bare at køre det: docker run -p 5555:5555 registreringsdatabasen.

Docker-dæmonen er tilgængelig ikke kun fra klienten, men også ved hjælp af RESTful API, både lokalt og fra en fjernmaskine. Standard Docker-porte er tcp/2375 og tcp/2376.

Docker-billedet skal ikke køres umiddelbart efter download, du kan først downloade det til din lokale maskine ved hjælp af docker pull-kommandoen, og først derefter køre: docker pull ubuntu.

Lagkage

Docker giver dig mulighed for at gøre arbejdet med virtuelle miljøer så bekvemt som muligt, hvilket forenkler både processen med at implementere miljøer og konfigurere deres interaktion med værtssystemet (som kun er det sidste eksempel). Men dette er ikke dets eneste højdepunkt.

Hvis du allerede har leget med Ubuntu-billedet fra de første to eksempler, har du sikkert bemærket, at hver ny lancering af beholderen sker fra bunden, og alle ændringer foretaget i den forrige session går tabt. Dette er slet ikke en fejl, dette er en af ​​nøglefunktionerne i Docker-arkitekturen, hvilket gør den endnu mere interessant og attraktiv løsning.

Faktum er, at i langt de fleste tilfælde er "Docker-billedet" slet ikke et monolitisk billede af filsystemet, men en slags lagkage bestående af flere billeder af filsystemer, på grundlag af hvilke beholderen er dannet. Samtidig er individuelle FS-billeder slet ikke ansvarlige for visse dele af mappestrukturen (som f.eks. i tilfælde af partitionering af en disk under Linux i /home, /var, /boot-partitioner), men er lagdelte. oven på hinanden ved hjælp af kerne AUFS-mekanismen Linux (der er også understøttelse af samme funktionalitet gennem brug af btrfs, enhedsmapper og overlay).

For at forstå, hvordan dette virker, lad os gå tilbage til vores containeriserede Ubuntu. Vi starter containeren og installerer nginx, som vist i det andet eksempel i begyndelsen af ​​artiklen, men fuldfører det ikke. I stedet starter vi en anden terminal og ser på listen over kørende containere:

$ sudo docker ps

Denne kommando viser alle kørende containere sammen med deres ID, brugte billede, kommandokørsel, køretid og mere. Vi er interesserede i værdien i kolonnen CONTAINER ID. Kopier det og kør følgende kommando:

$ sudo docker commit ubuntu-nginx container-id

Når den er færdig, kan du forlade beholderen og dermed fuldføre dens arbejde. Og så starter vi bare ubuntu-nginx-beholderen og ser, at nginx ikke er forsvundet nogen steder og er på sin plads:

$ sudo docker run -i -t ubuntu-nginx /bin/bash # som nginx /usr/sbin/nginx

Hvad har vi gjort? Vi oprettede endnu et lag, det vil sige et ekstra FS-billede, og genererede et nyt Docker-billede baseret på det allerede eksisterende Ubuntu Docker-billede, inklusive vores FS-image, som indeholder nginx. Det lyder lidt forvirrende, ikke? Faktisk er alt ret simpelt.

Vi har allerede fundet ud af, at hvert Docker-billede består af flere FS-billeder. Når vi starter containeren, bliver disse billeder monteret og samlet i en enkelt mappestruktur ved hjælp af AUFS. For eksempel kan det første billede kun indeholde en grundlæggende Ubuntu-installation, det andet tilføjer et sæt standarddæmoner til det, det tredje - administrationsværktøjer og så videre. Docker monterer alle lag i skrivebeskyttet tilstand, men for at vi skal kunne ændre indholdet af billedet, er endnu et oprindeligt tomt lag forbundet ovenpå i læse/skrivetilstand.


Som standard, når en container afsluttes (hvilket sker efter den sidste proces, der kører i den, er afsluttet), slettes det sidste lag, og alle vores ændringer går tabt. Men ved at bruge docker commit-kommandoen kan vi "commit" ændringerne ved at skabe et nyt Docker-billede baseret på de eksisterende filsystembilleder plus filsystembilledet med vores ændringer. Dette vil gemme vores ændringer. Eventuelt kan vi starte ubuntu-nginx-beholderen, foretage ændringer i den og gemme den i et nyt Docker-billede ved at bruge commit på samme måde, tilføje endnu et lag. For at se en liste over alle de resulterende (og modtaget fra Docker Hub) billeder kan du bruge kommandoen docker images, og for at se historikken for dannelsen af ​​lag, kommandoen docker history:

$ sudo docker historie ubuntu-nginx

Denne tilgang til billedbehandling giver dig mere fleksibilitet i containerstyring, sparer en masse tid og giver dig mulighed for nemt at overføre allerede konfigurerede Docker-billeder mellem maskiner (billedet kan uploades til Docker Hub og derefter implementeres til en anden maskine). Et mindre indlysende plus er diskpladsbesparelser. Hvis vi installerer en hel zoologisk have af containere på en maskine, som hver især vil være baseret på ét basisbillede (det samme Ubuntu, for eksempel) - vil de alle referere til dette basisbillede og ikke duplikere dets indhold.


Docker uden for Linux

Den eneste måde at køre Docker på OS X eller Windows er at installere det på en virtuel maskine. Det er ikke nødvendigt at gøre dette manuelt, du kan bruge en færdiglavet løsning, såsom boot2docker. Dette er et sæt scripts, der giver dig mulighed for hurtigt at implementere en virtuel maskine med Linux og Docker inde i VirtualBox og køre den med automatisk adgang via SSH. Instruktioner til brug af det og selve installationsprogrammet kan findes på den officielle Docker-websted.

Netværkskonfiguration

For at containere kan kommunikere med hinanden og med omverdenen, rejser Docker automatisk en virtuel netværksbro og konfigurerer masquerading (NAT) regler for den eksterne netværksgrænseflade. Det betyder, at det ikke vil være muligt at nå containerne udefra. Vi kan dog opsætte port forwarding, så en anmodning til bestemte porte på maskinens eksterne netværksinterface automatisk videresendes til de angivne containerporte. For eksempel, hos Mirantis, kører Fuel master noden (dette er GUI'en til implementering og konfiguration af OpenStack) i Docker og bruger portvideresendelse til at afsløre ful/nginx containeren (port 8000):

$ sudo docker run -d -p 8000:8000 fuel/nginx_6.0:latest /usr/local/bin/start.sh

Vi kunne videresende port 8000 til enhver anden containerport ved blot at ændre det andet tal i -p-indstillingen, men dette giver ikke mening i denne konfiguration.

Filvideresendelse og Dockerfile

I begyndelsen af ​​artiklen stiftede vi allerede bekendtskab med flaget -v, som giver dig mulighed for at videresende enhver fil eller mappe fra værtssystemet til containeren. Dette er en meget praktisk funktion, den kan bruges både til at gemme nogle midlertidige data og til at dele filer mellem flere containere. Mirantis bruger denne funktion til at sende Brændstof/Smart service konfigurationsfiler (/etc/astute) inde i containeren:

$ sudo docker run -d -v /etc/astute fuel/astute_6.0:latest /usr/local/bin/start.sh

Det samme kan gøres med kommandoen VOLUME i Dockerfilen. Selve Dockerfilen er den lokale ækvivalent til Makefilen, men mens sidstnævnte er til at bygge applikationer fra kilden, giver Dockerfilen dig mulighed for at bygge Docker-billeder. Dens formål er at forenkle oprettelsen af ​​nye billeder uden at skulle starte en container, udføre nogle operationer i den og udføre en commit. Du kan bare skrive en Dockerfile og Docker vil gøre alt for dig. Overvej f.eks. Dockerfilen til at bygge brændstof/kloge:

FRA brændstof/centos VEDLIGEHOLDER Matthew Mosesohn [e-mailbeskyttet] KØR rm -rf /etc/yum.repos.d/*;\ echo -e "\nnavn=Nailgun Local Repo\nbaseurl=http://$(rute -n | awk "/^0.0.0.0/ ( print $2 )"):_PORT_/os/x86_64/\ngpgcheck=0" > /etc/yum.repos.d/nailgun.repo;\ yum clean all;\ yum --quiet install -y ruby21-nailgun-mcagents sysstat ADD osv. /etc ADD start.sh /usr/local/bin/start.sh RUN puppet apply --detailed-exitcodes -d -v /etc/puppet/modules/nailgun/examples/astute-only.pp; [[$? == 0 || $? == 2 ]] KØR chmod +x /usr/local/bin/start.sh;\ echo -e "\nname=Nailgun Local Repo\nbaseurl=file:/var/www/nailgun/centos/x86_64\ngpgcheck=0 " > /etc/yum.repos.d/nailgun.repo; yum ren alt VOLUME /etc/astute CMD /usr/local/bin/start.sh

Det er ikke svært at forstå, hvad det er beregnet til. Det opretter et billede baseret på brændstof/centos, kører et par kommandoer for at forberede billedet, tilføjer filer fra den aktuelle mappe til billedet, anvender Puppet-manifestet, ændrer tilladelser på nogle filer, skubber /etc/asture/-mappen fra værtssystem ind i containeren og kører container ved hjælp af /usr/local/bin/start.sh kommandoen.

For at bygge en container skal du bare lægge Dockerfilen og alle de filer, der vil blive tilføjet til den, i en eller anden mappe og køre følgende kommando:

$ sudo docker build fuel/astute_6.0:nyeste

I dette tilfælde valgte vi navnet fuel/astute_6.0:latest, selvom det kan være hvad som helst.

Nuancerne ved at arbejde med Docker

Docker er bygget op omkring ideen om, at kun én service skal køre i hver container. Du pakker Apache, MySQL, nginx, Varnish og hvad dit projekt måtte have brug for i forskellige containere, og bruger derefter Docker til at bygge det hele sammen. Denne tilgang giver stor fleksibilitet, da den giver dig mulighed for nemt at ændre konfigurationen, teste opdateringer og migrere individuelle tjenester til andre maskiner.

Af samme grund bruges Docker ikke almindeligvis til at køre fuldgyldige Linux-miljøer med init-dæmonen, cron- og syslog-dæmonerne og andre. I stedet starter vi simpelthen den service, vi har brug for, og den kører i et virtuelt miljø helt alene:

$ sudo docker run -d -p 80 ubuntu-nginx /usr/sbin/nginx

Men der er et lille problem her. Docker afslutter containeren umiddelbart efter processen, der kører i den (i dette tilfælde nginx) er afsluttet, og da nginx er dæmoniseret som standard, det vil sige, at den forgrener en ny proces og afslutter den, vi lancerede manuelt, afslutter Docker øjeblikkeligt og en container, der sømmer den gaflede Docker.

I tilfælde af nginx kan du omgå dette problem ved at tilføje daemon off; den første linje i hans konfiguration. Andre dæmoner vil kræve deres egne indstillinger, og nogle kan forhindres i at blive dæmoniseret direkte fra kommandolinjen. For eksempel giver sshd flaget -D til dette:

$ sudo docker run -d -p 22 ubuntu-ssh /usr/sbin/sshd -D

Du kan til enhver tid oprette forbindelse til containeren ved hjælp af docker exec-kommandoen for at se logfilerne eller ændre indstillingerne (herefter er container-id'et enten det ID, der kan ses i outputtet af docker ps, eller det angivne navn ved opstart i --name-indstillingen):

$ sudo docker exec -ti container ID /bin/bash

Men her er der en lille hage. Som vi ved, vil al den information, der er akkumuleret under driften af ​​det virtuelle miljø, gå tabt, hvis vi lukker det virtuelle miljø, og med det forsvinder logfilerne og ændringerne i indstillingerne. Vi kan heller ikke oprette lag i det uendelige (om ikke andet fordi der ikke kan være mere end 127 af dem), men vi kan gå en lidt anden vej og bruge logaggregeringssystemet indbygget i Docker. Selvfølgelig ved Docker ikke, hvordan man indsamler logfiler for individuelle applikationer, men den kan akkumulere STDOUT-output, det vil sige enhver konsoludgang. Alt, der er tilbage for os, er at ændre nginx-konfigurationen, så logfilerne hældes ind i /dev/stdout, og derefter se dem ved hjælp af docker-logs-kommandoen:

$ sudo docker logger container-id

En anden og mere korrekt mulighed er blot at overføre logfilerne (og om nødvendigt indstillingerne) til værtssystemet ved at bruge -v-indstillingen, som allerede er beskrevet:

$ sudo mkdir /root/logs $ sudo docker run -d -v /root/logs:/var/logs -p 80 ubuntu-nginx /usr/sbin/nginx

Hvis det er nødvendigt, kan containeren standses elegant ved at afslutte den service, der kører i den ved hjælp af docker stop-kommandoen:

$ sudo docker stop container ID

Og hvis det af en eller anden grund ikke virker korrekt, så kan du dræbe det med kill:

$ sudo docker kill container ID

Derved sker der en vigtig ting, som mange begyndere glemmer: Docker gemmer metainformation om containeren. Faktisk betyder det, at hvis du starter for eksempel nginx, angiver dets navn, mapper, der skal videresendes til containeren, porte, miljøvariabler og lignende ved at bruge argumenterne fra docker run-kommandoen, så er alle disse oplysninger gemmes, når containeren afsluttes, og for at køre den næste gang, behøver du ikke længere at angive den, men blot køre følgende kommando (du kan bruge navnet i stedet for ID):

$ sudo docker start container ID

Hvis det ikke er nødvendigt at gemme tilstanden (f.eks. for at teste eller kontrollere nogle funktioner), så kan du bruge flaget --rm, som vil tvinge Docker til at ødelægge containeren fuldstændigt, efter den er afsluttet (mens billedet gemmes):

$ sudo docker run --rm -i -t busybox /bin/bash

Du kan ødelægge alle tidligere gemte containere ved at bruge følgende kommando:

# docker rm $(docker ps -a -q)

Docker er i stand til selvstændigt at genstarte containere, hvis de går ned og endda køre dem under systemstart. Alt du skal gøre er bare at bruge --restart muligheden:

$ sudo docker run --restart=altid \ -d -v /root/logs:/var/logs -p 80 \ ubuntu-nginx /usr/sbin/nginx

Billedet kan til enhver tid eksporteres til en enkelt fil og derefter importeres på en anden maskine. Docker-gem og docker-gendannelseskommandoer er tilvejebragt til dette. Brugen af ​​dem er meget enkel, eksporten udføres sådan:

$ sudo docker save -o ubuntu-nginx.img ubuntu-nginx

Og importer sådan her:

$ sudo docker load -i ubuntu-nginx.img

konklusioner

Docker er et fremragende værktøj. For en uindviet kan det virke som et legetøj, der ikke længere egner sig til andet end at køre software i en sandkasse, men med dens hjælp kan du løse en lang række opgaver, som vi vil tale om i næste artikel.

Fordele ved Docker frem for LXC, OpenVZ og andre virtualiseringsløsninger på OS-niveau

  1. Docker bruger et bærbart generisk billedformat. Det betyder, at disse billeder uden problemer kan overføres til en anden maskine og deles til brug for andre brugere.
  2. Et billede kan tjene som base for andre billeder. I Docker anses det for normalt at bruge flere lag til at danne det endelige billede. Du kan starte med et grundlæggende Ubuntu-billede og derefter tilføje Apache 2.4 for at oprette en Ubuntu + Apache-mikrotjeneste.
  3. Ved committing kan billedet versioneres, ligesom det gøres i GIT.
  4. Docker har et stort fællesskab og et omfattende økosystem, som inkluderer et seriøst antal værktøjer til skalering, gruppering, overvågning, implementering og styring af containere.

Vi har berørt emnet mere end én gang og overvejet mange systemer til at bygge dem. I dag vil vi introducere endnu et vidunderligt Docker-containersystem.

Lad os starte med at beskrive den grundlæggende funktionalitet, der vil komme til nytte i fremtidige artikler i serien, og kort huske Docker-arkitekturen. Docker bruger en klient-server-arkitektur og består af en klient - docker-værktøjet, der tilgår serveren vha. RESTful API, og en dæmon i Linux-operativsystemet (se figur 1). Selvom Docker fungerer på ikke-Linux-operativsystemer, er de ikke dækket af denne artikel.

De vigtigste komponenter i Docker:
    • Containere– brugermiljøer isoleret af operativsystemteknologier, hvor applikationer kører. Den nemmeste måde at definere en Docker-container på er som et program, der kører fra et billede. Det er i øvrigt præcis, hvad der ideologisk adskiller Docker, for eksempel fra LXC ( Linux containere), selvom de bruger de samme Linux-kerneteknologier. Udviklerne af Docker-projektet bekender sig til princippet: én container er én applikation.
    • billeder– skrivebeskyttede ansøgningsskabeloner. Nye niveauer kan tilføjes oven på eksisterende billeder, der tilsammen repræsenterer filsystemet, ændre eller tilføje til det tidligere niveau. Normalt oprettes et nyt billede enten ved at gemme en allerede kørende container til et nyt billede oven på et eksisterende, eller ved at bruge specielle instruktioner til . For at adskille de forskellige containerniveauer på filsystemniveau kan bruges AUFS, btrfs, vfs og Device Mapper. Hvis du har til hensigt at bruge Docker med SELinux, så er det påkrævet enhedsmapper.
    • Registre, der indeholder depoter ( depot) billeder, er netværkslagre af billeder. De kan være både private og offentlige. Det mest berømte register er .

GNU/Linux-operativsystemer bruger standard Linux-kerneteknologier til at isolere containere, såsom:
  • navnerum ( Linux navnerum).
  • Kontrolgrupper ( Grupper).
  • Privilegium kontrol ( Linux-funktioner).
  • Yderligere, påbudte sikkerhedssystemer som f.eks AppArmor eller SELinux.

Lad os se nærmere på disse teknologier.

Kontrolgruppemekanisme (c-grupper) giver et værktøj til finmasket kontrol over allokering, prioritering og styring af systemressourcer. Kontrolgrupper er implementeret i Linux-kernen. I moderne distributioner implementeres kontrolgruppestyring igennem systemd, men muligheden for at kontrollere ved hjælp af biblioteket forbliver libcgruppe og forsyningsselskaber cgconfig. De vigtigste kontrolgruppehierarkier (også kaldet controllere) er anført nedenfor:

  • blkio– sætter grænser for I/O-operationer og adgang til at blokere enheder;
  • cpu- ved at bruge procesplanlæggeren, fordeler processortid mellem opgaver;
  • cpuacct– opretter automatiske rapporter om brugen af ​​CPU-ressourcer. Arbejder med controller cpu beskrevet ovenfor;
  • cpuset tildeler visse processorer og hukommelsesknuder til opgaver;
  • enheder– regulerer adgangen til opgaver til visse enheder;
  • fryser– pauser eller genoptager opgaver;
  • hukommelse– sætter grænser og genererer rapporter om hukommelsesbrug af cgroup-opgaver;
  • net_cls– udfører tagging af netværkspakker med en klasse-id ( klassid). Dette gør det muligt for trafiklederen ( tc kommando) og firewall ( iptables) overveje disse tags, når du behandler trafik;
  • perf_event– giver dig mulighed for at overvåge kontrolgrupper ved hjælp af hjælpeprogrammet perf;
  • hugetlb- giver dig mulighed for at bruge store virtuelle hukommelsessider og anvende begrænsninger på dem.

navnerum, til gengæld kontrollerer de ikke allokeringen af ​​ressourcer, men adgangen til kernedatastrukturer. Det betyder faktisk at isolere processer fra hinanden og mulighed for parallelt at have "det samme", men ikke krydsende med hinanden, hierarkier af processer, brugere og netværksgrænseflader. Hvis det ønskes, kan forskellige tjenester endda have deres egne loopback-grænseflader.

Eksempler på navnerum brugt af Docker:
  • PID, proces-id– isolering af proceshierarki.
  • NET, netværk– isolering af netværksgrænseflader.
  • PC, InterProcess Communication– styring af samspillet mellem processer.
  • MNT, Mount– styring af monteringspunkter.
  • UTS, Unix tidsdelingssystem– isolering af kerne- og versionsidentifikatorer.

Mekanismen kaldes Evner giver dig mulighed for at opdele root-brugerens privilegier i små grupper af privilegier og tildele dem individuelt. Denne funktionalitet er dukket op i GNU/Linux siden version kerne 2.2. I første omgang lanceres containere med et begrænset sæt privilegier.

Med docker-kommandoindstillingerne kan du aktivere og deaktivere:
  • monteringsoperationer;
  • socket adgang;
  • udføre en del af handlingerne på filsystemet, såsom at ændre attributterne for filer eller ejeren.

Du kan lære mere om privilegier ved at bruge man-siden. FUNKTIONER(7).

Installation af Docker

Overvej at installere Docker ved at bruge CentOS som eksempel. Når du arbejder med CentOS, har du et valg: brug den seneste version fra u pstream eller en version bygget af CentOS-projektet med Red Hat-tilføjelser. En beskrivelse af ændringerne findes på siden.

Disse er hovedsageligt backports af rettelser fra nye upstream-versioner og ændringer foreslået af Red Hat-udviklerne, men endnu ikke accepteret i hovedkoden. Den mest bemærkelsesværdige forskel i skrivende stund var, at i nyere versioner er docker-tjenesten blevet opdelt i tre dele: dæmonen docker, containerd og runc. Red Hat anser endnu ikke denne ændring for at være stabil og sender en version 1.10 monolitisk eksekverbar.

Lagringsindstillinger til installation upstream-versioner, samt instruktioner til installation i andre distributioner og operativsystemer, er givet i installationsvejledningen på den officielle hjemmeside. Specifikt er indstillingerne for CentOS 7-depotet:

# kat /etc/yum.repos.d/docker.repo name=Docker Repository baseurl=https://yum.dockerproject.org/repo/main/centos/7 enabled=1 gpgcheck=1 gpgkey=https://yum .dockerproject.org/gpg

# kat /etc/yum.repos.d/docker.repo

navn = Depot

baseurl=https://yum.dockerproject.org/repo/main/centos/7

aktiveret=1

gpgcheck=1 gpgkey=https://yum.dockerproject.org/gpg

Installer de nødvendige pakker på og start og aktiver tjenesten:

# yum install -y docker-engine # systemctl start docker.service # systemctl aktiver docker.service

# yum installer -y docker-motor

# systemctl start docker.service

# systemctl aktiver docker.service

Kontrol af servicestatus:

# systemctl status docker.service

# systemctl status docker.service

Du kan også se systemoplysninger om Docker og miljøet:

# dockerinfo

Hvis du kører den samme kommando på en Docker-installation fra CentOS-lagrene, vil du se mindre forskelle på grund af den ældre version af softwaren. Fra udgangen docker info vi kan finde ud af, hvad der bruges som driver til datalagring enhedsmapper, og som lager - en fil i /var/lib/docker/:

# ls -lh /var/lib/docker/devicemapper/devicemapper/data -rw-------. 1 rodrod 100G 27. december 12:00 /var/lib/docker/devicemapper/devicemapper/data

# ls -lh /var/lib/docker/devicemapper/devicemapper/data

Rw -- -- -- - . 1 rodrod 100G 27. december 12:00 /var/lib//devicemapper/devicemapper/data

Daemon-opstartsmuligheder, som det er almindeligt med CentOS, er gemt i /etc/sysconfig/. I dette tilfælde er filnavnet docker. Tilsvarende linje /etc/sysconfig/docker, der beskriver mulighederne:

OPTIONS="--selinux-enabled --log-driver=journald"

Hvis du skulle køre docker-kommandoen som en ikke-rootbruger og ikke en bruger i docker-gruppen, ville du se en fejl som denne:

$ docker søg mysql

$search mysql

Advarsel: Det lykkedes ikke at hente standardregistrets slutpunkt fra dæmonen (Kan ikke oprette forbindelse til Docker-dæmonen. Kører docker-dæmonen på denne vært?). Brug af systemstandard: https://index. docker.io/v1/

Kan ikke oprette forbindelse til Docker-dæmonen. Kører docker-dæmonen på denne vært?

Bemærk, at faktisk inkludere en bruger i docker-gruppen er det samme som at inkludere denne bruger i rodgruppen.

RHEL/CentOS-udviklerne har en lidt anden tilgang til at sikre Docker-dæmonen end opstrøms Docker-udviklerne selv. Læs mere om Red Hats tilgang i en artikel af RHEL distributionsudvikler Dan Walsh.

Hvis du vil have Dockers "standard"-adfærd installeret fra CentOS-lagrene (dvs. beskrevet i den officielle dokumentation), så skal du oprette en docker-gruppe og tilføje dæmonens opstartsmuligheder:

OPTIONS="--selinux-enabled --log-driver=journald ↵ --group=docker"

MULIGHEDER= "--selinux-aktiveret --log-driver=journalført ↵ --group=docker"

Derefter genstarter vi tjenesten og kontrollerer, at docker-socket-filen tilhører docker-gruppen og ikke root:

# ls -l /var/run/docker.sock

Docker billedsøgning og tags

Lad os prøve at finde en container på Docker Hub.

$ docker søge haproxy

$ søg haproxy


I dette output fik vi en liste over en række HA Proxy-billeder. Det øverste punkt på listen er HA Proxy fra det officielle lager. Sådanne billeder adskiller sig ved, at der ikke er noget symbol i navnet «/» A, der adskiller navnet på brugerens lager fra navnet på selve containeren. Eksemplet bag det officielle viser to haproxybilleder fra offentlige brugerlagre eeacms og million12.

Du kan oprette billeder som de to nedenfor ved at registrere dig på Docker Hub. De officielle vedligeholdes af et dedikeret hold sponsoreret af Docker, Inc. Funktioner i det officielle lager:

  • Disse er anbefalede billeder til brug, skabt i overensstemmelse med de bedste anbefalinger og praksis.
  • De er grundlæggende billeder, der kan være et udgangspunkt for mere finjustering. For eksempel basisbilleder af Ubuntu, CentOS eller biblioteker og udviklingsmiljøer.
  • Indeholder de seneste versioner af software med rettet sårbarheder.
  • Dette er den officielle produktdistributionskanal. For kun at søge i officielle billeder, kan du bruge muligheden --filter "er-officiel=sand" hold docker-søgning.

Antal stjerner i kommandoudgang docker-søgning svarer til billedets popularitet. Dette ligner en knap. Synes godt om på sociale netværk eller bogmærker for andre brugere. automatiseret betyder, at billedet bygges automatisk ud fra et særligt script ved hjælp af Docker Hub. Generelt bør autobyggede billeder foretrækkes på grund af det faktum, at deres indhold kan verificeres ved at se på de tilsvarende .

Download det officielle HA Proxy-billede:

$ docker pull haproxy Brug af standard tag: nyeste

Det fulde billednavn kan se sådan ud:

[brugernavn]billedenavn[:tag]

Du kan se listen over downloadede billeder med kommandoen docker billeder:

Kørende containere

Du behøver ikke at downloade billedet for at køre containeren. Hvis den er tilgængelig, indlæses den automatisk. Lad os prøve at køre en container med Ubuntu. Vi angiver ikke et lager, og det seneste officielle billede, der understøttes af Canonical, vil blive downloadet.

$ docker run -it ubuntu [e-mailbeskyttet]:/#

$ run - det er ubuntu

root@d7402d1f7c54 :/#

Ud over holdet løb, vi specificerede to muligheder: -jeg- containeren skal starte i interaktiv tilstand og -t– der skal vælges en pseudoterminal. Som du kan se fra outputtet, har vi root-brugerrettigheder i containeren, og container-id'et vises som værtsnavnet. Sidstnævnte er muligvis ikke sandt for alle containere og afhænger af containerudvikleren. Lad os kontrollere, at dette faktisk er et Ubuntu-miljø:

[e-mailbeskyttet]:/# kat /etc/*release | grep DISTRIB_DESCRIPTION DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"

root@d7402d1f7c54 :/ # kat /etc/*release | grep DISTRIB_DESCRIPTION

DISTRIB_DESCRIPTION = "Ubuntu 16.04.1 LTS"

uname kommando -en den kan ikke bruges til sådanne formål, da containeren arbejder med værtskernen.

En mulighed ville være at angive et unikt containernavn, der kan henvises til for nemheds skyld ud over container-id. Det er givet som -navn<имя>. Hvis indstillingen udelades, genereres navnet automatisk.

Automatisk genererede containernavne bærer ikke en semantisk belastning, men som et interessant faktum kan det bemærkes, at navnene er tilfældigt genereret fra et adjektiv og navnet på en berømt videnskabsmand, opfinder eller hacker. I generatorkoden for hvert navn kan du finde en kort beskrivelse af, hvad denne person er kendt for.

Du kan se listen over kørende containere med kommandoen . For at gøre dette skal du åbne en anden terminal:

Men hvis vi udsteder kommandoen, vil vi ikke finde den container, der er oprettet fra mysql-billedet. Lad os bruge muligheden -en, som viser alle containere, ikke kun kørende dem:

Det er klart, at de påkrævede parametre ikke blev specificeret ved start af containeren. For en beskrivelse af de miljøvariabler, der kræves for at køre containeren, kan du finde det officielle MySQL-billede på Docker Hub. Lad os prøve igen ved at bruge indstillingen -e, som indstiller miljøvariablerne i containeren:

$ docker run --name mysql-test ↵ -e MYSQL_ROOT_PASSWORD=docker -d mysql

Den sidste parameter er den kommando, vi ønsker at udføre inde i containeren. I dette tilfælde er det kommandofortolkeren. bash. Muligheder -det lignende formål som dem, der blev brugt tidligere i teamet docker-løb.

Faktisk efter at have kørt denne kommando i containeren mysql test endnu en proces er tilføjet - bash. Dette kan ses visuelt med kommandoen pstree. Forkortet output til kommando docker exec: