Instalar Ferramentas de Build em um contêiner

É possível instalar as Ferramentas de Build do Visual Studio em um contêiner do Windows para oferecer suporte a fluxos de trabalho de CI e CD (integração contínua e entrega contínua). Este artigo orienta sobre quais alterações de configuração do Docker são necessárias, bem como quais cargas de trabalho e componentes podem ser instalados em um contêiner.

Os contêineres são uma ótima maneira de empacotar um sistema de build consistente e podem ser usados não somente em um ambiente de servidor CI/CD, mas também em ambientes de desenvolvimento. Por exemplo, é possível pode montar o código-fonte em um contêiner a ser criado por um ambiente personalizado e, ao mesmo tempo, continuar a usar o Visual Studio ou outras ferramentas para escrever o código. Caso o fluxo de trabalho CI/CD use a mesma imagem de contêiner, fique tranquilo, o código será compilado de forma consistente. Também é possível usar os contêineres para obter consistência em runtime, o que é comum em microsserviços que usam vários contêineres com um sistema de orquestração, mas está fora do escopo deste artigo.

Se as Ferramentas de Build do Visual Studio não têm o que você precisa para compilar o código-fonte, estas etapas podem ser usadas em outros produtos do Visual Studio. Observe, no entanto, que os contêineres do Windows não dão suporte a uma interface do usuário interativa, portanto, todos os comandos devem ser automatizados.

Antes de começar

É esperada alguma familiaridade com o Docker abaixo. Se você ainda não estiver familiarizado com a execução do Docker no Windows, leia como instalar e configurar o mecanismo do Docker no Windows.

A imagem de base abaixo é uma amostra e pode não funcionar no seu sistema. Leia Compatibilidade da versão do contêiner do Windows para determinar qual imagem de base você deve usar para o seu ambiente.

Criar e compilar o Dockerfile

Salve o Dockerfile de exemplo a seguir em um novo arquivo no disco. Se o nome do arquivo é simplesmente "Dockerfile", ele será reconhecido por padrão.

Aviso

Este Dockerfile de exemplo exclui apenas SDKs do Windows anteriores que não podem ser instalados em contêineres. As versões anteriores causam uma falha no comando de build.

  1. Abra um prompt de comando.

  2. Crie um novo diretório (recomendado):

    mkdir C:\BuildTools
    
  3. Altere os diretórios para este novo diretório:

    cd C:\BuildTools
    
  4. Salve o conteúdo a seguir em C:\BuildTools\Dockerfile.

    # escape=`
    
    # Use the latest Windows Server Core 2019 image.
    FROM mcr.microsoft.com/windows/servercore:ltsc2019
    
    # Restore the default Windows shell for correct batch processing.
    SHELL ["cmd", "/S", "/C"]
    
    RUN `
        # Download the Build Tools bootstrapper.
        curl -SL --output vs_buildtools.exe https://aka.ms/vs/16/release/vs_buildtools.exe `
        `
        # Install Build Tools with the Microsoft.VisualStudio.Workload.AzureBuildTools workload, excluding workloads and components with known issues.
        && (start /w vs_buildtools.exe --quiet --wait --norestart --nocache `
            --installPath "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\BuildTools" `
            --add Microsoft.VisualStudio.Workload.AzureBuildTools `
            --remove Microsoft.VisualStudio.Component.Windows10SDK.10240 `
            --remove Microsoft.VisualStudio.Component.Windows10SDK.10586 `
            --remove Microsoft.VisualStudio.Component.Windows10SDK.14393 `
            --remove Microsoft.VisualStudio.Component.Windows81SDK `
            || IF "%ERRORLEVEL%"=="3010" EXIT 0) `
        `
        # Cleanup
        && del /q vs_buildtools.exe
    
    # Define the entry point for the docker container.
    # This entry point starts the developer command prompt and launches the PowerShell shell.
    ENTRYPOINT ["C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\Common7\\Tools\\VsDevCmd.bat", "&&", "powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]
    

    Dica

    Para atingir 64 bits, especifique a opção -arch=amd64 no comando ENTRYPOINT para iniciar o Prompt de Comando do Desenvolvedor para Visual Studio (VSDevCmd.bat).

    Por exemplo: ENTRYPOINT ["C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\Common7\\Tools\\VsDevCmd.bat", "-arch=amd64", "&&", "powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]

    Aviso

    Se você basear sua imagem diretamente no microsoft/windowsservercore, o .NET Framework poderá não ser instalado corretamente e nenhum erro de instalação será indicado. Código gerenciado não poderá ser executado depois que a instalação for concluída. Em vez disso, baseie sua imagem em microsoft/dotnet-framework:4.8] ou posterior. As imagens marcadas com a versão 4.8 ou posterior também podem usar o PowerShell como o SHELL padrão, o que causará uma falha nas instruções RUN e ENTRYPOINT.

    Confira Compatibilidade de versão do contêiner do Windows para ver quais versões do sistema operacional de contêiner têm suporte em quais versões do sistema operacional host e solucionar problemas de contêineres do Windows e das Ferramentas de Build para problemas conhecidos.

    # escape=`
    
    # Use the latest Windows Server Core 2022 image.
    FROM mcr.microsoft.com/windows/servercore:ltsc2022
    
    # Restore the default Windows shell for correct batch processing.
    SHELL ["cmd", "/S", "/C"]
    
    RUN `
        # Download the Build Tools bootstrapper.
        curl -SL --output vs_buildtools.exe https://aka.ms/vs/17/release/vs_buildtools.exe `
        `
        # Install Build Tools with the Microsoft.VisualStudio.Workload.AzureBuildTools workload, excluding workloads and components with known issues.
        && (start /w vs_buildtools.exe --quiet --wait --norestart --nocache `
            --installPath "%ProgramFiles(x86)%\Microsoft Visual Studio\2022\BuildTools" `
            --add Microsoft.VisualStudio.Workload.AzureBuildTools `
            --remove Microsoft.VisualStudio.Component.Windows10SDK.10240 `
            --remove Microsoft.VisualStudio.Component.Windows10SDK.10586 `
            --remove Microsoft.VisualStudio.Component.Windows10SDK.14393 `
            --remove Microsoft.VisualStudio.Component.Windows81SDK `
            || IF "%ERRORLEVEL%"=="3010" EXIT 0) `
        `
        # Cleanup
        && del /q vs_buildtools.exe
    
    # Define the entry point for the docker container.
    # This entry point starts the developer command prompt and launches the PowerShell shell.
    ENTRYPOINT ["C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\Common7\\Tools\\VsDevCmd.bat", "&&", "powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]
    

    Dica

    Para atingir 64 bits, especifique a opção -arch=amd64 no comando ENTRYPOINT para iniciar o Prompt de Comando do Desenvolvedor para Visual Studio (VSDevCmd.bat).

    Por exemplo: ENTRYPOINT ["C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\Common7\\Tools\\VsDevCmd.bat", "-arch=amd64", "&&", "powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]

    Aviso

    Se você basear sua imagem diretamente no microsoft/windowsservercore, o .NET Framework poderá não ser instalado corretamente e nenhum erro de instalação será indicado. Código gerenciado não poderá ser executado depois que a instalação for concluída. Em vez disso, baseie a imagem no microsoft/dotnet-framework:4.8 ou posterior. As imagens marcadas com a versão 4.8 ou posterior também podem usar o PowerShell como o SHELL padrão, o que causará uma falha nas instruções RUN e ENTRYPOINT.

    Confira Compatibilidade de versão do contêiner do Windows para ver quais versões do sistema operacional de contêiner têm suporte em quais versões do sistema operacional host e solucionar problemas de contêineres do Windows e das Ferramentas de Build para problemas conhecidos.

    Observação

    O código de erro 3010 é usado para indicar o êxito com uma reinicialização necessária; confira mensagens de erro MsiExec.exe para obter mais informações.

  5. Execute o seguinte comando nesse diretório.

    docker build -t buildtools2019:latest -m 2GB .
    

    Este comando cria o Dockerfile no diretório atual usando 2 GB de memória. O padrão de 1 GB não é suficiente quando algumas cargas de trabalho são instaladas; no entanto, você pode ser capaz de criar com apenas 1 GB de memória, dependendo de seus requisitos de build.

    A imagem final recebe a marca buildtools2019:latest para que você possa executá-la facilmente em um contêiner como buildtools2019, pois a marca "mais recente" é o padrão se nenhuma marca for especificada. Caso queira utilizar uma versão específica das Ferramentas de Build do Visual Studio 2019 em um cenário mais avançado, em vez disso, é possível marcar o contêiner com um número de build específico do Visual Studio, assim como "mais recente", para que os contêineres usem uma versão específica constantemente.

    docker build -t buildtools:latest -m 2GB .
    

    Este comando cria o Dockerfile no diretório atual usando 2 GB de memória. O 1 GB padrão não é suficiente quando algumas cargas de trabalho são instaladas. No entanto, é possível compilar com apenas 1 GB de memória, de acordo com os requisitos de build.

    A imagem final contém uma marca "buildtools:latest", então, é possível executá-la facilmente em um contêiner como "buildtools", visto que a marca "mais recente" é o padrão se nenhuma marca é especificada. Caso queira utilizar uma versão específica das Ferramentas de Build do Visual Studio em um cenário mais avançado, em vez disso, é possível marcar o contêiner com um número de build específico do Visual Studio, assim como "mais recente", para que os contêineres usem uma versão específica constantemente.

Usar a imagem criada

Agora que a imagem foi criada, é possível executá-la em um contêiner para fazer builds interativos e automatizados. O exemplo usa o Prompt de Comando do Desenvolvedor, assim, PATH e outras variáveis de ambiente já estão configuradas.

  1. Abra um prompt de comando.

  2. Execute o contêiner para iniciar um ambiente do PowerShell com as variáveis de ambiente de desenvolvedor configuradas:

    docker run -it buildtools2019
    
    docker run -it buildtools
    

Para usar essa imagem no fluxo de trabalho CI/CD, publique-a no seu próprio Registro de Contêiner do Azure ou em outro registro Docker interno, assim, os servidores só precisarão efetuar pull dessa imagem.

Observação

Se o contêiner do Docker não for iniciado, provavelmente há um problema de instalação do Visual Studio. Você pode atualizar o Dockerfile para remover a etapa que chama o comando em lote do Visual Studio. Isso permite que você inicie o contêiner do Docker e leia os logs de erros de instalação.

No arquivo Dockerfile, remova os parâmetros C:\\BuildTools\\Common7\\Tools\\VsDevCmd.bat e && do comando ENTRYPOINT. O comando agora deve ser ENTRYPOINT ["powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]. Em seguida, recompile o Dockerfile e execute o comando run para acessar arquivos de contêiner. Para localizar os logs de erros de instalação, acesse o diretório $env:TEMP e localize o arquivo dd_setup_<timestamp>_errors.log.

Depois de identificar e corrigir o problema de instalação, você poderá adicionar os parâmetros && e C:\\BuildTools\\Common7\\Tools\\VsDevCmd.bat de volta ao comando ENTRYPOINT e recompilar o Dockerfile.

Para obter mais informações, confira Solucionar problemas de contêineres do Windows e das Ferramentas de Build.

Solução de problemas de contêineres do Windows e das Ferramentas de Build

Há alguns problemas ao instalar o Visual Studio em um contêiner do Docker.

Solucionar problemas de contêineres do Windows

Estes problemas conhecidos ocorrem quando as Ferramentas de Build do Visual Studio são instaladas em um contêiner do Windows.

  • Passe -m 2GB (ou mais) ao compilar a imagem. Algumas cargas de trabalho exigem mais memória que o padrão de 1 GB quando instaladas.

  • Configure o Docker para usar discos maiores que o padrão de 20 GB.

  • Passe --norestart na linha de comando. A partir dessa gravação, tentar reiniciar um contêiner do Windows dentro do contêiner retorna ERROR_TOO_MANY_OPEN_FILES para o host.

  • Se você basear sua imagem diretamente no mcr.microsoft.com/windows/servercore, o .NET Framework poderá não ser instalado corretamente e nenhum erro de instalação será indicado. Código gerenciado não poderá ser executado depois que a instalação for concluída. Em vez disso, baseie a imagem no microsoft/dotnet-framework:4.7.1 ou posterior. Por exemplo, ao compilar com o MSBuild, você poderá ver um erro semelhante ao seguinte:

    C:\BuildTools\MSBuild\15.0\bin\Roslyn\Microsoft.CSharp.Core.targets(84,5): erro MSB6003: Não foi possível executar o executável da tarefa especificado "csc.exe". Não foi possível carregar o arquivo ou assembly “System.IO.FileSystem, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ou uma de suas dependências. O sistema não pode encontrar o arquivo especificado.

Solucionar problemas de contêineres de Ferramentas de Build

Os problemas conhecidos a seguir podem ocorrer ao usar o contêiner das Ferramentas de Build. Para ver se os problemas foram corrigidos ou se há outros problemas conhecidos, acesse a Developer Community.

  • O IntelliTrace pode não funcionar em alguns cenários dentro de um contêiner.
  • Em versões mais antigas do Docker for Windows, o tamanho da imagem de contêiner padrão é de apenas 20 GB e não cabe nas Ferramentas de Criação. Siga as instruções para alterar o tamanho da imagem para 127 GB ou mais. Para confirmar um problema de espaço em disco, verifique os arquivos de log para obter mais informações. Seu arquivo vslogs\dd_setup_<timestamp>_errors.log incluirá o seguinte se você ficar sem espaço em disco:
Pre-check verification: Visual Studio needs at least 91.99 GB of disk space. Try to free up space on C:\ or change your target drive.
Pre-check verification failed with error(s) :  SizePreCheckEvaluator.