Table of Contents
O desafio de containers entre plataformas
Os recipientes docker prometem portabilidade de gravação once-run-anywhere, mas a realidade é mais nuances quando seus alvos de implantação abrangem hosts Windows e Linux. Cada família de sistemas operacionais expõe interfaces de kernel fundamentalmente diferentes: os recipientes Linux dependem de cgroups, namespaces e sistemas de arquivos Ext4, enquanto os recipientes Windows exigem o kernel do Windows NT, o isolamento Hyper-V e volumes NTFS ou ReFS. Uma imagem construída em uma base Ubuntu irá falhar instantaneamente em um host do Windows Server, e vice-versa, a menos que você desenhe explicitamente a compatibilidade entre plataformas.
Esta incompatibilidade surge porque uma imagem de contentor não é uma máquina totalmente virtualizada. Partilha o kernel da máquina. Um contentor Linux usa o kernel Linux da máquina; um contentor Windows usa o kernel da máquina. Nenhuma camada de emulação ou tradução é fornecida por omissão. Para as organizações que gerem infra-estruturas híbridas, isto cria uma necessidade urgente de uma abordagem disciplinada e assistida por ferramentas para construir e distribuir imagens que funcionem em ambos os ecossistemas.
Os operadores de frota e engenheiros de plataforma devem adotar estratégias que produzam imagens separadas por plataforma ou alavancam os recursos manifestos de multiarquitetura da Docker para apresentar uma única referência de imagem que resolva a variante correta para cada host. A escolha depende do seu modelo de implantação, suporte de registro e maturidade CI/CD.
Arquitetura do Windows vs. Imagens Linux
Acoplamento de Kernel e Seleção de Imagem Base
Cada imagem do Docker começa a partir de uma imagem base que é baseada em Linux (por exemplo, , , ) ou Windows (por exemplo, , ). A imagem base determina o ambiente de execução e o conjunto de bibliotecas do sistema disponíveis. As imagens Linux podem ser tão pequenas quanto 5 MB (Alpina), enquanto as imagens do Windows Server Core começam em torno de 1,5 GB e o Servidor Nano em torno de 200 MB. Esta disparidade de tamanho tem implicações operacionais para tempos de extração de imagens, uso de disco e custos de armazenamento de registro.
Os recipientes do Windows também têm uma ligação mais rigorosa: uma imagem do recipiente do Windows construída para uma compilação do sistema operacional host (por exemplo, 20H2) pode não ser executada numa compilação diferente (por exemplo, 21H2). A Microsoft atenua isto com o conceito de ] isolamento do processo vs. isolamento do Hyper-V[, mas a imagem em si ainda deve corresponder à versão do sistema operacional host. Os recipientes do Linux são mais indulgentes porque as APIs do kernel Linux são largamente compatíveis com versões menores.
Sistema de Ficheiros e Permissões
As imagens Linux usam permissões POSIX (usuário, grupo, outros) e caminhos de arquivos sensíveis a maiúsculas. As imagens Windows dependem de ACLs (Access Control Lists) e caminhos insensíveis a minúsculas. Executar uma imagem Linux com código que espera o tratamento de arquivos sensíveis a maiúsculas em uma máquina Windows (mesmo em um recipiente) pode levar a erros sutis. Por outro lado, caminhos com backslashes ou letras de unidade (por exemplo, ]) não irão resolver em um recipiente Linux. Qualquer projeto de plataforma cruzada deve garantir que seu código de aplicação e arquivos de configuração usem construções de caminho diagnóstico de plataforma ou que você injecte a convenção de caminho correta por SO alvo.
Imagens de arquitetura múltipla com Docker Buildx
Como Funciona o Buildx
O Docker Buildx é a maneira recomendada para criar imagens que podem ser executadas em várias plataformas a partir de uma única invocação de compilação. Ele usa emulação baseada em QEMU (para a compilação cruzada Linux-on-Linux) ou construtores nativos em nós separados para compilar a imagem para cada arquitetura de destino. Para as compilações de plataforma cruzada Windows e Linux, você normalmente precisa de nós nativos de compilação Windows e Linux, porque o QEMU não pode emular o kernel do Windows.
O Buildx produz um manifesto multi-arquitetura (também chamado de ] lista de Maiores ou manifesto de Gordura[) que referencia uma ou mais imagens, cada uma com a sua plataforma. Quando um usuário roda em uma máquina Windows, o Docker seleciona automaticamente a variante Windows do manifesto. Em uma máquina Linux, a variante Linux é selecionada. Não é necessário mudar de tags manuais.
Configurar um Construtor Buildx para a Plataforma Cross
Para criar uma imagem multi-arquitetura que inclua variantes Linux e Windows, você deve registrar um construtor que possa acessar tanto um host Linux quanto um host Windows. Um padrão comum é usar um nó remoto do Windows como driver de compilação:
Uma vez que o construtor está configurado, você pode construir e empurrar o manifesto em um passo:
A bandeira empurra automaticamente as imagens individuais e a lista de manifestos para o registro. Não são necessários comandos adicionais de criação de manifestos.
Limitações e Techteds
- A compilação cruzada do Windows-on-Linux não é possível porque você não pode usar o QEMU para emular o kernel do Windows. Você deve ter um nó de compilação do Windows nativo acessível ao driver Buildx.
- O suporte ao registo deve incluir listas de manifestos . Os registos mais importantes (Docker Hub, AWS ECR, Azure ACR, GitHub Container Registry) suportam- nos. Alguns registos privados podem exigir que verifique a compatibilidade.
- O cache de camadas é por plataforma. O cache construído em um nó Linux não se aplica ao compilador Windows. Planeje etapas de CI separadas ou use um local de cache compartilhado que respeite a plataforma.
- Tag imutability: Depois de carregar numa lista de manifestos, não poderá modificá- la sem reprimir todas as imagens referenciadas. Utilize sempre uma nova etiqueta ou um esquema de versão imutável se necessitar de voltar.
Desenhando arquivos de Docker para Cross-Platform
Passos Condicionais com Compilações de Multi-Stage
Em vez de manter dois arquivos Docker completamente separados, você pode usar argumentos de compilação e builds de múltiplos estágios para lidar com diferenças de plataforma em um único arquivo. As variáveis e são automaticamente definidas pelo Buildx quando você especificar a bandeira :
ARG BASE_IMAGE
FROM ${BASE_IMAGE} AS base
FROM base AS install-linux
RUN apt-get update && apt-get install -y libfoo
FROM base AS install-windows
RUN powershell -Command Install-Package -Name Foo
FROM install-${TARGETOS} AS final
COPY app /app
CMD ["/app/start"]
Neste padrão, resolve-se para ou , e o estágio seleciona o passo de instalação apropriado. Você também pode usar na linha para fixar etapas específicas para Linux ou Windows, embora isso exija arquivos Docker separados se você precisar de imagens de base completamente diferentes.
Variáveis de ambiente e injeção de configuração
Use variáveis de ambiente para abstrair valores específicos de plataforma, como os caminhos de arquivos, finais de linha ou nomes de comandos. No seu arquivo Docker, defina padrões que sejam conscientes de plataforma:
ARG TARGETOS
ENV CONFIG_DIR=/etc/myapp
ENV CONFIG_DIR=C:\\ProgramData\\MyApp
No entanto, tenha cuidado: o exemplo acima é ilustrativo, mas não pode funcionar como está, porque a diretiva é avaliada em tempo de compilação, mas o arg está disponível em tempo de compilação por plataforma. Você pode usar um "truck shell" com um script de plataforma-condicional ou um modelo de tempo de compilação. Uma abordagem mais robusta é injetar diretórios de configuração específicos de plataforma através de um ou Kubernetes ConfigMap por tipo de nó, em vez de assá- lo na imagem.
Lidando com Terminações de Linha e Bits Executáveis
Linux espera que os finals de linha LF em scripts de shell e arquivos de configuração; Windows usa CRLF. Quando você verificar os arquivos em um repositório Git, defina para armazenar scripts como LF e converter na saída apenas para hosts Windows. No arquivo Docker, marque explicitamente scripts de ponto de entrada como executáveis com (apenas Linux) ou use uma diretiva que funciona de forma idêntica em ambas as plataformas (requer Docker BuildKit).
Integração CI/CD Pipeline
Matriz Constrói para cada plataforma
Em Acções GitHub, GitLab CI ou Azure Pipelines, use uma estratégia de matriz para construir e testar a imagem em conjuntos de corredores Linux e Windows separadamente. Depois de cada compilação, empurre a imagem específica da plataforma para o registro com uma tag que inclui o sufixo da plataforma (por exemplo, , ). O passo final é uma tarefa que funde as duas imagens numa única lista de manifestos.
Exemplo GitHub Actions Workflow (Simplificado)
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
include:
- os: ubuntu-latest
platform: linux/amd64
- os: windows-latest
platform: windows/amd64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Build and push
uses: docker/build-push-action@v5
with:
platforms: ${{ matrix.platform }}
tags: myapp:${{ matrix.platform }}-${{ github.sha }}
push: true
manifest:
needs: build
runs-on: ubuntu-latest
steps:
- uses: docker/setup-buildx-action@v3
- name: Create manifest list
run: |
docker buildx imagetools create \
-t myregistry.io/myapp:latest \
myregistry.io/myapp:linux-amd64-${{ github.sha }} \
myregistry.io/myapp:windows-amd64-${{ github.sha }}
Testes em ambas as plataformas
Integrar testes de integração específicos de plataforma na mesma matriz de compilação. Por exemplo, depois de construir a imagem do Windows em um corredor do Windows, execute um teste de fumaça que verifique o aplicativo inicia e responde na porta esperada. Para Linux, faça o mesmo. Somente se ambos os conjuntos de testes passarem, a criação manifesta deve prosseguir. Isto impede que uma imagem do Windows quebrada seja mesclada em uma tag "multi-arch" que os consumidores do Linux esperam que funcione.
Dica: Use para forçar uma variante de plataforma específica durante os testes locais. Isto é inestimável quando você só tem uma estação de trabalho Linux, mas quer verificar a estrutura manifesta antes de cometer.
Depurando Problemas de Plataformas Cruzadas
Modos de Falha Comum
- Base de erro de imagem: A versão do Windows Server Core (por exemplo, ltsc2022 vs. ltsc2019) não corresponde à versão do sistema operacional host. Sempre afixa uma etiqueta de lançamento específica do Windows e coordena com a sua equipe de infraestrutura.
- Limites de memória e parâmetros do kernel: Os recipientes do Windows podem exigir isolamento Hyper-V para fazer cumprir os limites de memória, enquanto os recipientes Linux podem usar CFS (Completely Fair Scheduler). Se a sua aplicação espera páginas enormes ou configurações específicas de sysctl, são apenas Linux.
- Diferenças de trabalho em rede: Os recipientes Windows usam um switch baseado em NAT por padrão e a ligação de portas se comporta de forma diferente. não é suportada no Windows. Certifique-se de que seu aplicativo não depende de rede host a menos que você esteja no Linux.
- File locking and signs: Windows não suporta sinais POSIX da mesma forma que o Linux faz. Enviar um SIGTERM para um processo dentro de um recipiente Windows não pode desencadear desligamento gracioso. Projete seu aplicativo para lidar com (Windows) como um manipulador de sinal.
Ferramentas de registo e introspecção
Ao depurar uma questão de plataforma cruzada, use para verificar o SO e a arquitetura da imagem. Olhe para os campos e sob ]:
Se a plataforma estiver ausente ou mostrar apenas uma variante, a imagem não é um manifesto de multi-arquitetura. Para listar todas as plataformas em um manifesto, use:
Este comando mostra cada entrada de plataforma e sua digest. Se você ver apenas uma entrada, o passo de criação manifesto foi incompleto ou a compilação não se destinava a ambas as famílias do sistema operacional.
Padrões e Padrões do Mundo Real
Padrão: Usando o Ecrã de Docker para Desenvolvimento Local
O Docker Desktop no Windows pode alternar entre os modos de Linux e o Windows container, mas não pode executar ambos simultaneamente. Para o desenvolvimento de plataformas cruzadas, use construtores remotos separados ou máquinas virtuais. A capacidade do Docker Desktop de executar os containers Linux nativamente (via WSL 2) reduziu a necessidade de recipientes Windows em estações de trabalho de desenvolvedores, mas você ainda precisa de containers Windows para testar a integração de recursos de imagem somente do Windows.
Padrão: Alinhamento LTS para imagens do Windows
A Microsoft lança uma nova versão do Servidor de Longo Prazo (LTSC) do Windows Server aproximadamente a cada dois a três anos. Cada versão do LTSC tem uma imagem base correspondente do recipiente. Se a sua imagem do recipiente do Windows se destina ao ltsc2022, você deve compilá- la numa máquina do ltsc2022 e executá- la em máquinas do ltsc2022. Não há garantia de compatibilidade posterior. Planeje a sua cadência de atualização para se alinhar com o ciclo de lançamento da Microsoft. Para o Linux, esta restrição é muito mais solta, mas ainda vale a pena notar: uma imagem construída num kernel muito antigo () pode ser executada em kernels mais recentes, mas uma imagem construída com novas chamadas de sistema dependentes do kernel (por exemplo, )) irá falhar nas máquinas mais antigas.
Pitfall: Ignorando o ARM64
Enquanto o artigo foca no Windows e Linux, o futuro da computação é heterogêneo: AWS Graviton, Azure Ampere, Apple Silicon e Raspberry Pi clusters todos rodam Linux ARM64. Se você estiver construindo uma imagem de multi-arquitetura para Windows e Linux, considere também incluir em seu manifesto. Muitos corredores CI agora oferecem nós Linux ARM64 nativos, e o ecossistema Docker Buildx lida perfeitamente com a compilação cruzada. Excluindo ARM64 hoje pode forçar um esforço de reengenharia caro em 12 a 18 meses.
Pitfall: Permissões do sistema de arquivos no COpy
Ao usar em um arquivo Docker, o Docker respeita os metadados do sistema de arquivos da máquina de origem. Se você copiar um script de uma máquina Linux, ele mantém seus bits executáveis e terminações de linha LF. Se você copiar de uma máquina Windows, o arquivo fica sem o bit executável e com terminações CRLF. Para garantir um comportamento consistente, use e garanta que seus arquivos de código-fonte sejam verificados no Git com terminações de linha LF. Alternativamente, adicione um passo que normaliza permissões por plataforma após o COpy.
Conclusão
Gerenciar imagens de Docker multiplataforma para compatibilidade com Windows e Linux não é mais um caso de uso exótico. É um requisito prático para qualquer frota que abrange infraestrutura heterogênea, desde clusters de Windows Server no local até Linux Kubernetes nativo na nuvem. Ao adotar o Docker Buildx para manifestos de multiarquitetura, mantendo arquivos Docker condicionais de plataforma, integrando um pipeline CI/CD baseado em matriz e testando rigorosamente em ambas as famílias de sistemas operacionais, você pode fornecer uma única tag de imagem que funciona perfeitamente em toda a sua frota.
As chaves são simples:
- Use com nós de construção nativo do Windows e Linux para produzir listas de manifestos.
- Projete seus arquivos Docker com e para evitar duplicações de código.
- Automatize builds e testes específicos da plataforma em CI; somente os manifestos de mesclagem após a passagem.
- Mantenha-se atualizado com os ciclos de lançamento LTSC da Microsoft para evitar erros de versão de imagem base.
Com estas práticas em vigor, você pode se concentrar em entregar valor de aplicação em vez de lutar com incompatibilidades de plataforma. Para leitura posterior, consulte a documentação de compilação multiplataforma , o Contêineres de Windows visão geral sobre Microsoft Learn, e o [Repositório Buildingkit[] para configuração avançada do construtor. Esses recursos irão aprofundar sua compreensão dos mecanismos subjacentes e prepará-lo para a evolução inevitável da infraestrutura containerizada.