Använder docker i flera steg för att bygga Windows-bilder

Hej alla! Jag heter Andrey och jag arbetar som DevOps-ingenjör på Exness i utvecklingsteamet. Min huvudsakliga aktivitet är relaterad till att bygga, distribuera och stödja applikationer i docker under operativsystemet Linux (nedan kallat OS). För inte så länge sedan hade jag en uppgift med samma aktiviteter, men målet för projektet var Windows Server och en uppsättning C++-projekt. För mig var detta den första nära interaktionen med docker-containrar under Windows OS och i allmänhet med C++-applikationer. Tack vare detta hade jag en intressant upplevelse och lärde mig om några av krångligheterna med att behålla applikationer i Windows.

Använder docker i flera steg för att bygga Windows-bilder

I den här artikeln vill jag berätta vilka svårigheter jag hade att möta och hur jag lyckades lösa dem. Jag hoppas att detta är till hjälp för dina nuvarande och framtida utmaningar. Njut av att läsa!

Varför containrar?

Företaget har befintlig infrastruktur för Hashicorp Nomad containerorkestrator och relaterade komponenter - Consul och Vault. Därför valdes applikationscontainerisering som en enhetlig metod för att leverera en komplett lösning. Eftersom projektinfrastrukturen innehåller docker-värdar med Windows Server Core OS-versionerna 1803 och 1809, är det nödvändigt att bygga separata versioner av docker-avbildningar för 1803 och 1809. I version 1803 är det viktigt att komma ihåg att versionsnumret för build docker-värden måste matcha versionsnumret för basdockarbilden och den värd där behållaren från denna bild kommer att startas. Version 1809 har ingen sådan nackdel. Du kan läsa mer här.

Varför i flera steg?

Utvecklingsteamingenjörer har ingen eller mycket begränsad tillgång till att bygga värdar; det finns inget sätt att snabbt hantera uppsättningen av komponenter för att bygga en applikation på dessa värdar, till exempel installera en extra verktygsuppsättning eller arbetsbelastning för Visual Studio. Därför tog vi beslutet att installera alla komponenter som behövs för att bygga in applikationen i build Docker-avbildningen. Om det behövs kan du snabbt bara ändra dockerfilen och starta pipelinen för att skapa den här bilden.

Från teori till handling

I en idealisk Docker-bildbyggnad i flera steg är miljön för att bygga applikationen förberedd i samma Dockerfile-skript som själva applikationen byggs. Men i vårt fall lades en mellanlänk till, nämligen steget att preliminärt skapa en docker-bild med allt som behövs för att bygga applikationen. Detta gjordes för att jag ville använda docker-cache-funktionen för att minska installationstiden för alla beroenden.

Låt oss titta på huvudpunkterna i dockerfile-skriptet för att skapa den här bilden.

För att skapa bilder av olika OS-versioner kan du definiera ett argument i dockerfilen genom vilket versionsnumret skickas under byggandet, och det är också taggen för basbilden.

En komplett lista över Microsoft Windows Server-bildtaggar finns här.

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

Som standard kommandona i instruktionerna RUN inuti dockerfilen på Windows OS körs de i cmd.exe-konsolen. För att underlätta att skriva skript och utöka funktionaliteten hos de använda kommandona kommer vi att omdefiniera kommandoexekveringskonsolen i Powershell genom instruktionen SHELL.

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

Nästa steg är att installera chokladpakethanteraren och de nödvändiga paketen:

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'

För att installera paket med choklad kan du helt enkelt skicka dem som en lista, eller installera dem en i taget om du behöver skicka unika parametrar för varje paket. I vår situation använde vi en manifestfil i XML-format, som innehåller en lista över nödvändiga paket och deras parametrar. Dess innehåll ser ut så här:

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

Därefter installerar vi applikationsbyggarmiljön, nämligen MS Build Tools 2019 - detta är en lätt version av Visual Studio 2019, som innehåller den minsta nödvändiga uppsättningen komponenter för att kompilera kod.
För att fullt ut arbeta med vårt C++-projekt behöver vi ytterligare komponenter, nämligen:

  • Arbetsbelastning C++-verktyg
  • Verktygssats v141
  • Windows 10 SDK (10.0.17134.0)

Du kan installera en utökad uppsättning verktyg automatiskt med hjälp av en konfigurationsfil i JSON-format. Konfigurationsfilens innehåll:

En komplett lista över tillgängliga komponenter finns på dokumentationssidan 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"
  ]
}

Dockerfilen kör installationsskriptet och lägger för enkelhetens skull sökvägen till byggverktygens körbara filer till miljövariabeln PATH. Det är också lämpligt att ta bort onödiga filer och kataloger för att minska storleken på bilden.

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)

I det här skedet är vår bild för att kompilera C++-applikationen klar, och vi kan gå direkt vidare till att skapa en docker-flerstegsbyggnad av applikationen.

Flersteg i aktion

Vi kommer att använda den skapade bilden med alla verktyg ombord som en byggbild. Som i det tidigare dockerfile-skriptet kommer vi att lägga till möjligheten att dynamiskt specificera versionsnumret/bildtaggen för att underlätta återanvändning av kod. Det är viktigt att lägga till en etikett as builder till monteringsbilden i instruktionerna FROM.

ARG WINDOWS_OS_VERSION=1809
FROM buildtools:$WINDOWS_OS_VERSION as builder

Nu är det dags att bygga applikationen. Allt här är ganska enkelt: kopiera källkoden och allt som är associerat med den och starta kompileringsprocessen.

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

Det sista steget för att skapa den slutliga bilden är att specificera basbilden för programmet, där alla kompileringsartefakter och konfigurationsfiler kommer att finnas. För att kopiera kompilerade filer från den mellanliggande sammansättningsbilden måste du ange parametern --from=builder i instruktionerna COPY.

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

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

Nu återstår bara att lägga till de nödvändiga beroenden för att vår applikation ska fungera och ange startkommandot genom instruktionerna ENTRYPOINT eller CMD.

Slutsats

I den här artikeln pratade jag om hur man skapar en fullfjädrad kompileringsmiljö för C++-applikationer inuti en behållare under Windows och hur man använder funktionerna i docker-flerstegsbyggen för att skapa fullfjädrade bilder av vår applikation.

Källa: will.com

Lägg en kommentar