Differences

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

Link to this comparison view

idp:laboratoare:01 [2021/03/07 07:49]
radu.ciobanu
idp:laboratoare:01 [2022/03/07 15:12] (current)
radu.ciobanu [Instalare]
Line 9: Line 9:
 De asemenea, Docker oferă flexibilitate maximă. Dacă, într-un proiect de mari dimensiuni, avem nevoie de unelte software noi pentru că se schimbă anumite cerințe, le putem împacheta în containere și apoi să le legăm foarte ușor la sistem. Dacă avem nevoie de replicarea infrastructurii pe alt mediu, putem refolosi imaginile de Docker salvate în registru (un fel de repository de containere). Dacă avem nevoie de actualizarea anumitor componente, Docker ne permite să rescriem imaginile, ceea ce înseamnă că se vor lansa, mereu, cele mai noi versiuni ale componentelor sub formă de containere. De asemenea, Docker oferă flexibilitate maximă. Dacă, într-un proiect de mari dimensiuni, avem nevoie de unelte software noi pentru că se schimbă anumite cerințe, le putem împacheta în containere și apoi să le legăm foarte ușor la sistem. Dacă avem nevoie de replicarea infrastructurii pe alt mediu, putem refolosi imaginile de Docker salvate în registru (un fel de repository de containere). Dacă avem nevoie de actualizarea anumitor componente, Docker ne permite să rescriem imaginile, ceea ce înseamnă că se vor lansa, mereu, cele mai noi versiuni ale componentelor sub formă de containere.
  
 +<note tip>
 +Docker este o variantă foarte bună ca mediu de lucru, cele mai multe IDE-uri cum ar fi Visual Studio, VSCode sau IntelliJ, au integrat suport pentru debugging în Docker fie în mod implicit fie ca plugin. Motivul pentru care cele mai folosite IDE-uri ofera acest suport este ca imaginile de Docker reprezinta un mediu de lucru replicabil și consistent identic cu cel de productie.
 +</​note>​
 ==== Imagini și containere ==== ==== Imagini și containere ====
  
Line 33: Line 36:
 Comenzile de mai jos sunt pentru Ubuntu. Pentru alte variante de Linux (Debian, CentOS, Fedora), găsiți informații suplimentare pe pagina de documentație oficială Docker. Comenzile de mai jos sunt pentru Ubuntu. Pentru alte variante de Linux (Debian, CentOS, Fedora), găsiți informații suplimentare pe pagina de documentație oficială Docker.
  
-Pentru instalarea Docker CE, este nevoie de una din următoarele versiuni de Ubuntu: ​Focal 20.04 (LTS)Disco 19.04, Cosmic 18.10, Bionic 18.04 (LTS), ​Xenial 16.04 (LTS). Docker CE are suport pentru arhitecturile **//​x86_64//​**,​ **//​amd64//​**,​ **//​armhf//​**,​ **//​arm64//​****//​s390x//​** (IBM Z) și **//​ppc64le//​** (IBM Power).+Pentru instalarea Docker CE, este nevoie de una din următoarele versiuni de Ubuntu: ​Impish 21.10Hirsute 21.04, Focal 20.04 (LTS), ​Bionic 18.04 (LTS). Docker CE are suport pentru arhitecturile **//​x86_64//​**,​ **//​amd64//​**,​ **//​armhf//​**,​ **//​arm64//​** ​și **//​s390x//​** (IBM Z).
    
-Varianta recomandată de instalare a Docker CE presupune folosirea repository-ului oficial, deoarece update-urile sunt apoi instalate automat. La prima instalare a Docker CE pe o mașină, este necesară inițializarea repository-ului ​(exemplul de mai jos este pentru un sistem cu arhitectură **//​amd64//​**):+Varianta recomandată de instalare a Docker CE presupune folosirea repository-ului oficial, deoarece update-urile sunt apoi instalate automat. La prima instalare a Docker CE pe o mașină, este necesară inițializarea repository-ului:​
  
 <code bash> <code bash>
Line 42: Line 45:
  
 <code bash> <code bash>
-$ sudo apt-get install ​apt-transport-https ​ca-certificates curl software-properties-common+$ sudo apt-get install ca-certificates curl gnupg lsb-release
 </​code>​ </​code>​
  
 <code bash> <code bash>
-$ curl -fsSL https://​download.docker.com/​linux/​ubuntu/​gpg | sudo apt-key add -+$ curl -fsSL https://​download.docker.com/​linux/​ubuntu/​gpg | sudo gpg --dearmor -o /​usr/​share/​keyrings/​docker-archive-keyring.gpg
 </​code>​ </​code>​
  
 <code bash> <code bash>
-sudo add-apt-repository ​"deb [arch=amd64] https://​download.docker.com/​linux/​ubuntu $(lsb_release -cs) stable"​+echo \ 
 +  ​"deb [arch=$(dpkg --print-architecture) signed-by=/​usr/​share/​keyrings/​docker-archive-keyring.gpg] https://​download.docker.com/​linux/​ubuntu ​
 +  ​$(lsb_release -cs) stable" ​| sudo tee /​etc/​apt/​sources.list.d/​docker.list > /dev/null
 </​code>​ </​code>​
  
Line 441: Line 446:
 </​code>​ </​code>​
  
-Înainte de a publica imaginea în registru, ea trebuie tag-uită după formatul **//​username/​repository:​tag//​**. Tag-ul este opțional, dar este util pentru că denotă versiunea unei imagini Docker. Se folosește următoarea comandă pentru tag-uirea unei imagini (în exemplul de mai jos, unde vrem să tag-uim imaginea pe care am creat-o ​în laboratorul anterior, utilizatorul se numește **//​raduioanciobanu//​**,​ repository-ul este **//​idp//​**,​ iar tag-ul este **//​example//​**):​+Înainte de a publica imaginea în registru, ea trebuie tag-uită după formatul **//​username/​repository:​tag//​**. Tag-ul este opțional, dar este util pentru că denotă versiunea unei imagini Docker. Se folosește următoarea comandă pentru tag-uirea unei imagini (în exemplul de mai jos, unde vrem să tag-uim imaginea pe care am creat-o ​mai devreme, utilizatorul se numește **//​raduioanciobanu//​**,​ repository-ul este **//​idp//​**,​ iar tag-ul este **//​example//​**):​
  
 <code bash> <code bash>
Line 482: Line 487:
 Alternativ, în loc să rulăm comanda de publicare a unei imagini de fiecare dată când modificăm ceva la codul sursă, putem să configurăm [[https://​docs.docker.com/​docker-hub/​builds/​|build-uri automate]] din contul de Docker Hub. Pașii necesari sunt descriși în continuare. Alternativ, în loc să rulăm comanda de publicare a unei imagini de fiecare dată când modificăm ceva la codul sursă, putem să configurăm [[https://​docs.docker.com/​docker-hub/​builds/​|build-uri automate]] din contul de Docker Hub. Pașii necesari sunt descriși în continuare.
 În primul rând, este necesară existența unui repository Docker Hub și a unui repository pe GitHub (Docker Hub funcționează și cu BitBucket, dar în acest exemplu ne vom concentra pe GitHub). Toate fișierele necesare creării unei imagini Docker (adică Dockerfile-ul și toate fișierele sursă și de configurare) trebuie să fie prezente în repository-ul GitHub. Mai departe, de pe pagina repository-ului de Docker Hub, se selectează tab-ul Builds și apoi opțiunea „Configure Automated Builds”, așa cum se poate observa în imaginea de mai jos. În primul rând, este necesară existența unui repository Docker Hub și a unui repository pe GitHub (Docker Hub funcționează și cu BitBucket, dar în acest exemplu ne vom concentra pe GitHub). Toate fișierele necesare creării unei imagini Docker (adică Dockerfile-ul și toate fișierele sursă și de configurare) trebuie să fie prezente în repository-ul GitHub. Mai departe, de pe pagina repository-ului de Docker Hub, se selectează tab-ul Builds și apoi opțiunea „Configure Automated Builds”, așa cum se poate observa în imaginea de mai jos.
 +
 +<note tip>
 +Dacă lucrați la proiecte cu cod aflat pe repository-uri de git este de preferat să folosiți registrele de pe aceleși platforme în loc de Docker Hub, iar Github, Gitlab și Bitbucket ofera registre de imagini gratis. ​
 +</​note>​
  
 {{:​idp:​laboratoare:​dockerhub.png?​direct&​600|}} {{:​idp:​laboratoare:​dockerhub.png?​direct&​600|}}
Line 826: Line 835:
 </​code>​ </​code>​
  
 +Pentru a atașa un bind mount, comanda este similară, cu excepția faptului că trebuie să adăugăm și parametrul **//​type=bind//​** la opțiunile d mount, iar calea către bind mount trebuie să fie absolută, astfel:
 +
 +<code bash>
 +$ docker container run --name c3 -d -it --mount type=bind,​source="​$(pwd)"/​testidp/,​target=/​testidp2 alpine
 +</​code>​
 ==== Docker pe Windows și pe MacOS ==== ==== Docker pe Windows și pe MacOS ====
  
Line 903: Line 917:
 Diferența dintre comenzile **//​exec//​** și **//​attach//​** (care pot părea similare) este că, la **//​attach//​**,​ se asociază un terminal la container, ceea ce înseamnă că, dacă se iese din acel terminal, se iese cu totul și din container. Diferența dintre comenzile **//​exec//​** și **//​attach//​** (care pot părea similare) este că, la **//​attach//​**,​ se asociază un terminal la container, ceea ce înseamnă că, dacă se iese din acel terminal, se iese cu totul și din container.
 </​note>​ </​note>​
 +
 +=== Comenzi de lucru cu un registru ===
 +
 +<code bash>
 +$ docker login [–u <​UTILIZATOR>​ –p <​PAROLĂ>​] [SERVER] ​  # loghează un utilizator într-un registru
 +$ docker tag <​IMAGINE>​ <​UTILIZATOR/​REPOSITORY:​TAG> ​     # dă un tag unei imagini pentru upload în registru
 +$ docker push <​UTILIZATOR/​REPOSITORY:​TAG> ​              # uploadează o imagine în registru
 +</​code>​
 +
 +=== Creare și interacțiune cu rețele ===
 +
 +<code bash>
 +$ docker network create -d <​DRIVER>​ <​REȚEA> ​         # creează o rețea cu un driver dat
 +$ docker network ls                                  # afișează rețelele existente
 +$ docker network rm                                  # șterge o rețea
 +$ docker network connect <​REȚEA>​ <​CONTAINER> ​        # conectează un container la o rețea
 +$ docker network disconnect <​REȚEA>​ <​CONTAINER> ​     # deconectează un container de la o rețea
 +$ docker network inspect <​REȚEA> ​                    # afișează informații despre o rețea
 +$ docker container run --network=<​REȚEA>​ <​IMAGINE> ​  # pornește un container într-o rețea
 +</​code>​
 +
 +=== Creare și interacțiune cu volume sau bind mounts ===
 +
 +<code bash>
 +$ docker volume create <​VOLUM> ​                                               # creează un volum
 +$ docker volume ls                                                            # afișează volumele existente
 +$ docker volume rm <​VOLUM> ​                                                   # șterge un volum
 +$ docker container run -v <​VOLUM>​ <​IMAGINE> ​                                  # rulează un container cu un volum atașat
 +$ docker container run -v <​SURSĂ>:<​DESTINAȚIE>​ <​IMAGINE> ​                     # rulează un container cu un volum sau un bind mount atașat
 +$ docker container run --mount source=<​SURSĂ>,​target=<​DESTINAȚIE>​ <​IMAGINE> ​  # rulează un container cu un volum sau bind mount atașat
 +</​code>​
 +
 +==== Exerciții ====
 +
 +=== Comenzi de bază ===
 +
 +  - Aduceți în cache-ul local imaginea **//​busybox//​** din registrul oficial Docker.
 +  - Rulați un container de **//​busybox//​** care să execute comanda **//​uptime//​**.
 +  - Rulați un container interactiv de **//​busybox//​**. Odată ce ați intrat în el, executați comanda **//wget google.com//​**,​ apoi ieșiți.
 +  - Rulați un container interactiv detașat (daemon) de **//​busybox//​**. Odată ce l-ați pornit, atașați-vă la el și dați comanda **//id//**, apoi ieșiți.
 +  - Ștergeți toate containerele și imaginile create la punctele precedente.
 +
 +=== Crearea unei imagini ===
 +
 +<note tip>​Pentru exercițiile următoare, veți porni de la {{:​idp:​laboratoare:​homework1.zip|această arhivă}}, care conține o aplicație simplă NodeJS.</​note>​
 +
 +  - Pornind de la cele două fișiere din arhivă, scrieți un Dockerfile care va crea o imagine urmărind pașii de mai jos:
 +    - se va porni de la cea mai recentă versiune a imaginii oficiale de NodeJS, adică **//​node:​15.11.0-stretch//​**
 +    - se va copia fișierul **//​package.json//​** din arhivă în directorul curent (./); acest fișier are rolul de a specifica dependențele aplicației NodeJS (de exemplu, framework-ul Express.js)
 +    - se va rula comanda **//npm install//** pentru a instala dependețele din fișierul de la pasul precedent
 +    - se va copia sursa **//​server.js//​** în directorul de lucru **// /​usr/​src/​app/​ //**
 +    - se va expune portul 8080
 +    - în final, se va menționa comanda de rulare a aplicației;​ astfel, se va rula fișierul **///​usr/​src/​app/​server.js//​** cu binarul **//​node//​**.
 +  - Folosiți Dockerfile-ul scris anterior pentru a crea o imagine numita **//​nodejstest//​**.
 +  - Porniți un container care să ruleze imaginea **//​nodejstest//​** pe portul 12345 în modul detașat (daemon). Verificați că funcționează corect intrând pe [[http://​127.0.0.1:​12345]].
 +
 +=== Lucrul cu rețele, volume și bind mounts ===
 +
 +<note tip>​Pentru exercițiile următoare, veți porni de la {{:​idp:​laboratoare:​homework2.zip|această arhivă}}, care conține o aplicație NodeJS care realizează un API de adăugare de cărți într-o bibliotecă peste o bază de date PostgreSQL. Exercițiile de mai jos vă trec prin pașii necesari pentru a rula un container pentru o bază de date PostgreSQL și containerul cu aplicația în aceeași rețea, având persistență la oprirea containerelor.</​note>​
 +
 +  - Pe baza surselor și a fișierului Dockerfile din arhiva de laborator, construiți o imagine cu numele (tag-ul) **//​api-laborator-1-image//​**.
 +  - Creați o rețea bridge numită **//​laborator1-db-network//​**.
 +  - Creați un volum numit **//​laborator1-db-persistent-volume//​**.
 +  - Porniți în background un container pentru o bază de date cu următoarele caracteristici:​
 +    - se va atașa un bind mount care va face o mapare între fișierul **//​init-db.sql//​** de pe mașina locală (acesta va fi sursa la flag-ul de bind mount și se găsește în arhiva de laborator) și fișierul **///​docker-entrypoint-initdb.d/​init-db.sql//​** din containerul care se va rula (acesta va fi destinația)
 +    - se va atașa volumul **//​laborator1-db-persistent-volume//​** creat anterior (sursa) la calea **///​var/​lib/​postgresql/​data//​** din containerul care se va rula (destinația)
 +    - se va rula containerul în rețeaua **//​laborator1-db-network//​** creată anterior
 +    - se vor specifica următoarele variabile de mediu (într-o comandă de **//docker run//**, acest se lucru se face astfel: **//docker run -e NUME=valoare//​**):​
 +      - variabila **//​POSTGRES_USER//​** cu valoare **//​admin//​**
 +      - variabila **//​POSTGRES_PASSWORD//​** cu valoarea **//​admin//​**
 +      - variabila **//​POSTGRES_DB//​** cu valoarea **//​books//​**
 +    - containerul rulat se va numi **//​laborator1-db//​**
 +    - se va rula imaginea **//​postgres//​** din registrul oficial.
 +  - Porniți în background un container cu imaginea **//​api-laborator-1-image//​** creată anterior, cu următoarele caracteristici:​
 +    - se va rula containerul în rețeaua **//​laborator1-db-network//​** creată anterior
 +    - se vor specifica următoarele variabile de mediu:
 +      - variabila **//​PGUSER//​** cu valoare **//​admin//​**
 +      - variabila **//​PGPASSWORD//​** cu valoarea **//​admin//​**
 +      - variabila **//​PGDATABASE//​** cu valoarea **//​books//​**
 +      - variabila **//​PGHOST//​** cu valoarea **//​laborator1-db//​**
 +      - variabila **//​PGPORT//​** cu valoarea **//​5432//​**
 +    - containerul rulat se va numi **//​laborator1-api//​**
 +    - containerul va expune portul 80 și îl va mapa la portul 5555 de pe mașina locală.
 +  - Verificați că cele două containere rulează corect și au conectivitate:​
 +    - folosind [[https://​www.postman.com|Postman]] sau orice altă aplicație similară, realizați cereri de GET și POST pe [[http://​localhost:​5555/​api/​books]] (pentru un tutorial de Postman, puteți intra [[https://​learning.postman.com/​docs/​getting-started/​sending-the-first-request/​|aici]])
 +    - la cererile de POST, se așteaptă un body JSON cu formatul ''​%%{"​title":"​titlu","​author":"​autor"​}%%''​
 +    - cererile de GET vor returna o listă de cărți adăugate prin cereri de POST.
 +  - Verificați că volumul pe care l-ați adăugat păstrează persistența datelor:
 +    - opriți și ștergeți cele două containere
 +    - reporniți cele două containere cu aceleași comenzi ca anterior
 +    - trimiteți o cerere de GET
 +    - dacă ați configurat corect, veți primi o listă cu cărțile adăugate anterior.
idp/laboratoare/01.1615096159.txt.gz · Last modified: 2021/03/07 07:49 by radu.ciobanu
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