Usando docker en varias etapas para crear imaxes de Windows

Ola a todos! Chámome Andrey e traballo como enxeñeiro de DevOps en Exness no equipo de desenvolvemento. A miña actividade principal está relacionada coa construción, implantación e soporte de aplicacións en docker baixo o sistema operativo Linux (en diante denominado SO). Non hai moito tiven unha tarefa coas mesmas actividades, pero o sistema operativo de destino do proxecto era Windows Server e un conxunto de proxectos C++. Para min, esta foi a primeira interacción estreita cos contedores docker baixo o sistema operativo Windows e, en xeral, coas aplicacións C++. Grazas a isto, tiven unha experiencia interesante e aprendín algunhas das complejidades de contener aplicacións en Windows.

Usando docker en varias etapas para crear imaxes de Windows

Neste artigo quero contarvos que dificultades tiven que afrontar e como conseguín resolvelos. Espero que isto sexa útil para os teus retos actuais e futuros. Disfruta da lectura!

Por que contedores?

A empresa dispón dunha infraestrutura existente para o orquestrador de contedores Hashicorp Nomad e os compoñentes relacionados: Consul e Vault. Polo tanto, escolleuse a contenerización de aplicacións como un método unificado para ofrecer unha solución completa. Dado que a infraestrutura do proxecto contén hosts docker coas versións do sistema operativo Windows Server Core 1803 e 1809, é necesario construír versións separadas das imaxes docker para 1803 e 1809. Na versión 1803, é importante lembrar que o número de revisión do host docker de compilación debe coincidir co número de revisión da imaxe docker base e co host onde se lanzará o contedor desta imaxe. A versión 1809 non ten tal inconveniente. Podes ler máis aquí.

Por que multietapa?

Os enxeñeiros do equipo de desenvolvemento non teñen acceso ou son moi limitados para crear hosts; non hai forma de xestionar rapidamente o conxunto de compoñentes para crear unha aplicación nestes hosts, por exemplo, instalar un conxunto de ferramentas ou carga de traballo adicional para Visual Studio. Polo tanto, tomamos a decisión de instalar todos os compoñentes necesarios para integrar a aplicación na imaxe de compilación de Docker. Se é necesario, pode cambiar rapidamente só o ficheiro docker e iniciar a canalización para crear esta imaxe.

Da teoría á acción

Nunha compilación ideal de imaxes en varias etapas de Docker, o ambiente para a creación da aplicación prepárase no mesmo script Dockerfile que a propia aplicación. Pero no noso caso, engadiuse unha ligazón intermedia, é dicir, o paso de crear previamente unha imaxe docker con todo o necesario para construír a aplicación. Isto fíxose porque quería usar a función de caché docker para reducir o tempo de instalación de todas as dependencias.

Vexamos os puntos principais do script dockerfile para crear esta imaxe.

Para crear imaxes de diferentes versións do SO, pode definir un argumento no ficheiro docker a través do cal se pasa o número de versión durante a compilación e tamén é a etiqueta da imaxe base.

Pódese atopar unha lista completa de etiquetas de imaxe de Microsoft Windows Server aquí.

ARG WINDOWS_OS_VERSION=1809
FROM mcr.microsoft.com/windows/servercore:$WINDOWS_OS_VERSION

Por defecto, os comandos das instrucións RUN dentro do dockerfile no sistema operativo Windows execútanse na consola cmd.exe. Para a comodidade de escribir scripts e ampliar a funcionalidade dos comandos utilizados, redefiniremos a consola de execución de comandos en Powershell a través da instrución SHELL.

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]

O seguinte paso é instalar o xestor de paquetes chocolatey e os paquetes necesarios:

COPY chocolatey.pkg.config .
RUN Set-ExecutionPolicy Bypass -Scope Process -Force ;
    [System.Net.ServicePointManager]::SecurityProtocol = 
    [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 ;
    $env:chocolateyUseWindowsCompression = 'true' ;
    iex ((New-Object System.Net.WebClient).DownloadString( 
      'https://chocolatey.org/install.ps1')) ;
    choco install chocolatey.pkg.config -y --ignore-detected-reboot ;
    if ( @(0, 1605, 1614, 1641, 3010) -contains $LASTEXITCODE ) { 
      refreshenv; } else { exit $LASTEXITCODE; } ;
    Remove-Item 'chocolatey.pkg.config'

Para instalar paquetes usando chocolatey, pode simplemente pasalos como unha lista, ou instalalos un a un se precisa pasar parámetros únicos para cada paquete. Na nosa situación, usamos un ficheiro de manifesto en formato XML, que contén unha lista de paquetes necesarios e os seus parámetros. O seu contido ten este aspecto:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="python" version="3.8.2"/>
  <package id="nuget.commandline" version="5.5.1"/>
  <package id="git" version="2.26.2"/>
</packages>

A continuación, instalamos o ambiente de compilación da aplicación, é dicir, MS Build Tools 2019 - esta é unha versión lixeira de Visual Studio 2019, que contén o conxunto mínimo de compoñentes necesarios para compilar código.
Para traballar plenamente co noso proxecto C++, necesitaremos compoñentes adicionais, a saber:

  • Ferramentas de carga de traballo C++
  • Conxunto de ferramentas v141
  • Windows 10 SDK (10.0.17134.0)

Pode instalar un conxunto estendido de ferramentas automaticamente mediante un ficheiro de configuración en formato JSON. Contido do ficheiro de configuración:

No sitio de documentación pódese atopar unha lista completa de compoñentes dispoñibles Microsoft Visual Studio.

{
  "version": "1.0",
  "components": [
    "Microsoft.Component.MSBuild",
    "Microsoft.VisualStudio.Workload.VCTools;includeRecommended",
    "Microsoft.VisualStudio.Component.VC.v141.x86.x64",
    "Microsoft.VisualStudio.Component.Windows10SDK.17134"
  ]
}

O dockerfile executa o script de instalación e, por comodidade, engade o camiño aos ficheiros executables das ferramentas de compilación á variable de ambiente PATH. Tamén é recomendable eliminar ficheiros e directorios innecesarios para reducir o tamaño da imaxe.

COPY buildtools.config.json .
RUN Invoke-WebRequest 'https://aka.ms/vs/16/release/vs_BuildTools.exe' 
      -OutFile '.vs_buildtools.exe' -UseBasicParsing ;
    Start-Process -FilePath '.vs_buildtools.exe' -Wait -ArgumentList 
      '--quiet --norestart --nocache --config C:buildtools.config.json' ;
    Remove-Item '.vs_buildtools.exe' ;
    Remove-Item '.buildtools.config.json' ;
    Remove-Item -Force -Recurse 
      'C:Program Files (x86)Microsoft Visual StudioInstaller' ;
    $env:PATH = 'C:Program Files (x86)Microsoft Visual Studio2019BuildToolsMSBuildCurrentBin;' + $env:PATH; 
    [Environment]::SetEnvironmentVariable('PATH', $env:PATH, 
      [EnvironmentVariableTarget]::Machine)

Nesta fase, a nosa imaxe para compilar a aplicación C++ está lista, e podemos proceder directamente á creación dunha compilación docker en varias etapas da aplicación.

Multietapa en acción

Usaremos a imaxe creada con todas as ferramentas a bordo como imaxe de construción. Como no script dockerfile anterior, engadiremos a posibilidade de especificar dinámicamente o número de versión/etiqueta de imaxe para facilitar a reutilización do código. É importante engadir unha etiqueta as builder á imaxe de montaxe nas instrucións FROM.

ARG WINDOWS_OS_VERSION=1809
FROM buildtools:$WINDOWS_OS_VERSION as builder

Agora é o momento de construír a aplicación. Aquí todo é moi sinxelo: copia o código fonte e todo o que está asociado a el e inicia o proceso de compilación.

COPY myapp .
RUN nuget restore myapp.sln ;
    msbuild myapp.sln /t:myapp /p:Configuration=Release

A etapa final da creación da imaxe final é especificar a imaxe base da aplicación, onde se localizarán todos os artefactos de compilación e os ficheiros de configuración. Para copiar ficheiros compilados desde a imaxe de conxunto intermedia, debes especificar o parámetro --from=builder nas instrucións COPY.

FROM mcr.microsoft.com/windows/servercore:$WINDOWS_OS_VERSION

COPY --from=builder C:/x64/Release/myapp/ ./
COPY ./configs ./

Agora só queda engadir as dependencias necesarias para que a nosa aplicación funcione e especificar o comando de inicio a través das instrucións ENTRYPOINT ou CMD.

Conclusión

Neste artigo, falei sobre como crear un ambiente de compilación completo para aplicacións C++ dentro dun contedor en Windows e como usar as capacidades das compilacións en varias etapas de Docker para crear imaxes completas da nosa aplicación.

Fonte: www.habr.com

Engadir un comentario