Docker 101: Grundlæggende og praksis

Hvis du er træt af at høre dine kolleger rose Docker og fordelene ved enhver chance, de får, eller hvis du er træt af at nikke på hovedet og gå væk hver gang du befinder dig i en af ​​disse samtaler, er du kommet til højre placere.

Også, hvis du leder efter en ny undskyldning for at vandre uden at blive fyret, skal du fortsætte med at læse, og du vil takke mig senere.

Docker

Her er Dockers definition ifølge Wikipedia:

Docker er et computerprogram, der udfører virtualisering på operativsystemniveau.

Ret simpelt, ikke? Nå, ikke ligefrem. Okay, her er min definition af, hvad docker er:

Docker er en platform til oprettelse og kørsel af containere fra billeder .

Stadig tabt? Ingen bekymringer, det er fordi du sandsynligvis ikke ved, hvad containere eller billeder er.

Billeder er enkeltfiler, der indeholder alle de afhængigheder og konfigurationer, der kræves for at køre et program, mens containere er forekomsterne af disse billeder. Lad os gå videre og se et eksempel på det i praksis for at gøre tingene klarere.

Vigtig note: Før du fortsætter, skal du sørge for at installere docker ved hjælp af de anbefalede trin til dit operativsystem.

Del 1. "Hej verden!" fra et Python-billede

Lad os sige, at du ikke har Python installeret på din maskine - eller i det mindste ikke den nyeste version - og at du har brug for python for at udskrive "Hej, Verden!" i din terminal. Hvad laver du? Du bruger docker!

Fortsæt og kør følgende kommando:

docker run --rm -it python:3 python

Bare rolig, jeg forklarer den kommando om et øjeblik, men lige nu ser du sandsynligvis noget som dette:

Det betyder, at vi i øjeblikket er inde i en dockercontainer oprettet fra et python 3- dockerbillede, der kører pythonkommandoen. Afslut eksemplet ved at skrive print("Hello, World!")og se, når magien sker.

Okay, du gjorde det, men før du begynder at klappe dig selv på ryggen, lad os tage et skridt tilbage og forstå, hvordan det fungerede.

At nedbryde det

Lad os starte fra starten. Den docker runkommando er havnearbeider standard værktøj til at hjælpe dig starte og køre dine containere.

Den --rmflaget er der for at fortælle Docker Daemon at rydde op i beholderen, og fjern filsystemet efter at beholderen udgange. Dette hjælper dig med at spare diskplads efter at have kørt kortvarige containere som denne, at vi kun begyndte at udskrive "Hej, Verden!".

Den -t (or --tty)flag fortæller Docker at tildele en virtuel terminal session i beholderen. Dette bruges ofte med -i (or --interactive)indstillingen, som holder STDIN åben, selvom den kører i løsrevet tilstand (mere om det senere).

Bemærk: Du skal ikke bekymre dig for meget om disse definitioner lige nu. Bare ved at du vil bruge -itflaget når som helst du vil skrive nogle kommandoer på din container.

Endelig python:3er det basisbillede, vi brugte til denne container. Lige nu kommer dette billede med python version 3.7.3 installeret blandt andet. Nu spekulerer du måske på, hvor kom dette billede fra, og hvad der er inde i det. Du kan finde svarene på begge disse spørgsmål lige her sammen med alle de andre pythonbilleder, vi kunne have brugt til dette eksempel.

Sidst men ikke mindst pythonvar kommandoen, vi bad Docker om at udføre inde i vores python:3billede, som startede en pythonskal og tillod vores print("Hello, World!")opkald at arbejde.

En ting mere

For at afslutte python og afslutte vores container kan du bruge CTRL / CMD + D eller exit(). Fortsæt og gør det lige nu. Derefter skal du prøve at udføre vores docker runkommando igen, og du vil se noget lidt anderledes og meget hurtigere.

Det skyldes, at vi allerede har downloadet python:3billedet, så vores container starter meget hurtigere nu.

Del 2. Automatiseret "Hello World!" fra et Python-billede

Hvad er bedre end at skrive "Hej verden!" i din terminal en gang? Du har det, skriver det to gange!

Da vi ikke kan vente med at se "Hej verden!" udskrevet i vores terminal igen, og vi ønsker ikke at gå igennem stresset med at åbne python og skrive printigen, lad os gå videre og automatisere den proces lidt. Start med at oprette en hello.pyfil hvor som helst du vil.

# hello.py
print("Hello, World!")

Gå derefter videre og kør følgende kommando fra den samme mappe.

docker run --rm -it -v $(pwd):/src python:3 python /src/hello.py

Dette er det resultat, vi leder efter:

Bemærk: Jeg brugte lsfør kommandoen til at vise dig, at jeg var i den samme mappe, som jeg oprettede hello.pyfilen i.

Som vi gjorde tidligere, lad os tage et skridt tilbage og forstå, hvordan det fungerede.

At nedbryde det

Vi kører stort set den samme kommando, som vi kørte i sidste afsnit, bortset fra to ting.

Den -v $(pwd):/srcindstilling fortæller Docker Daemon at starte en volumen i n vores container . Volumener er den bedste måde at fastholde data i Docker på. I dette eksempel fortæller vi Docker, at vi ønsker, at den aktuelle mappe - hentet fra $(pwd)- skal føjes til vores container i mappen /src.

Bemærk: Du kan bruge ethvert andet navn eller mappe, du ønsker, ikke kun /src

Hvis du vil kontrollere, at der /src/hello.pyfaktisk findes i vores container, kan du ændre slutningen af ​​vores kommando fra python hello.pytil bash. Dette åbner en interaktiv skal inde i vores container, og du kan bruge den ligesom du forventer.

Bemærk: Vi kan kun bruge bashher, fordi det kommer forudinstalleret i python:3billedet. Nogle billeder er så enkle, at de ikke engang har det bash. Det betyder ikke, at du ikke kan bruge det, men du bliver nødt til at installere det selv, hvis du vil have det.

Den sidste del af vores kommando er python /src/hello.pyinstruktionen. Ved at køre det fortæller vi vores container at se inde i dens /srcmappe og udføre hello.pyfilen ved hjælp af python.

Måske kan du allerede se de vidundere, du kan gøre med denne kraft, men jeg vil alligevel fremhæve det for dig. Ved hjælp af det, vi lige har lært, kan vi stort set køre en hvilken som helst kode fra ethvert sprog inde i enhver computer uden at skulle installere nogen afhængigheder på værtsmaskinen - bortset fra Docker, selvfølgelig.Det er meget fed tekst til en sætning, så sørg for at læse det to gange!

Del 3. Nemmeste "Hej verden!" muligt fra et Python-billede ved hjælp af Dockerfile

Er du træt af at sige hej til vores smukke planet endnu? Det er en skam, for vi skal gøre det igen!

Den sidste kommando, vi lærte, var en smule detaljeret, og jeg kan allerede se, at jeg bliver træt af at skrive al den kode hver gang jeg vil sige "Hej verden!" Lad os automatisere tingene lidt længere nu. Opret en fil med navnet, Dockerfileog tilføj følgende indhold til den:

# Dockerfile
FROM python:3
WORKDIR /src/app
COPY . .
CMD [ "python", "./hello.py" ]

Kør nu denne kommando i den samme mappe, som du oprettede Dockerfile:

docker build -t hello .

Alt, hvad der er tilbage at gøre nu, er at blive skør ved at bruge denne kode:

docker run hello

Du ved allerede, hvordan det er. Lad os tage et øjeblik at forstå, hvordan en Dockerfile fungerer nu.

At nedbryde det

Startende med vores Dockerfile, FROM python:3fortæller den første linje Docker at starte alt med det basisbillede, vi allerede er bekendt med python:3.

Den anden linje, WORKDIR /src/appindstiller arbejdsmappen inde i vores container. Dette er for nogle instruktioner, som vi udfører senere, som CMDeller COPY. Du kan se resten af ​​de understøttede instruktioner til WORKDIRlige her.

Den tredje linje COPY . .fortæller grundlæggende Docker at kopiere alt fra vores nuværende mappe (første .) og indsætte det på /src/app(andet .). Indsætningsplaceringen blev indstillet med WORKDIRkommandoen lige over den.

Bemærk: Vi kunne opnå de samme resultater ved at fjerne WORKDIRinstruktionen og erstatte COPY . .instruktionen med COPY . /src/app. I så fald skal vi også ændre den sidste instruktion CMD ["python", "./hello.py"]til CMD ["python", "/src/app/hello.py"].

Endelig CMD ["python", "./hello.py"]leverer den sidste linje standardkommandoen til vores container. Det siger i grunden, at hver gang vi har runen container fra denne konfiguration, skal den køre python ./hello.py. Husk, at vi kører implicit i /src/app/hello.pystedet for kun hello.py, da det var det, hvor vi pegede WORKDIRpå.

Bemærk: Den CMDkommando kan overskrives ved runtime. For eksempel, hvis du vil køre i bashstedet, ville du gøre det docker run hello bashefter at have bygget containeren.

Når vores Dockerfile er færdig, starter vi buildprocessen. Den docker build -t hello .kommando læser al den konfiguration vi føjet til vores Dockerfile og skaber en havnearbejder billede fra det. Det er rigtigt, ligesom det python:3billede, vi har brugt til hele denne artikel. I .slutningen fortæller Docker, at vi vil køre en Dockerfil på vores nuværende placering, og -t helloindstillingen giver dette billede navnet hello, så vi nemt kan henvise til det ved kørsel.

Efter alt dette er alt, hvad vi skal gøre, at køre den sædvanlige docker runinstruktion, men denne gang med hellobillednavnet i slutningen af ​​linjen. Det vil starte en container fra det billede, vi for nylig har bygget, og endelig udskrive den gode ol '"Hej verden!" i vores terminal.

Udvide vores basisbillede

Hvad gør vi, hvis vi har brug for en vis afhængighed for at køre vores kode, der ikke kommer forudinstalleret med vores basisbillede? For at løse dette problem har docker RUNinstruktionen.

Efter vores python-eksempel, hvis vi havde brug for numpybiblioteket til at køre vores kode, kunne vi tilføje RUNinstruktionen lige efter vores FROMkommando.

# Dockerfile
FROM python:3
# NEW LINERUN pip3 install numpy
WORKDIR /src/app
COPY . .
CMD [ "python", "./hello.py" ]

Den RUNinstruktion dybest set giver en kommando der skal udføres af beholderens terminal. På den måde, da vores basisbillede allerede leveres med pip3installeret, kan vi bruge pip3 install numpy.

Bemærk: For en ægte python-app vil du sandsynligvis tilføje alle de afhængigheder, du har brug for, til en requirements.txtfil, kopiere den over til containeren og derefter opdatere RUNinstruktionen til RUN pip3 install -r requirements.txt.

Del 4. "Hej verden!" fra et Nginx-billede ved hjælp af en langvarig fritstående container

Jeg ved, at du sandsynligvis er træt af at høre mig sige det, men jeg har endnu en "Hej" at sige, før jeg går. Lad os gå videre og bruge vores nyerhvervede dockerkraft til at oprette en simpel, langvarig container i stedet for disse kortvarige, vi har brugt hidtil.

Opret en index.htmlfil i en ny mappe med følgende indhold.

# index.html

Hello, World!

Lad os nu oprette en ny Dockerfile i samme mappe.

# Dockerfile
FROM nginx:alpine
WORKDIR /usr/share/nginx/html
COPY . .

Byg billedet, og giv det navnet simple_nginx, som vi tidligere gjorde.

docker build -t simple_nginx .

Endelig lad os køre vores nyoprettede billede med følgende kommando:

docker run --rm -d -p 8080:80 simple_nginx

Du tænker måske på, at der ikke skete noget, fordi du er tilbage til din terminal, men lad os se nærmere på docker pskommandoen.

De docker pskommando viser alle de kørende containere i din maskine. Som du kan se på billedet ovenfor, har jeg en container med navnet simple_nginxkørende i min maskine lige nu. Lad os åbne en webbrowser og se om nginxdet gør sit job ved at få adgang localhost:8080.

Alt ser ud til at fungere som forventet, og vi serverer en statisk side gennem nginxkørslen inde i vores container. Lad os tage et øjeblik til at forstå, hvordan vi opnåede det.

At nedbryde det

Jeg vil springe over Dockerfile-forklaringen, fordi vi allerede har lært disse kommandoer i sidste afsnit. Det eneste "nye" i denne konfiguration er nginx:alpinebilledet, som du kan læse mere om det her.

Bortset fra hvad der er nyt, fungerer denne konfiguration, fordi den nginxbruger usr/share/nginx/htmlmappen til at søge efter en index.htmlfil og begynde at servere den, så da vi navngav vores fil index.htmlog konfigurerede den WORKDIRtil at være usr/share/nginx/html, fungerer denne opsætning lige ud af boksen.

Den buildkommando er nøjagtig som den, vi brugte i det sidste afsnit så godt, vi er kun ved hjælp af Dockerfile konfiguration til at opbygge et billede med et bestemt navn.

Nu til den sjove del, docker run --rm -d -p 8080:80 simple_nginxinstruktionen. Her har vi to nye flag. Den første er det løsrevne ( -d) flag, hvilket betyder, at vi vil køre denne container i baggrunden, og det er derfor, vi er tilbage på vores terminal lige efter at have brugt docker runkommandoen, selvom vores container stadig kører.

Det andet nye flag er -p 8080:80muligheden. Som du måske har gættet, er dette portflagget, og det kortlægger dybest set porten 8080fra vores lokale maskine til porten 80inde i vores container. Du kunne have brugt en hvilken som helst anden port i stedet for 8080, men du kan ikke ændre porten 80uden at tilføje en yderligere indstilling til nginxbilledet, da det 80er den standardport, som nginxbilledet udsætter.

Bemærk: Hvis du vil stoppe en løsrevet container som denne, kan du bruge docker pskommandoen til at hente containerens navn (ikke billede) og derefter bruge docker stopinstruktionen med den ønskede containers navn i slutningen af ​​linjen.

Del 5. Afslutningen

Det er det! Hvis du stadig læser dette, har du alt det grundlæggende for at begynde at bruge Docker i dag på dine personlige projekter eller daglige arbejde.

Fortæl mig, hvad du syntes om denne artikel i kommentarerne, og jeg sørger for at skrive en opfølgende artikel, der dækker mere avancerede emner som docker-composeet eller andet sted i den nærmeste fremtid.

Hvis du har spørgsmål, så lad mig det vide.

Skål!