Differences

This shows you the differences between two versions of the page.

Link to this comparison view

rl:labs:11:contents:02 [2019/12/08 14:53]
cosmin.prunaru [02. [20p] Docker images]
rl:labs:11:contents:02 [2024/01/08 12:34] (current)
vlad_iulius.nastase [02. [10p] VPC Networks]
Line 1: Line 1:
-==== 02. [20pDocker Images ​====+====== 02. [10pVPC Networks ======
  
-Făcând o analogie cu lumea sistemelor de operareputem considera ​un Docker image ca fiind similar unui binar - o componenta statică ce poate fi lansată în execuție. Un Docker container este asemănător procesuluio componenta dinamică ​care este o instanță aflată în execuție a unei imagini Docker.+După accesarea proiectuluiproiectul va avea atașat ​un **VPC network** numit default, care are alocat subnet-urile implicite pentru fiecare regiune
  
-{{ :rl:labs:11:contents:docker-steps.png?600 |}}+{{ :rl:labs:12:contents:vpc-network.png?700 |}}
  
-<​note>​ +<​note ​tip>Care era subrețeua folosită de Google Cloud pentru range-urile predefinite din fiecare regiune ? </​note>​
-În cadrul secțiunii curente vom parcurge etapele construcției unei imagini Docker scoțând în evidență câteva particularități ​de implementare. +
-</​note>​+
  
-Pentru început, să listăm imaginile stocate local. În lista desfășurată veți vedea imaginile pe care le-am utilizat în secțiunea 1: +<note warning
-<code bash+GCP impune o limitare de maxim Cloud Router pentru fiecare regiuneDeoarece un Cloud Router este atașat la  ​rețeava trebui ​să avem maxim 5 VPC Networks per regiuneÎnainte de a selecta regiunea ​pentru ​VPC Network verificațcă nu sunt deja 5 VPC Networks ​în acea regiune.
-student@aldebaran:​~$ docker image ls +
-REPOSITORY ​         TAG                 IMAGE ID            CREATED ​            ​SIZE +
-alpine ​             latest ​             965ea09ff2eb ​       6 weeks ago         5.55MB +
-hello-world ​        ​latest ​             fce289e99eb9 ​       11 months ago       ​1.84kB +
-</​code>​ +
- +
-Ca strategie, Docker își propune să ofere bibliotecă extrem de largă de servicii gata configurateîmpachetate sub formă de containere. În cazul în care ne dorim să căutăm o aplicație, un middleware, un runtime etccare ne-ar fi utile pentru ​a rezolva o cerință sau a dezvolta o soluție complexă, putem uta în upstream dacă există ​deja o astfel de imagine dezvoltată. Pentru a face acest lucru avem diferite metode, atât din CLI cât și din browser. Implicit, engine-ul docker va căuta ​în **DockerHub registry**, echivalentul GitHub pentru imagini DockerÎn terminologia Docker, un registry este un repository de imagini Docker: ''​docker search <nume imagine cautata>''​ +
-<note tip> +
-  * ''​docker search alpine''​ +
-  * ''​docker search httpd''​ +
-  * ''​docker search tomcat''​ +
-  * ''​docker search %%--filter%% is-official=true golang''​+
 </​note>​ </​note>​
  
-<note important>​ +Avem nevoie de un VPC custom pe care îl putem crea apăsând pe butonul ​**CREATE VPC NETWORK** aflat sub câmpul ​de căutare
-Un aspect foarte important din output-ul anterior ​îl reprezintă coloana Official, atribut ce garantează faptul că imaginea vizată este întreținută și verificată de către o comunitate de încredere, validată de către Docker. +În pagina ​de creare ​unui nou VPC trebuie ​să completăm următoarele detalii
-</​note>​  +  - Numele VPC-ului ​(doar caractere micicifre și cratimă sunt acceptate) și opțional o descriere - **student$X$-vpc-<name>​** ​(e.gstudent1-vpc) 
- +  Numele unui subnet definit ​în interiorul acestui VPC (aceleași limitări ca mai sus la caracterele acceptate**student$X$-host** (e.gstudent1-host) 
-Online putem accesa: ​ https://​hub.docker.com +  - Regiunea (este important să cream toate subnet-urile din acest laborator ​în aceeași regiunepreferabil ​**europe-west1**) 
-Pentru informații despre imagine de Alpine: ​ https://​hub.docker.com/​_/​alpine +  Range-ul de adrese IP din subnet ​- **10.$X$.0.0/24** (unde $X$ e id-ul de student ​) 
-Meniul tags este utilizat pentru diferențierea imaginilor ​pe versiuni/pe releases: https://​hub.docker.com/​_/​alpine?​tab=tags +  ​- Regulile ​de firewall aplicate pe VPC (nu uitați să bifați regulile ​de permitere ​**SSH** cel puțin). Vom edita regulile mai târziu ​pentru ​fiecare VPC.
- +
-Să creăm o imagine pornind de la imaginea oficială ​**Alpine** cu versiunea ​de release **latest**. În folder-ul home al utilizatorului curent creați un fișier numit ''​Dockerfile''​ și scrieți următoarele 2 linii: +
-<code bash> +
-student@aldebaran:​~$ cat Dockerfile +
-FROM alpine:​latest +
-CMD ["​echo",​ "Am facut si bune am facut si RL"] +
-</​code>​ +
- +
-Se poate observa ușor forma declarativă,​ auto-descriptivă,​ a instrucțiunilor Docker.  +
- +
-Urmând același flux ca în cazul construcției de software, vom compila codul Docker anterior scris, rezultatul fiind un obiect de tip Docker Image. Timpul de execuție poate varia și poate dura chiar și câteva minute. +
- +
-<code bash> +
-student@aldebaran:​~$ docker build -t rlrules/​rlhello:​v1.0 . +
-</​code>​ +
- +
-Înainte ​de a merge mai departe, ​să disecăm succint convenția de nume anterior folosită. +
-Numele imaginii Docker are în general ​următorul format:  +
- +
-''​%%<​DockerHub User (Repository) >/<​Nume Aplicație (Nume Imagine)>:<​tag (versiunerelease)>​ +
-rlrules/​rlhello:​v1.0%%''​ +
- +
-În sens mai extins, în cazul în care organizația în care lucrăm deține propriul repository de artefacte Docker (propriul Docker Registry), similar cu menținerea propriului Code Repository (ex: GitHub Enterprise, GitLab on premise, Atlassian Bitbucket etc.), convenția de nume este extinsă: +
- +
-''​%%<​adresă/​hostname registry>:<​port (oficial 5000)>/<​user (repository)>/<​Nume Aplicație (Nume Imagine)>:<​tag (versiune, release)>​ +
-mypersonalregistry:​5000/​rlrules/​rlhello:​v1.0%%''​ +
- +
-Respectarea unui astfel de format ne permite ulterior să putem face operațini de push sau pull asemănător acțiunilor pe care le putem face în GitHub/git server pentru un repository în care putem versiona ​și stoca codul. +
- +
-În continuare vom rula imaginea anterior creată: +
-<code bash> +
-student@aldebaran:​~$ docker run rlrules/​rlhello:​v1.0 +
-Am facut si bune am facut si RL +
-</​code>​ +
- +
-Utilizarea instucțiunii **CMD**, din Dockerfile, ne oferă, suplimentar,​ capabilitatea suprascrierii la runtime a comenzii specificate în declarație. Să testăm: +
-<code bash> +
-student@aldebaran:​~docker run rlrules/​rlhello:​v1.0 "​hello,​ world"​ +
-docker: Error response from daemon: OCI runtime create failed: container_linux.go:​346:​ starting container process caused "exec: \"​hello,​ world\":​ executable file not found in $PATH": unknown. +
-</​code>​ +
- +
-Eroarea apărută se datorează faptului că "​hello,​ world" nu este o comandă viabilă în Linux și deci nu este interpretată de către shell-ul utilizat (ex: bash, sh etc.)  +
- +
-<code bash> +
-student@aldebaran:​~$ docker run rlrules/​rlhello:​v1.0 cat /​etc/​issue +
-Welcome to Alpine Linux 3.10 +
-Kernel \r on an \m (\l) +
- +
-student@aldebaran:​~$ docker run rlrules/​rlhello:​v1.0 echo "​hello,​ world"​ +
-hello, world +
-</​code>​ +
- +
-Cele două comenzi vor rula cu succes, prima afișând o informație de pe container în timp ce a doua afișează mesajul transmis comenzii echo: hello, world +
- +
-Să modificăm imaginea anterioară înlocuind instrucțiunea **CMD** cu instrucțiunea **ENTRYPOINT**. +
-<code bash> +
-student@aldebaran:​~$ cat Dockerfile +
-FROM alpine:​latest +
-ENTRYPOINT ["​echo",​ "Am facut si bune am facut si RL"] +
-</​code>​ +
-În etapa de build vom construi un nou release v2.0: +
- +
-<code bash>​student@aldebaran:​~$ docker build -t rlrules/​rlhello:​v2.0 .</​code>​ +
- +
-Rularea release-ului v2.0 va avea același outcome ca în cazul versiunii anterioare : +
- +
-<code bash>​student@aldebaran:​~$ docker run rlrules/​rlhello:​v2.0</​code>​ +
- +
-Rezultatul utilizării celor 2 instrucțiuni ​(**CMD** ​și **ENTRYPOINT**este același! Care este totuși diferența între ​**CMD** și **ENTRYPOINT**?​ +
- +
-Pentru a vedea acest lucru, să încercăm să rulăm imaginea nouă utilizând, de data aceasta, argumente:​ +
-<code bash> +
-student@aldebaran:​~docker run rlrules/​rlhello:​v2.0 "​hello,​ world"​ +
-Am facut si bune am facut si RL hello, world +
-student@aldebaran:​~docker run rlrules/​rlhello:​v2.0 cat /​etc/​issue +
-Am facut si bune am facut si RL cat /​etc/​issue +
-student@aldebaran:​~$ docker run rlrules/​rlhello:​v2.0 echo "​hello,​ world"​ +
-Am facut si bune am facut si RL echo hello, world +
-</​code>​ +
- +
-Vedem că în cazul **ENTRYPOINT**,​ indiferent de argumentul adăugat la finalul comenzii docker run, acesta va fi anexat la comanda setată în instrucțiunea din DockerfileÎntrucât comanda configurată este echo <​string>,​ șirurile de caractere adăugate ulterior vor fi atașate stringului "Am făcut și bune, am făcut și RL"Într-o descriere mai pragmatică,​ **ENTRYPOINT** imprimă rolul unui executabil clasic asupra imaginii docker. +
- +
-<​note ​important+
-Challenge: Ce hack putem utiliza pentru a rula o altă comandă pe container?​ +
-<​solution>​ +
-<code bash> +
-docker run rlrules/​rlhello:​v2.0 ;cat /​etc/​passwd +
-</​code>​ +
-</​solution>​ +
-</​note>​ +
- +
-Un mecanism frecvent utilizat este conjuncția dintre cele două instrucțiuni. Putem folosi **ENTRYPOINT** pentru a desemna comanda fixă, explicit atașată containerului,​ în timp ce instrucțiunea **CMD** oferă argumentul default, interschimbabil,​ al comenzii definite de **ENTRYPOINT**. +
- +
- +
-Vom modifica imaginea astfel încât ​să reflecte scenariul definit anterior: +
-<code bash> +
-student@aldebaran:​~$ cat Dockerfile +
-FROM alpine:​latest +
- +
-ENTRYPOINT ["​echo"​] +
-CMD ["Am facut si bune, am facut si RL"] +
-</​code>​ +
- +
-Comanda echo este fixă, imutabilă, în timp ce string-ul ''​Am făcut și bune, am făcut și RL''​ devine valoare implicită ​în cazul în care niciun argument suplimentar nu este specificat în comanda docker run. +
- +
-Compilăm ​și rulăm noua imagine: +
- +
-<code bash> +
-student@aldebaran:​~$ docker build -t rlrules/​rlhello:​v3.0 . +
-student@aldebaran:​~$ docker run rlrules/​rlhello:​v3.0 +
-Am facut si buneam facut si RL +
-student@aldebaran:​~$ docker run rlrules/​rlhello:​v3.0 "​hello,​ world"​ +
-hello, world +
-student@aldebaran:​~$ docker run rlrules/​rlhello:​v3.0 cat /​etc/​issue +
-cat /​etc/​issue +
-student@aldebaran:​~$ docker run rlrules/​rlhello:​v3.0 echo "​hello,​ world"​ +
-echo hello, world +
-</​code>​ +
- +
-Lista instrucțiunilor Docker nu se rezumă doar la **FROM** sau **CMD**%%/​%%**ENTRYPOINT**. Pentru configurații mai complexe există o colecție largă de comenzi ce pot fi declarate la nivelul unui Dockerfile. Referințe despre aceste opțiuni se pot găsi pe site-ul Docker (https://​docs.docker.com/​engine/​reference/​builder/​+
- +
-În continuare vom crește complexitatea și vom construi un Dockerfile extins: +
-<code bash> +
-student@aldebaran:​~$ cat Dockerfile +
-FROM ubuntu:​latest +
-MAINTAINER rl-awesome-students-team +
- +
-RUN apt-get update && apt-get -y install cowsay +
-ENV RL_EXEC_PATH "/​usr/​games/"​ +
-ENV PATH=${PATH}:​${RL_EXEC_PATH} +
- +
-ENTRYPOINT ["​cowsay"​] +
-CMD ["Am facut si bune, am facut si RL"] +
-</​code>​ +
-Vom compila și rula imaginea nou definită:​ +
-<code bash>​student@aldebaran:​~$ docker build -t rlrules/​rlhello:​v4.0 .</​code>​ +
-<code bash>​student@aldebaran:​~$ docker run rlrules/​rlhello:​v4.0</​code>​ +
-<code bash>​student@aldebaran:​~$ docker run rlrules/​rlhello:​v4.0 "​Hello,​ world"</​code>​ +
- +
-În cadrul configurației curente, plecând de la imaginea de Ubuntu:​latest,​ la build time am instalat pachetul cowsay, am setat variabile de mediu, am specificat maintainer-ul imaginii și am configurat un parametrul implicit, în cazul în care imaginea este rulată fără parametrii adiționali. Complexitatea poate crește, în funcție ​de acțiunile pe care trebuie să le facem pentru a prepara containerul cu toate dependințele de care are nevoie.  +
- +
-Un aspect important și interesant legat de imagini este reprezentat de construcția pe layere/​straturi. Fiecare modificare adusă imaginii anterioare poate rezulta în construcția unui strat suplimentar. Dintr-o perspectivă simplificată,​ putem spune că fiecare instrucțiune ​din Dockerfile construiește o imagine nouă, intermediară,​ care se diferențiază de cea anterioară prin modificările aduse de instrucțiunea curentă. Plecând de la această premisă, un layer este exact acest delta dintre 2 imagini succesive. Dintr-o perspectivă mai complexă, nu orice instrucțiune rezultă într-un strat nou. Comenzi precum ​**CMD**, **MAINTAINER**,​ **ENTRYPOINT** nu aduc o modificare substanțială imaginii, ci alterează aspecte legate de metadatele atașate unei imagini +
- +
-Să validăm această informație pentru imaginea rlrules/​rlhello:​v4.0:​ +
-<code bash>​student@aldebaran:​~docker image inspect rlrules/​rlhello:​v4.0</​code>​ +
-În output-ul comenzii anterioare, căutați secțiunea RootFS. Pentru simplitate puteți rula: +
-<code bash> +
-student@aldebaran:​~$ docker image inspect --format "​{{json .RootFS}}"​ rlrules/​rlhello:​v4.0 | json_pp +
-</code> +
- +
-<note important>​ +
-Câte layere pot fi numărate? De ce? +
-<​solution>​ +
-<code bash> +
-student@aldebaran:​~docker image inspect ​--format "​{{json .RootFS}}"​ rlrules/​rlhello:​v4.0 | json_pp | grep -i sha256 | wc -l +
-</​code>​ +
-</​solution>​ +
-</​note>​ +
- +
-Să vedem care au fost acele instrucțiuni care au dus la construcția celor 5 straturi: +
-<code bash>student@aldebaran:​~$ docker image history rlrules/​rlhello:​v4.0</​code>​ +
-Toate instrucțiunile care au un ''​SIZE > 0''​ sunt responsabile de crearea unui layer suplimentar în imagine: +
-  ​* primele nivele sunt moștenite din construcția imaginii ​de bază Ubuntu cu tag-ul latest ​(''​**FROM** ubuntu:​latest''​) +
-  * ultimul nivel este adăugat de noi prin instrucțiunea ''​**RUN** apt-get update && apt-get install''​ ce creează noi fișiere în sistemul de fișiere +
- +
-În cazul în care ne dorim să ștergem o imagine de pe sistem, mai întâi trebuie să obținem identificatorul unic al imaginii (''​IMAGE ID''​)+
-<code bash>​student@aldebaran:​~$ docker image ls</​code>​ +
- +
-Să încercăm să ștergem imaginea rlrules/​rlhello:​v1.0: +
-<code bash>​student@aldebaran:​~$ docker image rm <id imagine rlrules/​rlhello:​v1.0></​code>​ +
-<note important>​De ce returnează eroare? Ce putem face pentru ​a șterge imaginea?</​note>​ +
- +
-O soluție a problemei anterioare o reprezintă ștergerea containerului care utilizează imaginea vizată: +
-<code bash>​student@aldebaran:​~$ docker container ps -a</​code>​ +
-<note important>​ +
-Care este containerul care utilizează imaginea vizată? +
-<code bash>​student@aldebaran:​~$ docker container rm <id container oprit care utilizeaza imaginea v1.0></​code>​ +
-</​note>​+
  
-Acum putem efectua ștergerea imaginii: 
-<code bash>​student@aldebaran:​~$ docker image rm <id imagine rlrules/​rlhello:​v1.0></​code>​ 
  
-Voila!+{{ :​rl:​labs:​12:​contents:​create-vpc-network.png?​500 |}}
rl/labs/11/contents/02.1575809614.txt.gz · Last modified: 2019/12/08 14:53 by cosmin.prunaru
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0