minhas informações de contato
Correspondência[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
buildx é uma ferramenta de construção fornecida oficialmente pelo Docker. Ela pode ajudar os usuários a construir imagens Docker de forma rápida e eficiente e oferece suporte à construção de múltiplas plataformas. Usando buildx, os usuários podem construir imagens para múltiplas arquiteturas, como arquiteturas x86 e arm, em um único comando, sem ter que operar manualmente vários comandos de construção. Além disso, o buildx também oferece suporte à construção em vários estágios e ao cache do Dockerfile, o que pode melhorar muito a eficiência e a velocidade da construção da imagem.
buildx é um plug-in CLI que gerencia compilações do Docker. A camada subjacente usa BuildKit para estender os recursos de compilação do Docker.
BuildKit é um mecanismo de construção de alto desempenho fornecido oficialmente pelo Docker, que pode ser usado para substituir o mecanismo de construção original do Docker. Comparado com o mecanismo original, o BuildKit possui velocidade de construção mais rápida, maior paralelismo, menos uso de recursos e melhor segurança.
Para instalar e usar o buildx, o número da versão do Docker Engine é maior ou igual a 19.03.
O construtor oferece suporte a diferentes estratégias para a construção de imagens multiplataforma.
Se você estiver usando o Docker Desktop, o QEMU já é compatível e é a estratégia mais simples para construir imagens multiplataforma. Não requer nenhuma alteração no Dockerfile original. O BuildKit implementará a execução do programa multiplataforma por meio da função do kernel Linux binfmt_misc.
princípio de trabalho:
QEMU é um simulador de processador que pode simular diferentes arquiteturas de CPU. Podemos entendê-lo como outra forma de máquina virtual. No buildx, o QEMU é usado para executar binários para arquiteturas não nativas durante o processo de construção. Por exemplo, ao construir uma imagem ARM em um host x86, o QEMU pode simular o ambiente ARM e executar binários ARM.
binfmt_misc é um módulo do kernel Linux que permite aos usuários registrar formatos de arquivos executáveis e intérpretes correspondentes.Quando o kernel encontra um arquivo executável de formato desconhecido, binfmt_misc é usado para encontrar o interpretador associado ao formato do arquivo (QEMU neste caso) e executar o arquivo . Esta função está desativada na plataforma rk3568.
A combinação de QEMU e binfmt_misc torna possível a construção de plataforma cruzada via buildx. Isso nos permite construir imagens Docker para uma arquitetura em um host para outras arquiteturas sem precisar possuir o hardware de destino real.
Embora o Docker Desktop seja pré-configurado com suporte binfmt_misc para outras plataformas, para outras versões do Docker, pode ser necessário usar a imagem tonistiigi/binfmt para iniciar um contêiner privilegiado para suporte.
docker run --privileged --rm tonistiigi/binfmt --install all
A execução deste comando instalará programas interpretadores de diferentes arquiteturas, ou seja, o simulador qemu no diretório /usr/bin:
O módulo binfmt_misc é carregado em nosso servidor de compilação:
Docker Buildx é um recurso experimental do Docker que estende os recursos de construção do Docker, incluindo o uso de vários nós, qemu, etc. QEMU é um software de máquina virtual de código aberto que pode simular diferentes CPUs e outros hardwares, permitindo-nos construir uma imagem de outro sistema operacional em um sistema operacional.
Usar a função qemu do Docker Buildx pode nos ajudar a construir imagens Docker para várias arquiteturas diferentes (como ARM, MIPS, etc.).
A seguir está um exemplo simples que mostra como usar Docker Buildx e QEMU para construir uma imagem Docker para arquitetura ARM:
- # 创建一个新的 buildkit 实例
- docker buildx create --name mybuilder --use
-
- # 启动 buildkit 实例
- docker buildx start mybuilder
-
- # 启用 QEMU 驱动支持
- docker buildx inspect --bootstrap
-
- # 构建一个面向 ARM 架构的 Docker 镜像
- docker buildx build --platform linux/arm/v7 -t myimage:latest .
Neste exemplo,--platform
O parâmetro especifica que a plataforma de destino para a qual queremos construir é ARM v7. Desta forma, o Docker usará o QEMU para simular um ambiente ARM e construir uma imagem Docker para a arquitetura ARM na máquina com arquitetura x86.
binfmt-misc é uma função fornecida pelo kernel do Linux semelhante à associação de arquivos no Windows, mas mais poderosa do que a associação de arquivos é que ela pode não apenas julgar com base no nome do sufixo do arquivo, mas também pode ser aberta usando diferentes programas baseados no arquivo conteúdo (bytes mágicos). Um cenário de uso típico é usar o qemu para executar arquivos binários em outras plataformas de arquitetura.
Habilitar binfmt-misc
Para habilitá-lo temporariamente, use o seguinte comando:
$ sudo mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
Este método se tornará inválido após a reinicialização. Se desejar que ele tenha efeito por um longo período, você pode adicionar uma linha ao arquivo /etc/fstab:
none /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0
Você pode usar o seguinte comando para verificar se a abertura foi bem-sucedida:
- $ mount | grep binfmt_misc
- binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
- $ ls -l /proc/sys/fs/binfmt_misc
- 总用量 0
- --w------- 1 root root 0 2月 5 22:55 register
- -rw-r--r-- 1 root root 0 2月 5 22:55 status
Primeiro prepare um programa com arquitetura arm64. Após executá-lo, um erro é relatado:
bash: ./go-test:无法执行二进制文件: 可执行文件格式错误
Agora, vamos executar o comando apt install qemu-user-binfmt e, em seguida, executar o programa arm64 acima e descobrir que ele pode ser executado normalmente. Após a instalação do qemu-user-binfmt, vários arquivos serão criados no diretório /proc/sys/fs/binfmt_misc, incluindo um qemu-aarch64.
- root@ubuntu:/proc/sys/fs/binfmt_misc# cat qemu-aarch64
- enabled
- interpreter /usr/bin/qemu-aarch64-static
- flags: OC
- offset 0
- magic 7f454c460201010000000000000000000200b700
- mask ffffffffffffff00fffffffffffffffffeffffff
- root@ubuntu:/proc/sys/fs/binfmt_misc#
Este arquivo descreve o arquivo de regras:
A primeira linha habilitada indica que a regra está habilitada;
O interpretador de segunda linha /usr/bin/qemu-aarch64-static indica o uso de /usr/bin/qemu-aarch64-static para executar o arquivo binário;
A terceira linha: OC representa o sinalizador em execução, o significado específico é o seguinte:
P: significa preserve-argv, o que significa que ao chamar o simulador, os parâmetros originais (argv) serão preservados.Isto é útil para situações onde programas silenciosos precisam saber seu próprio nome (ou seja, argv[0]) em tempo de execução
O: representa offset, o que significa que antes de iniciar o simulador é necessário ler um offset do arquivo binário, e esse offset será utilizado como parâmetro do simulador.
C: significa credenciais, o que significa que o emulador será executado com o mesmo ID de usuário e ID de grupo usado pelo programa original, o que ajuda a garantir que o emulador seja executado com as mesmas permissões do programa original.
A quarta linha: offset 0 significa começar a ler o arquivo a partir do valor 0;
A quinta linha: magic 7f454c4602010100000000000000000200b700 representa o byte do módulo a ser correspondido;
O campo mágico no cabeçalho do arquivo ELF da arquitetura arm64 é o seguinte, o que significa que o sistema de arquivos binfmt_misc pode determinar qual simulador de arquitetura usar para executar o arquivo com base no campo mágico no arquivo ELF:
Abaixo estão duas arquiteturas diferentes
Arquitetura Mips: 7f454c46010201000000000000000000020008
Arquitetura arm64: 7f454c46020101000000000000000000200b700
Linha 6: máscara ffffffffffff00ffffffffffffffffffff representa a máscara de bytes, que pode ser usada para ignorar alguns bytes sem importância no arquivo.
Agora usamosestivadorO comando executa uma imagem arm64:
- $ docker run -it arm64v8/ubuntu bash
- Unable to find image 'arm64v8/ubuntu:latest' locally
- latest: Pulling from arm64v8/ubuntu
- 005e2837585d: Pull complete
- Digest: sha256:ba545858745d6307f0d1064d0d25365466f78d02f866cf4efb9e1326a4c196ca
- Status: Downloaded newer image for arm64v8/ubuntu:latest
- standard_init_linux.go:207: exec user process caused "no such file or directory"
Depois de alguma exploração, descobri que desde que eu execute o seguinte comando:apt install qemu-user-static
, então inicie o dockerrecipienteÉ normal.
A complexidade da compilação cruzada não está no Docker, mas no próprio programa. Por exemplo, os programas Go podem ser facilmente compilados de forma cruzada. Você só precisa executar as duas variáveis de ambiente GOOS e GOARCH ao construir o programa usando go build.
Para usar o buildx para construir uma imagem multiplataforma, precisamos primeiro criar um construtor, que pode ser traduzido como construtor.
Use o comando docker buildx ls para visualizar a lista de construtores:
- root@ubuntu:/proc# docker buildx ls
- NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS
- mybuild * docker-container
- mybuild0 unix:///var/run/docker.sock running linux/arm64*, linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/386
- vigilant_hugle docker-container
- vigilant_hugle0 unix:///var/run/docker.sock stopped
- default docker
- default default running linux/amd64, linux/386
O sinal * indica o construtor atualmente em uso. Quando executamos o comando docker build, estamos usando este construtor para construir a imagem. DRIVER/ENDPOINT na segunda coluna indica o driver usado. buildx oferece suporte aos seguintes drivers:
Como o construtor padrão que usa o driver docker não suporta a construção de imagens de plataforma cruzada usando um único comando (o parâmetro --platform do construtor padrão aceita apenas um único valor), precisamos criar um novo construtor usando o driver docker-container .
A sintaxe do comando é a seguinte:
$ docker buildx create --name=<builder-name> --driver=<driver> --driver-opt=<driver-options>
O significado dos parâmetros é o seguinte;
--name: Nome construído, obrigatório.
--driver: Driver do construtor, o padrão é docker-container.
--driver-opt: opções de driver. Por exemplo, a opção --driver-opt=image=moby/buildkit:v0.11.3 pode instalar a versão especificada do BuildKit.
Podemos criar um novo construtor usando o seguinte comando:
- $ docker buildx create --name mybuilder
- mybuilder
Verifique a lista de construtores novamente:
- $ docker buildx ls
- NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
- mybuilder * docker-container
- mybuilder0 unix:///var/run/docker.sock inactive
- default docker
- default default running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
- desktop-linux docker
- desktop-linux desktop-linux running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
Você pode descobrir que a compilação selecionada foi alternada para Mybuilder. Se não estiver selecionado, você precisará usar manualmente o comando docker buildx use mybuilder para alternar o construtor.
Nosso mybuilder recém-criado está atualmente inativo e precisa ser iniciado antes de poder ser usado.
- $ docker buildx inspect --bootstrap mybuilder
- [+] Building 16.8s (1/1) FINISHED
- => [internal] booting buildkit 16.8s
- => => pulling image moby/buildkit:buildx-stable-1 16.1s
- => => creating container buildx_buildkit_mybuilder0 0.7s
- Name: mybuilder
- Driver: docker-container
-
- Nodes:
- Name: mybuilder0
- Endpoint: unix:///var/run/docker.sock
- Status: running
- Buildkit: v0.9.3
- Platforms: linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
O subcomando inspecionar é usado para verificar o status da construção. Use o parâmetro --bootstrap para iniciar o construtor mybuilder. Verifique a lista do construtor novamente.
- $ docker buildx ls
- NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
- mybuilder * docker-container
- mybuilder0 unix:///var/run/docker.sock running v0.9.3 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
- default docker
- default default running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
- desktop-linux docker
- desktop-linux desktop-linux running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
O valor exibido na coluna PLATAFORMAS
linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6 são suportados pelo construtor atual Todos plataformas.
Agora use o comando docker ps para ver se o contêiner BuildKit correspondente ao construtor mybuilder foi iniciado.
- $ docker ps
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- b8887f253d41 moby/buildkit:buildx-stable-1 "buildkitd" 4 minutes ago Up 4 minutes buildx_buildkit_mybuilder0
Este contêiner é usado para nos ajudar na construção de imagens multiplataforma. Não o exclua manualmente.
$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go .
A sintaxe do docker buildx build é a mesma do docker build. O parâmetro --platform indica a plataforma de destino para construir a imagem, -t indica a tag da imagem. . indica que o contexto é o diretório atual.。
A única coisa que não funciona é o suporte para o parâmetro --platform O parâmetro --platform do docker build suporta apenas a passagem de informações de uma plataforma, como --platform linux/arm64, o que significa que uma única imagem de plataforma pode. ser construído por vez.
Usar docker buildx build para construir uma imagem suporta a transmissão de informações de múltiplas plataformas ao mesmo tempo, separadas por vírgulas em inglês, realizando assim a função de construir múltiplas imagens de plataforma cruzada com apenas um comando.
Após executar o comando acima, receberemos um aviso:
WARNING: No output specified with docker-container driver. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load
Este aviso nos lembra que não especificamos uma saída para o driver docker-container. Os resultados gerados serão mantidos apenas no cache de construção. Use --push para enviar a imagem para o repositório remoto do Docker Hub e use --load. para salvar a imagem localmente.
Isso ocorre porque nosso mybuilder recém-criado inicia um contêiner para executar o BuildKit. Ele não pode enviar diretamente a imagem de plataforma cruzada construída para a máquina local ou enviá-la para o remoto.
Podemos tentar especificar --load para salvar a imagem no host local.
- $ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go . --load
- [+] Building 0.0s (0/0)
- ERROR: docker exporter does not currently support exporting manifest lists
O resultado será um log de erros. Parece que ele não suporta a exportação de imagens de plataforma cruzada para o local. Na verdade, isso ocorre porque vários --platforms são passados para esta plataforma. máquina.
Então só podemos enviar a imagem de plataforma cruzada para o warehouse remoto por meio do parâmetro --push. No entanto, antes de fazer isso, você precisa usar o docker login para concluir o login.
$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go . --push
Agora faça login no Docker Hub e você poderá ver a imagem de plataforma cruzada enviada.
Também podemos usar o imagestools para verificar as informações do manifesto da imagem multiplataforma. Este comando só pode ser usado para obter informações da imagem no warehouse e as imagens locais não podem ser visualizadas.
- $ docker buildx imagetools inspect jianghushinian/hello-go
- Name: docker.io/jianghushinian/hello-go:latest
- MediaType: application/vnd.docker.distribution.manifest.list.v2+json
- Digest: sha256:51199dadfc55b23d6ab5cfd2d67e38edd513a707273b1b8b554985ff562104db
-
- Manifests:
- Name: docker.io/jianghushinian/hello-go:latest@sha256:8032a6f23f3bd3050852e77b6e4a4d0a705dfd710fb63bc4c3dc9d5e01c8e9a6
- MediaType: application/vnd.docker.distribution.manifest.v2+json
- Platform: linux/arm64
-
- Name: docker.io/jianghushinian/hello-go:latest@sha256:fd46fd7e93c7deef5ad8496c2cf08c266bac42ac77f1e444e83d4f79d58441ba
- MediaType: application/vnd.docker.distribution.manifest.v2+json
- Platform: linux/amd64
Como você pode ver, esta imagem de plataforma cruzada contém imagens de duas plataformas de destino, nomeadamente linux/arm64 e linux/amd64.