Budowanie obrazów Docker w werf jest teraz możliwe również za pomocą zwykłego Dockerfile

Lepiej późno niż wcale. Albo jak ledwo nie popełniliśmy poważnego błędu, nie mając wsparcia dla standardowych Dockerfile do budowania obrazów aplikacji.

Budowanie obrazów Docker w werf jest teraz możliwe również za pomocą zwykłego Dockerfile

Będzie mowa o werf — narzędziu GitOps, które integruje się z każdym systemem CI/CD i zapewnia zarządzanie całym cyklem życia aplikacji, umożliwiając:

  • tworzenie i publikowanie obrazów,
  • wdrażanie aplikacji w Kubernetes,
  • usuwanie nieużywanych obrazów za pomocą specjalnych polityk.


Filozofia projektu to zebranie narzędzi niskiego poziomu w jednolitą zintegrowaną system, który daje inżynierom DevOps kontrolę nad aplikacjami. W miarę możliwości powinny być wykorzystywane już istniejące narzędzia (takie jak Helm i Docker). Jeśli nie ma rozwiązania jakiegoś problemu — możemy stworzyć i wesprzeć wszystko, co potrzebne do tego.

Wstęp: nasz własny kompilator obrazów

I tak się stało w przypadku kompilatora obrazów w werf: brakujący nam standardowy Dockerfile okazał się niewystarczający. Jeśli przyjrzeć się historii projektu, problem ten ujawnił się już w pierwszych wersjach werf (wtedy jeszcze znanego jako dapp).

Tworząc narzędzie do budowy aplikacji w obrazy Docker, szybko zrozumieliśmy, że Dockerfile nie nadaje się do niektórych konkretnych zadań:

  1. Potrzeba budowania typowych małych aplikacji webowych wg następującego standardowego schematu:
    • zainstalować systemowe zależności aplikacji,
    • zainstalować pakiet bibliotek zależności aplikacji,
    • zbudować zasoby,
    • i co najważniejsze — szybko i efektywnie aktualizować kod w obrazie.
  2. Przy zmianach w plikach projektu, kompilator musi szybko tworzyć nową warstwę poprzez nakładanie poprawek na zmienione pliki.
  3. Jeżeli zmieniły się konkretne pliki, należy przebudować odpowiednią zależną fazę.

Na dzień dzisiejszy nasz kompilator ma wiele innych możliwości, ale początkowe pragnienia i impuls były takie.

Generalnie, bez zastanowienia, uzbroiliśmy się w używany język programowania (patrz poniżej) i wyruszyliśmy w drogę — implementować własny DSL! Odpowiadając na postawione zadania, był on przeznaczony do opisu procesu budowy w etapach i definiowania zależności tych etapów od plików. A uzupełniał go własny kompilator, który przekształcał DSL w końcowy cel — zbudowany obraz. Początkowo DSL był w Ruby, a w miarę przechodzenia na Golang — konfiguracja naszego kompilatora jest teraz opisana w pliku YAML.

Budowanie obrazów Docker w werf jest teraz możliwe również za pomocą zwykłego Dockerfile
Stara konfiguracja dla aplikacji dapp na Ruby

Budowanie obrazów Docker w werf jest teraz możliwe również za pomocą zwykłego Dockerfile
Aktualna konfiguracja dla werf w YAML

Mechanizm działania kompilatora również zmieniał się z czasem. Początkowo po prostu generowaliśmy na bieżąco tymczasowy Dockerfile z naszej konfiguracji, a potem zaczęliśmy uruchamiać instrukcje kompilacji w tymczasowych kontenerach i wykonywać commit.

NB: Obecnie nasz kompilator, który działa ze swoją konfiguracją (w YAML) i nazywa się kompilatorem Stapel, już ewoluował w wystarczająco potężne narzędzie. Jego rozbudowany opis zasługuje na oddzielne artykuły, a główne szczegóły można znaleźć w dokumentacji.

Świadomość problemu

Jednak zrozumieliśmy, i to nie od razu, że popełniliśmy jeden błąd: nie dodaliśmy możliwości kompilowania obrazów przez standardowy Dockerfile i integrowania ich w tę samą infrastrukturę kompleksowego zarządzania aplikacją (tzn. kompilowania obrazów, wdrażania i czyszczenia ich). Jak można było stworzyć narzędzie do wdrażania w Kubernetes i nie zrealizować wsparcia dla Dockerfile, tzn. standardowego sposobu opisywania obrazów dla większości projektów?..

Zamiast odpowiedzi na takie pytanie oferujemy jego rozwiązanie. Co zrobić, jeśli już posiadasz Dockerfile (lub zestaw Dockerfile’ów) i chcesz używać werf?

NB: Zresztą, dlaczego w ogóle chcesz używać werf? Główne funkcje ograniczają się do następujących:

  • pełny cykl zarządzania aplikacją, w tym czyszczenie obrazów;
  • możliwość zarządzania kompilacją od razu kilku obrazów z jednego pliku konfiguracyjnego;
  • ulepszony proces wdrażania chartów, zgodnych z Helm.

Pełną listę ich funkcji można znaleźć na Część 2: laboratoria.

A więc, jeśli wcześniej zaproponowalibyśmy przepisanie Dockerfile na naszą konfigurację, to teraz z radością powiemy: „Pozwól werf skompilować Twoje Dockerfile’y!”

Jak z tego korzystać?

Pełna realizacja tej możliwości pojawiła się w wersji werf v1.0.3-beta.1. Ogólny zasada jest prosta: użytkownik wskazuje ścieżkę do istniejącego Dockerfile w konfiguracji werf, a następnie uruchamia polecenie werf build… i to wszystko — werf skompiluje obraz. Rozważmy to na abstrakcyjnym przykładzie.

Ogłośmy następny Dockerfile w głównym katalogu projektu:

FROM ubuntu:18.04
RUN echo Budowanie ...

I ogłośmy werf.yaml, który wykorzystuje ten Dockerfile:

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

To wszystko! Pozostaje ,但这一过程并没有像他们的创始人希望的那样顺利。 werf build:

Budowanie obrazów Docker w werf jest teraz możliwe również za pomocą zwykłego Dockerfile

Ponadto, można ogłosić następny werf.yaml do kompilacji od razu kilku obrazów z różnych Dockerfile’ów:

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

W końcu wspierane jest również przekazywanie dodatkowych parametrów budowy — takich jak --build-arg i --add-host — przez konfigurację werf. Pełny opis konfiguracji obrazu Dockerfile dostępny jest na stronie dokumentacji.

Jak to działa?

Podczas budowy działa standardowa pamięć podręczna lokalnych warstw w Dockerze. Co ważne, werf również integruje konfigurację Dockerfile w swoją infrastrukturę. Co to oznacza?

  1. Każdy obraz zbudowany z Dockerfile składa się z jednej fazy o nazwie dockerfile (więcej o tym, czym są fazy w werf, można przeczytać tutaj).
  2. Dla fazy dockerfile werf oblicza podpis, który zależy od zawartości konfiguracji Dockerfile. Po zmianie konfiguracji Dockerfile następuje zmiana podpisu fazy dockerfile i werf inicjuje ponowne budowanie tej fazy z nową konfiguracją Dockerfile. Jeśli jednak podpis się nie zmienia, werf pobiera obraz z pamięci podręcznej (więcej o używaniu podpisów w werf było omawiane w tej prezentacji).
  3. Następnie zbudowane obrazy można opublikować komendą werf publish (lub werf build-and-publish) i używać do wdrożenia w Kubernetes. Opublikowane obrazy w rejestrze Docker będą czyszczone standardowymi środkami czyszczenia werf, tj. nastąpi automatyczne czyszczenie starych obrazów (starszych niż N dni), obrazów związanych z nieistniejącymi gałęziami Git oraz według innych polityk.

Więcej o opisanych tu kwestiach można znaleźć w dokumentacji:

Uwagi i ostrzeżenia

1. Zewnętrzny adres URL w ADD nie jest wspierany

Obecnie nie wspiera się użycia zewnętrznego adresu URL w dyrektywie ADD. Werf nie rozpocznie ponownego budowania przy zmianie zasobu według wskazanego adresu URL. Wkrótce planowane jest dodanie tej możliwości.

2. Nie można dodawać .git do obrazu

Ogólnie rzecz biorąc, dodawanie katalogu .git do obrazu jest praktyką niewłaściwą i oto dlaczego:

  1. Jeśli .git zostaje w finalnym obrazie, narusza zasady 12 factor app: ponieważ końcowy obraz powinien być związany z jednym commitem, nie powinno być możliwości wykonania git checkout dowolnego commita.
  2. .git powiększa rozmiar obrazu (repozytorium może być duże, ponieważ kiedyś dodano do niego duże pliki, a później je usunięto). Rozmiar work-tree, związany tylko z określonym commitem, nie będzie zależał od historii operacji w Git. W tym przypadku dodanie i późniejsze usunięcie .git z finalnego obrazu nie zadziała: obraz i tak nabierze dodatkowej warstwy — tak działa Docker.
  3. Docker może inicjować niepotrzebną przebudowę, nawet jeśli jest budowany ten sam commit, ale z różnych work-tree. Na przykład, GitLab tworzy osobne skierowane katalogi w /home/gitlab-runner/builds/HASH/[0-N]/yourproject przy włączonej równoległej budowie. Dodatkowa przebudowa będzie związana z tym, że katalog .git różni się w różnych sklonowanych wersjach tego samego repozytorium, nawet jeśli budowany jest ten sam commit.

Ostatni punkt ma konsekwencje również przy używaniu werf. Werf wymaga, aby skompilowana pamięć podręczna była obecna podczas uruchamiania niektórych poleceń (np. werf deploy). Podczas działania takich poleceń werf oblicza sygnatury etapów dla obrazów wskazanych w werf.yaml, i muszą być w pamięci podręcznej budowy — w przeciwnym razie polecenie nie będzie mogło kontynuować. Jeśli sygnatura etapów będzie zależała od zawartości .git, otrzymujemy niestabilną pamięć podręczną, która nie jest odporna na zmiany w nieistotnych plikach, a werf nie będzie w stanie wybaczyć takiej pomyłki (szczegóły w dokumentacji).

Ogólnie dodanie tylko określonych, niezbędnych plików za pomocą instrukcji ADD w każdym przypadku zwiększa efektywność i niezawodność pisanego Dockerfile, a także poprawia odporność pamięci podręcznej zbudowanej na tym Dockerfile, na zmiany, które nie mają związku z Git.

Podsumowanie

Nasza pierwotna droga pisania własnego kompilatora na określone potrzeby była trudna, uczciwa i prosta: zamiast używać obejść w standardowym Dockerfile, napisaliśmy nasze rozwiązanie z niestandardową składnią. I to dało swoje korzyści: kompilator Stapel doskonale spełnia swoje zadanie.

Jednak w procesie pisania własnego kompilatora przeoczyliśmy wsparcie dla już istniejących Dockerfile’ów. Obecnie ten niedobór został naprawiony, a w przyszłości planujemy rozwijać wsparcie dla Dockerfile obok naszego niestandardowego kompilatora Stapel dla złożonej budowy oraz dla budowy z wykorzystaniem Kubernetes (tj. budowy na runnerach w Kubernetes, jak to ma miejsce w kaniko).

Więc jeśli gdzieś masz kilka Dockerfile'ów... spróbuj werf!

P.S. Lista dokumentów na ten temat

Czytaj także na naszym blogu: „werf — nasze narzędzie do CI/CD w Kubernetes (przegląd i wideo wykładu)».

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster