Como usar o Docker Buildx Bake para criar pipelines de construção de imagens complexas
Publicados: 2022-08-10 O grupo de comandos docker buildx
usa o BuildKit para expor recursos avançados de criação de imagens. As compilações preparadas são um recurso de alto nível que pode ser usado para definir pipelines de compilação automatizados. Eles permitem que você produza várias imagens a partir de uma única operação de compilação.
Os fluxos de trabalho preparados são úteis quando você deseja publicar diferentes variantes de suas imagens ou criar vários projetos vinculados em paralelo. Neste artigo, abordaremos os principais recursos do docker buildx bake
e como você pode usá-los para simplificar compilações complexas.
Começando
O comando docker buildx bake
executa vários "destinos" de compilação, cada um produzindo uma imagem de contêiner. Os alvos são executados em paralelo sempre que possível para maximizar o desempenho. Os destinos também podem fazer referência direta aos predecessores para criar pipelines sequenciais.
Os destinos de compilação podem ser definidos usando vários mecanismos diferentes, incluindo arquivos existentes do Docker Compose. O Buildx construirá automaticamente todas as imagens identificadas no arquivo.
Recursos mais avançados são expostos quando você lista destinos de compilação em arquivos JSON ou HCL. Essas variáveis de suporte, funções e interpolação de valor para personalizar suas compilações.
O comando buildx bake
procura os seguintes arquivos em ordem:
-
docker-compose.yml
-
docker-compose.yaml
-
docker-bake.json
-
docker-bake.override.json
-
docker-bake.hcl
-
docker-bake.override.hcl
Você pode especificar um arquivo diferente com o sinalizador de comando -f
.
Construir alvos
Os destinos de compilação encapsulam toda a configuração relacionada à sua compilação. Eles incluem detalhes como
- o caminho para o Dockerfile para construir
- construir caminhos de contexto, definindo o conteúdo disponível em seu Dockerfile
- tags e rótulos para anexar às imagens de saída
- as plataformas para produzir imagens.
Uma lista completa de campos de configuração suportados está disponível na documentação. Anteriormente, você pode ter fornecido essas configurações como sinalizadores de linha de comando para docker buildx build
(ou até mesmo docker build
), forçando você a lembrar os valores corretos a cada vez. Com buildx bake
, você pode usar os mesmos valores de maneira confiável, definindo-os em seu arquivo assado com controle de versão.
Aqui está um exemplo simples de um comando docker-bake.hcl
que define um único destino de compilação:
target "default" { dockerfile = "app/Dockerfile" contexts = { app = "app/src" shared = "shared-components/src" } tags = ["my-app:latest", "docker.io/my-org/my-app:latest"] }
A execução docker buildx bake
com este arquivo bake carregará o app/Dockerfile
Dockerfile do seu diretório de trabalho. Ele terá acesso aos diretórios app/src
e shared-components/src
como contextos de construção. A imagem produzida receberá duas tags.
O destino default
é criado automaticamente quando você executa o docker buildx bake
. Você também pode definir destinos nomeados que podem ser criados sob demanda:
target "app" { // ... }
$ docker buildx bake app
Usando vários destinos
Você pode construir outra imagem simultaneamente definindo-a como um novo alvo dentro do seu arquivo bake:
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"] }
Essas imagens podem ser criadas simultaneamente porque estão aninhadas em um grupo. As imagens da api
e app
serão compiladas em paralelo sempre que você executar o comando docker buildx bake
, pois o grupo default
é selecionado automaticamente. Você pode usar grupos nomeados de maneira semelhante ao exemplo de destinos nomeados acima.
Criar herança de destino
Os destinos de compilação podem herdar uns dos outros para reutilizar a configuração. Um cenário em que isso pode ser útil diz respeito a imagens que precisam ser personalizadas para diferentes ambientes. Você pode querer adicionar arquivos de configuração extras às variantes de imagem destinadas ao uso em desenvolvimento. Aqui está um docker-bake.hcl
que demonstra esse modelo:
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"] }
O destino backend-dev
herda todas as propriedades do destino backend
-end, mas substitui o contexto de config
e aplica uma tag diferente.
Você pode visualizar a estrutura do arquivo mesclado executando o comando bake
com o sinalizador --print
:
$ docker buildx bake --print ... "backend-dev": { "context": ".", "contexts": { "config": "api/config-dev", "src": "api/src" }, "dockerfile": "backend/Dockerfile", "tags": [ "backend:dev" ] } ...
Usando um alvo anterior como uma imagem de base
Às vezes, você pode querer que um destino de compilação use a imagem criada por um destino anterior como sua própria base. Essa é uma alternativa para compilações de vários estágios que podem ser usadas quando seus Dockerfiles dependem uns dos outros, mas não podem ser mesclados, talvez porque existam em projetos diferentes.
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"] }
O exemplo primeiro cria o destino org-base-image
. Isso pode conter alguns utilitários comuns às cargas de trabalho em contêiner da sua organização. O destino da api
é então compilado com a saída do destino org-base-image
acessível como o build-context base
. O API Dockerfile agora pode fazer referência ao conteúdo dentro da imagem base:
COPY --from=base /utilities/example /usr/bin/example-utility
Este é um padrão poderoso que permite criar links de dependência entre imagens enquanto mantém Dockerfiles separados.
Substituindo propriedades de destinos no tempo de compilação
O comando docker buildx bake
permite que você substitua as propriedades de seus destinos ao executar sua compilação:
$ docker buildx bake --set api.dockerfile="api/Dockerfile-dev"
Este exemplo altera o Dockerfile do destino da api
. O curinga *
é suportado ao identificar o destino a ser alterado. *
por si só seleciona todos os alvos enquanto api*
modificará todos os alvos que começam com api
.
Configurando Variáveis
Os arquivos HCL podem definir variáveis que você pode fazer referência em seus destinos de compilação. use um bloco variable
para configurá-los:
variable "TAG" { default = "latest" } group "default" { targets = ["app"] } target "app" { dockerfile = "src/Dockerfile" tags = ["my-app:${TAG}"] }
A execução docker buildx bake
com essa configuração marcará o destino do app
como my-app:latest
. Você pode alterar o valor da variável TAG
definindo uma variável de ambiente antes de executar o comando:
$ TAG=v1 docker buildx bake
Você pode usar todos os recursos de interpolação e comparação de variáveis da linguagem HCL para tornar seus destinos de compilação reutilizáveis. As funções também estão disponíveis para analisar e transformar seus valores.
Resumo
As compilações Baked Buildx permitem encapsular a configuração de compilação da imagem como “destinos” definidos em um arquivo. Quando você executa buildx bake
, as imagens de todos os destinos referenciados são criadas em paralelo.
Os alvos podem herdar e depender uns dos outros. Você também pode usar variáveis e funções para criar pipelines de compilação altamente complexos e configuráveis.
O comando docker buildx bake
é uma operação de alto nível que não é necessária em todos os fluxos de trabalho. Você não precisa usá-lo ao criar imagens simples sem dependências entre projetos. O uso do docker compose build
é uma alternativa melhor para a maioria dos casos de uso que mantém a configuração do build no arquivo docker-compose.yml
. Mudar para compilações preparadas deve ser considerado quando você estiver compilando muitas imagens simultaneamente usando diferentes variáveis, plataformas, contextos de compilação e substituições de configuração.