Docker multi-stage gebruiken om Windows-images te bouwen

Dag Allemaal! Mijn naam is Andrey en ik werk als DevOps engineer bij Exness in het ontwikkelteam. Mijn hoofdactiviteit heeft betrekking op het bouwen, implementeren en ondersteunen van applicaties in docker onder het Linux besturingssysteem (hierna het OS genoemd). Nog niet zo lang geleden had ik een taak met dezelfde activiteiten, maar het doelbesturingssysteem van het project was Windows Server en een reeks C++-projecten. Voor mij was dit de eerste nauwe interactie met docker-containers onder Windows OS en, in het algemeen, met C++-applicaties. Hierdoor had ik een interessante ervaring en leerde ik over enkele fijne kneepjes van het containeriseren van applicaties in Windows.

Docker multi-stage gebruiken om Windows-images te bouwen

In dit artikel wil ik je vertellen met welke moeilijkheden ik te maken kreeg en hoe ik ze heb weten op te lossen. Ik hoop dat dit nuttig is voor uw huidige en toekomstige uitdagingen. Veel plezier met lezen!

Waarom containers?

Het bedrijf beschikt over een bestaande infrastructuur voor de containerorkestrator Hashicorp Nomad en aanverwante componenten: Consul en Vault. Daarom werd gekozen voor containerisatie van applicaties als een uniforme methode voor het leveren van een complete oplossing. Omdat de projectinfrastructuur docker-hosts bevat met Windows Server Core OS-versies 1803 en 1809, is het noodzakelijk om afzonderlijke versies van docker-images voor 1803 en 1809 te bouwen. In versie 1803 is het belangrijk om te onthouden dat het revisienummer van de build-docker-host moet overeenkomen met het revisienummer van de basisdocker-image en de host waar de container van deze image wordt gelanceerd. Versie 1809 heeft zo'n nadeel niet. Je kunt meer lezen hier.

Waarom meertraps?

Ontwikkelteamingenieurs hebben geen of zeer beperkte toegang om hosts te bouwen; er is geen manier om snel de set componenten te beheren voor het bouwen van een applicatie op deze hosts, door bijvoorbeeld een extra toolset of werklast voor Visual Studio te installeren. Daarom hebben we besloten om alle componenten te installeren die nodig zijn om de applicatie in de build Docker-image te bouwen. Indien nodig kunt u snel alleen het dockerbestand wijzigen en de pijplijn starten voor het maken van deze afbeelding.

Van theorie naar actie

Bij een ideale Docker-imagebouw in meerdere fasen wordt de omgeving voor het bouwen van de applicatie voorbereid in hetzelfde Dockerfile-script als waarin de applicatie zelf is gebouwd. Maar in ons geval is er een tussenliggende link toegevoegd, namelijk de stap van het voorlopig maken van een docker-image met alles wat nodig is om de applicatie te bouwen. Dit werd gedaan omdat ik de docker-cachefunctie wilde gebruiken om de installatietijd van alle afhankelijkheden te verkorten.

Laten we eens kijken naar de belangrijkste punten van het dockerfile-script voor het maken van deze afbeelding.

Om images van verschillende besturingssysteemversies te maken, kunt u een argument definiëren in het dockerbestand waardoor het versienummer wordt doorgegeven tijdens de build, en dit is ook de tag van de basisimage.

U kunt een volledige lijst met Microsoft Windows Server-afbeeldingstags vinden hier.

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

Standaard staan ​​de opdrachten in de instructies RUN in het dockerbestand op Windows OS worden ze uitgevoerd in de cmd.exe-console. Voor het gemak van het schrijven van scripts en het uitbreiden van de functionaliteit van de gebruikte opdrachten, zullen we de console voor het uitvoeren van opdrachten in Powershell opnieuw definiëren via de instructie SHELL.

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

De volgende stap is het installeren van de chocoladepakketbeheerder en de benodigde pakketten:

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'

Om pakketten te installeren met behulp van chocolatey, kunt u ze eenvoudigweg doorgeven als een lijst, of ze één voor één installeren als u voor elk pakket unieke parameters moet doorgeven. In onze situatie hebben we een manifestbestand in XML-indeling gebruikt, dat een lijst met vereiste pakketten en hun parameters bevat. De inhoud ziet er als volgt uit:

<?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>

Vervolgens installeren we de applicatie-bouwomgeving, namelijk MS Build Tools 2019 - dit is een lichtgewicht versie van Visual Studio 2019, die de minimaal vereiste set componenten bevat voor het compileren van code.
Om volledig met ons C++-project te kunnen werken, hebben we aanvullende componenten nodig, namelijk:

  • Workload C++-tools
  • Gereedschapset v141
  • Windows 10 SDK (10.0.17134.0)

U kunt automatisch een uitgebreide set tools installeren met behulp van een configuratiebestand in JSON-indeling. Inhoud configuratiebestand:

Een volledige lijst met beschikbare componenten vindt u op de documentatiesite 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"
  ]
}

De dockerfile voert het installatiescript uit en voegt voor het gemak het pad naar de uitvoerbare bestanden van de buildtools toe aan de omgevingsvariabele PATH. Het is ook raadzaam om onnodige bestanden en mappen te verwijderen om de grootte van de afbeelding te verkleinen.

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)

In dit stadium is ons image voor het compileren van de C++-applicatie gereed en kunnen we direct doorgaan met het maken van een docker-meerfasige build van de applicatie.

Meertraps in actie

We zullen de gemaakte afbeelding met alle tools aan boord gebruiken als een build-image. Net als in het vorige dockerfile-script zullen we de mogelijkheid toevoegen om het versienummer/de afbeeldingstag dynamisch te specificeren, zodat de code gemakkelijk opnieuw kan worden gebruikt. Het is belangrijk om een ​​label toe te voegen as builder naar de montageafbeelding in de instructies FROM.

ARG WINDOWS_OS_VERSION=1809
FROM buildtools:$WINDOWS_OS_VERSION as builder

Nu is het tijd om de applicatie te bouwen. Alles is hier vrij eenvoudig: kopieer de broncode en alles wat daarmee samenhangt, en start het compilatieproces.

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

De laatste fase van het maken van de uiteindelijke afbeelding is het specificeren van de basisafbeelding van de applicatie, waar alle compilatieartefacten en configuratiebestanden zich zullen bevinden. Om gecompileerde bestanden van de tussenmontage-image te kopiëren, moet u de parameter opgeven --from=builder in de instructies COPY.

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

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

Het enige dat nu nog overblijft is het toevoegen van de noodzakelijke afhankelijkheden om onze applicatie te laten werken en het specificeren van de startopdracht via de instructies ENTRYPOINT of CMD.

Conclusie

In dit artikel heb ik gesproken over hoe je een volwaardige compilatieomgeving voor C++-applicaties in een container onder Windows kunt creëren en hoe je de mogelijkheden van docker-meerfasige builds kunt gebruiken om volwaardige images van onze applicatie te maken.

Bron: www.habr.com

Voeg een reactie