Acum, puteți construi imagini Docker în werf și folosind un Dockerfile obișnuit

Mai bine mai târziu decât niciodată. Sau cum am aproape comis o greșeală serioasă neavând suport pentru Dockerfile tradiționale pentru construirea imaginilor aplicației.

Acum, puteți construi imagini Docker în werf și folosind un Dockerfile obișnuit

Va fi vorba despre werf — un instrument GitOps care se integrează cu orice sistem CI/CD și asigură gestionarea întregului ciclu de viață al aplicației, permițând:

  • începutul și publicarea imaginilor,
  • implementarea aplicațiilor în Kubernetes,
  • eliminarea imaginilor neutilizate prin politici speciale.


Filozofia proiectului este de a aduna instrumente de nivel jos într-un singur sistem unificat, care să ofere inginerilor DevOps control asupra aplicațiilor. Pe cât posibil, trebuie să fie utilizate utilitarele existente (precum Helm și Docker). Dacă nu există o soluție pentru o anumită problemă, putem crea și menține tot ce este necesar pentru aceasta.

Context: propriul nostru constructor de imagini

Astfel s-a întâmplat cu constructorul de imagini în werf: ne lipsea Dockerfile-ul obișnuit. Dacă ne gândim la istoria proiectului, această problemă s-a manifestat în primele versiuni ale werf (pe atunci cunoscut ca dapp) Creând un instrument pentru construirea aplicațiilor în imagini Docker, ne-am dat rapid seama că Dockerfile-ul nu ne era potrivit pentru anumite sarcini specifice:).

Necesitatea de a construi aplicații web mici tipice conform următoarei scheme standard:

  1. instalarea dependențelor de sistem ale aplicației,
    • instalarea bibliotecilor de dependență ale aplicației,
    • construirea resurselor,
    • iar cel mai important - actualizarea rapidă și eficientă a codului în imagine.
    • La modificările din fișierele proiectului, constructorul trebuie să genereze rapid un nou strat prin aplicarea unui patch pe fișierele modificate.
  2. Dacă anumite fișiere s-au schimbat, atunci este necesar să se reconstruiască etapa de dependență corespunzătoare.
  3. Până în prezent, constructorul nostru are multe alte funcționalități, dar dorințele și impulsurile inițiale au fost acestea.

În general, fără să stăm pe gânduri, ne-am înarmat cu limbajul de programare utilizat

și am pornit la drum - implementând (vezi mai jos) DSL-ul nostru propriu ! Conform cerințelor stabilite, acesta a fost destinat descrierii procesului de construcție pe etape și determinării dependențelor acestor etape în funcție de fișiere. Și a fost completat deconstructorul propriu , care transforma DSL-ul în scopul final - imaginea construită. La început, DSL-ul era în Ruby, iar pe parcursultrecerii la Golang - configurația constructorului nostru a început să fie descrisă într-un fișier YAML. — конфиг нашего сборщика стал описываться в YAML-файле.

Acum, puteți construi imagini Docker în werf și folosind un Dockerfile obișnuit
Configurația veche pentru dapp pe Ruby

Acum, puteți construi imagini Docker în werf și folosind un Dockerfile obișnuit
Configurația actuală pentru werf pe YAML

Mecanismul de funcționare al compilatorului s-a schimbat de-a lungul timpului. La început, generam în mod temporar un Dockerfile din configurația noastră, iar apoi am început să rulăm instrucțiuni de compilare în containere temporare și să facem commit.

NB: În prezent, compilatorul nostru, care lucrează cu configurația sa (în YAML) și se numește compilator Stapel, s-a dezvoltat într-un instrument destul de puternic. Descrierea sa detaliată merită articole separate, iar principalele detalii pot fi aflate din documentation.

Conștientizarea problemei

Dar am realizat, deși nu imediat, că am făcut o greșeală: nu am adăugat posibilitatea de a construi imagini printr-un Dockerfile standard și de a le integra în aceeași infrastructură de gestionare completă a aplicației (adică de a construi imagini, a le desfășura și a le curăța). Cum era posibil să creăm un instrument pentru desfășurarea în Kubernetes și să nu implementăm suport pentru Dockerfile, adică metoda standard de descriere a imaginilor pentru cele mai multe proiecte?..

În loc de un răspuns la o astfel de întrebare, oferim soluția sa. Ce să faceți dacă aveți deja un Dockerfile (sau un set de Dockerfile-uri) și doriți să folosiți werf?

NB: Apropo, de ce ați dori să folosiți werf? Principalele funcții se reduc la următoarele:

  • ciclul complet de gestionare a aplicației, inclusiv curățarea imaginilor;
  • posibilitatea de a gestiona compilarea mai multor imagini dintr-o configurație unică;
  • procesul îmbunătățit de desfășurare a charturilor compatibile cu Helm.

Pentru o listă mai completă, puteți consulta pagina proiectului.

Așadar, dacă înainte am fi sugerat să rescriem Dockerfile-ul pe configurația noastră, acum spunem cu plăcere: „Permiteți-le werf să construiască Dockerfile-urile dvs.!"

Cum se folosește?

Implementarea completă a acestei funcționalități a apărut în versiunea werf v1.0.3-beta.1. Principiul general este simplu: utilizatorul specifică calea către Dockerfile existent în configurația werf, apoi rulează comanda werf build… și totul — werf va construi imaginea. Să luăm un exemplu abstract.

Să declarăm următorul Dockerfile în rădăcina proiectului:

FROM ubuntu:18.04
RUN echo Building ...

Și să declarăm werf.yaml, care folosește acest Dockerfile:

configVersion: 1
project: dockerfile-example
---
image: ~
dockerfile: ./Dockerfile

Asta e! Rămâne să pornească werf build:

Acum, puteți construi imagini Docker în werf și folosind un Dockerfile obișnuit

În plus, se poate declara următorul werf.yaml pentru a construi mai multe imagini din diferite Dockerfile-uri:

configVersion: 1
project: dockerfile-example
---
image: backend
dockerfile: ./dockerfiles/Dockerfile-backend
---
image: frontend
dockerfile: ./dockerfiles/Dockerfile-frontend

În cele din urmă, se suportă și transmiterea parametrilor suplimentari de construire — cum ar fi --build-arg și --add-host — prin intermediul configurației werf. O descriere completă a configurației imaginii Dockerfile este disponibilă pe pagina de documentație.

Cum funcționează?

În procesul de construire, funcționează memoria cache standard a nivelurilor locale în Docker. Cu toate acestea, ceea ce este important este că werf de asemenea integrează configurația Dockerfile în infrastructura sa. Ce înseamnă asta?

  1. Fiecare imagine construită din Dockerfile constă dintr-un singur stage numit dockerfile (detalii despre ce sunt stage-urile în werf pot fi citite aici).
  2. Pentru stage-ul dockerfile werf calculează o semnătură, care depinde de conținutul configurației Dockerfile. Când configurația Dockerfile se schimbă, se schimbă și semnătura etapei dockerfile iar werf inițiază reconstrucția acestei etape cu noua configurație Dockerfile. Dacă semnătura nu se schimbă, werf ia imaginea din cache (detalii despre utilizarea semnăturilor în werf au fost prezentate în această prezentare).
  3. Apoi, imaginile construite pot fi publicate cu comanda werf publish (sau werf build-and-publish) și utilizate pentru desfășurarea în Kubernetes. Imaginile publicate în Docker Registry vor fi curățate cu ajutoarele standard de curățare werf, adică va avea loc o curățare automată a imaginilor vechi (mai vechi de N zile), a imaginilor legate de ramuri Git inexistente și conform altor politici.

Detalii despre aspectele descrise aici pot fi găsite în documentație:

Note și precauții

1. URL extern în ADD nu este suportat

În prezent, utilizarea unui URL extern în directiva ADD. Werf nu va iniția reconstrucția în cazul modificării resursei la URL-ul specificat. Este planificată introducerea acestei funcții în curând.

2. Nu se poate adăuga .git în imagine

În general, adăugarea directorului .git în imagine este o practică proastă și iată de ce:

  1. Dacă .git rămâne în imaginea finală, încălcând principiile 12 factor app: deoarece imaginea finală trebuie să fie asociată cu un singur commit, nu ar trebui să existe posibilitatea de a face git checkout un commit aleator.
  2. .git crește dimensiunea imaginii (repozitoriul poate fi mare deoarece a fost adăugat anterior fișiere mari, iar apoi s-au șters). Dimensiunea work-tree, legată doar de un anumit commit, nu va depinde de istoricul operațiunilor în Git. În același timp, adăugarea și apoi eliminarea .git Din imaginea finală nu se va activa: imaginea va căpăta oricum un strat suplimentar — așa funcționează Docker.
  3. Docker poate iniția o reconstituire suplimentară, chiar dacă se compilează același commit, dar din work-tree-uri diferite. De exemplu, GitLab creează directorii separate clonat. /home/gitlab-runner/builds/HASH/[0-N]/yourproject când compilarea paralelă este activată. Reconstituirea suplimentară va fi legată de faptul că directorul .git diferențiază versiuni diferite clonat ale aceluiași repository, chiar dacă se compilează același commit.

Ultimul punct are consecințe și atunci când utilizați werf. Werf necesită ca cache-ul construit să fie prezent în timpul rulării unor comenzi (de exemplu, werf deploy). În timpul rularii acestor comenzi, werf calculează semnăturile stadiilor pentru imaginile specificate în werf.yaml, și acestea trebuie să fie în cache-ul de compilare — altfel, comanda nu va putea continua. Dacă semnătura stadiilor depinde de conținutul .git, atunci obținem un cache instabil la modificări în fișiere nerelevante, iar werf nu va putea ierta o astfel de greșeală (mai multe detalii pot fi găsite în documentation).

În general adăugarea doar a fișierelor necesare prin instrucțiunea ADD în orice caz, crește eficiența și fiabilitatea acestuia Dockerfile, precum și îmbunătățește stabilitatea cache-ului, construit pe baza acestuia Dockerfile, la modificările nerelevante din Git.

Rezultatul

Calea noastră inițială cu scrierea propriului builder pentru nevoile specifice a fost grea, cinstită și dreaptă: în loc să folosim soluții temporare peste Dockerfile-ul standard, ne-am scris propria soluție cu o sintaxă personalizată. Și aceasta a avut avantajele ei: builder-ul Stapel își îndeplinește excelent sarcina.

Cu toate acestea, în procesul de scriere a propriului builder, am omis să suportăm deja existenții Dockerfile. Acum această lipsă este corectată, iar pe viitor ne propunem să dezvoltăm suportul pentru Dockerfile, împreună cu builder-ul nostru personalizat Stapel pentru compilarea distribuită și pentru compilarea utilizând Kubernetes (adică compilarea pe runneri în interiorul Kubernetes, așa cum se face în kaniko).

Așadar, dacă ai câteva Dockerfile-uri adunate pe undeva... încercați werf!

P.S. Lista de documentație pe subiect

Citiți și în blogul nostru: „werf — our tool for CI/CD in Kubernetes (overview and presentation video)».

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster