Jak używać Docker Buildx Bake do tworzenia złożonych potoków budowania obrazu

Opublikowany: 2022-08-10

Grafika przedstawiająca logo Docker

Grupa poleceń docker buildx buildx używa BuildKit do ujawniania zaawansowanych możliwości budowania obrazów. Pieczone kompilacje to funkcja wysokiego poziomu, której można używać do definiowania automatycznych potoków kompilacji. Umożliwiają tworzenie wielu obrazów z jednej operacji budowania.

Gotowe przepływy pracy są przydatne, gdy chcesz publikować różne warianty swoich obrazów lub równolegle tworzyć kilka połączonych projektów. W tym artykule omówimy kluczowe funkcje docker buildx bake i sposoby ich wykorzystania do usprawnienia złożonych kompilacji.

Pierwsze kroki

Polecenie docker buildx bake wykonuje wiele „celów” kompilacji, z których każdy tworzy obraz kontenera. Tam, gdzie to możliwe, cele działają równolegle, aby zmaksymalizować wydajność. Cele mogą również bezpośrednio odwoływać się do poprzedników, tworząc sekwencyjne potoki.

Cele kompilacji można zdefiniować przy użyciu kilku różnych mechanizmów, w tym istniejących plików Docker Compose. Buildx automatycznie zbuduje wszystkie obrazy zidentyfikowane w pliku.

Bardziej zaawansowane funkcje są ujawniane, gdy umieszczasz cele kompilacji w plikach JSON lub HCL. Obsługują one zmienne, funkcje i interpolację wartości w celu dostosowania kompilacji.

Komenda buildx bake wyszukuje następujące pliki w kolejności:

  • docker-compose.yml
  • docker-compose.yaml
  • docker-bake.json
  • docker-bake.override.json
  • docker-bake.hcl
  • docker-bake.override.hcl

Inny plik można określić za pomocą flagi polecenia -f .

Buduj cele

Cele kompilacji zawierają całą konfigurację związaną z kompilacją. Zawierają szczegóły, takie jak

  • ścieżka do pliku Dockerfile do zbudowania
  • buduj ścieżki kontekstowe, definiując zawartość dostępną w Twoim Dockerfile
  • tagi i etykiety do dołączenia do obrazów wyjściowych
  • platformy do produkcji obrazów.

Pełna lista obsługiwanych pól konfiguracyjnych jest dostępna w dokumentacji. Wcześniej mogłeś podać te ustawienia jako flagi wiersza polecenia do docker buildx build (lub nawet zwykły docker build ), zmuszając za każdym razem do zapamiętania poprawnych wartości. Dzięki buildx bake możesz niezawodnie używać tych samych wartości, definiując je w pliku pieczonym z kontrolą wersji.

Oto prosty przykład polecenia docker-bake.hcl , które definiuje pojedynczy cel kompilacji:

 target "default" { dockerfile = "app/Dockerfile" contexts = { app = "app/src" shared = "shared-components/src" } tags = ["my-app:latest", "docker.io/my-org/my-app:latest"] }

Uruchomienie docker buildx bake z tym plikiem pieczenia spowoduje załadowanie pliku app/Dockerfile z katalogu roboczego. Będzie miał dostęp do katalogów app/src i shared-components/src jako konteksty kompilacji. Wytworzony obraz otrzyma dwa znaczniki.

default cel jest budowany automatycznie po uruchomieniu docker buildx bake . Możesz także zdefiniować nazwane cele, które można zbudować na żądanie:

 target "app" { // ... }
 $ docker buildx bake app

Korzystanie z wielu celów

Możesz jednocześnie zbudować inny obraz, definiując go jako nowy cel w pliku pieczenia:

 group "default" { targets = ["app", "api"] } target "app" { dockerfile = "app/Dockerfile" contexts = { app = "app/src" shared = "shared-components/src" } tags = ["my-app:latest", "docker.io/my-org/my-app:latest"] } target "api" { dockerfile = "api/Dockerfile" contexts = { src = "api/src" } tags = ["my-api:latest", "docker.io/my-org/my-api:latest"] }

Te obrazy mogą być budowane jednocześnie, ponieważ są zagnieżdżone w grupie. Obrazy api i app będą budowane równolegle za każdym razem, gdy uruchomisz polecenie docker buildx bake , ponieważ default grupa jest wybierana automatycznie. Możesz użyć nazwanych grup podobnie jak w powyższym przykładzie nazwanych celów.

Zbuduj dziedziczenie celu

Cele kompilacji mogą dziedziczyć po sobie nawzajem, aby ponownie wykorzystać konfigurację. Jeden scenariusz, w którym może to być przydatne, dotyczy obrazów, które należy dostosować do różnych środowisk. Możesz chcieć dodać dodatkowe pliki konfiguracyjne do wariantów obrazu przeznaczonych do użytku programistycznego. Oto plik docker-bake.hcl , który demonstruje ten model:

 group "default" { targets = ["backend", "backend-dev"] } target "backend" { dockerfile = "backend/Dockerfile" contexts = { src = "api/src" config = "api/config" } tags = ["backend:latest"] } target "backend-dev" { inherits = ["backend"] contexts = { config = "api/config-dev" } tags = ["backend:dev"] }

Cel backend-dev dziedziczy wszystkie właściwości celu backend , ale zastępuje kontekst config i stosuje inny tag.

Możesz wyświetlić podgląd scalonej struktury plików, uruchamiając polecenie bake z flagą --print :

 $ docker buildx bake --print ... "backend-dev": { "context": ".", "contexts": { "config": "api/config-dev", "src": "api/src" }, "dockerfile": "backend/Dockerfile", "tags": [ "backend:dev" ] } ...

Używanie poprzedniego celu jako obrazu bazowego

Czasami możesz chcieć, aby cel kompilacji używał obrazu utworzonego przez poprzedni cel jako własną bazę. Jest to alternatywa dla wieloetapowych kompilacji, których można używać, gdy pliki Dockerfile są od siebie zależne, ale nie można ich scalać, być może dlatego, że istnieją w różnych projektach.

 group "default" { targets = ["org-base-image", "api"] } target "org-base-image" { dockerfile = "docker-base/Dockerfile" tags = ["org-base-image:latest"] } target "api" { dockerfile = "api/Dockerfile" contexts = { base = "target:org-base-image" } tags = ["api:latest"] }

Przykład najpierw kompiluje cel org-base-image . Może to zawierać niektóre narzędzia, które są wspólne dla skonteneryzowanych obciążeń Twojej organizacji. Docelowy api jest następnie budowany z danymi wyjściowymi z docelowego org-base-image dostępnym jako base kontekst kompilacji. Plik dockerowy interfejsu API może teraz odwoływać się do zawartości w obrazie podstawowym:

 COPY --from=base /utilities/example /usr/bin/example-utility

Jest to potężny wzorzec, który umożliwia tworzenie powiązań zależności między obrazami przy jednoczesnym zachowaniu oddzielnych plików Docker.

Nadpisywanie właściwości celów w czasie kompilacji

Polecenie docker buildx bake pozwala nadpisać właściwości celów podczas uruchamiania kompilacji:

 $ docker buildx bake --set api.dockerfile="api/Dockerfile-dev"

Ten przykład zmienia plik Dockerfile celu api . Symbol wieloznaczny * jest obsługiwany podczas identyfikowania celu do zmiany. * samodzielnie wybiera każdy cel, podczas gdy api* modyfikuje wszystkie cele, które zaczynają się od api .

Ustawianie zmiennych

Pliki HCL mogą definiować zmienne, do których można odwoływać się w celach kompilacji. użyj bloku variable , aby je skonfigurować:

 variable "TAG" { default = "latest" } group "default" { targets = ["app"] } target "app" { dockerfile = "src/Dockerfile" tags = ["my-app:${TAG}"] }

Uruchomienie docker buildx bake z tą konfiguracją spowoduje oznaczenie celu app jako my-app:latest . Możesz zmienić wartość zmiennej TAG , ustawiając zmienną środowiskową przed wykonaniem polecenia:

 $ TAG=v1 docker buildx bake

Możesz użyć wszystkich możliwości interpolacji i porównywania zmiennych języka HCL, aby umożliwić ponowne użycie celów kompilacji. Dostępne są również funkcje do analizowania i przekształcania wartości.

Streszczenie

Gotowe kompilacje Buildx pozwalają na hermetyzację konfiguracji kompilacji obrazu jako „celów” zdefiniowanych w pliku. Po uruchomieniu buildx bake obrazy dla wszystkich celów, do których się odwołuje, są budowane równolegle.

Cele mogą dziedziczyć od siebie i od siebie zależeć. Możesz także używać zmiennych i funkcji do tworzenia bardzo złożonych i konfigurowalnych potoków kompilacji.

Polecenie docker buildx bake to operacja wysokiego poziomu, która nie jest konieczna w każdym przepływie pracy. Nie musisz go używać podczas tworzenia prostych obrazów bez zależności między projektami. Korzystanie z docker compose build jest lepszą alternatywą dla większości przypadków użycia, która zachowuje konfigurację kompilacji w pliku docker-compose.yml . Przejście na upieczone kompilacje należy rozważyć, gdy tworzysz wiele obrazów jednocześnie przy użyciu różnych zmiennych, platform, kontekstów kompilacji i nadpisań konfiguracji.