Použitie docker multi-stage na zostavenie Windows obrazov

Ahojte všetci! Volám sa Andrej a pracujem ako DevOps inžinier vo firme Exness v tímu vývoja. Moja hlavná činnosť súvisiaca so zostavovaním, nasadzovaním a podporou aplikácií v dockeri na operačnom systéme Linux (ďalej len — OS). Nedávno som mal úlohu so s podobnými aktivitami, avšak ako cieľový OS projektu sa stal Windows Server a súbor projektov v C++. Pre mňa to bolo prvé intenzívne zapojenie sa do docker kontajnerov na OS Windows a celkovo s aplikáciami v C++. Vďaka tomu som získal zaujímavé skúsenosti a dozvedel sa o niektorých nuansách kontajnerizácie aplikácií na OS Windows.

Použitie docker multi-stage na zostavenie Windows obrazov

V tomto článku chcem porozprávať, s akými ťažkosťami som sa stretol a akým spôsobom sa ich podarilo vyriešiť. Dúfam, že to bude užitočné pri riešení vašich súčasných a budúcich úloh. Príjemné čítanie!

Prečo kontajnery?

V spoločnosti existuje existujúca infraštruktúra orchestrátora kontajnerov Hashicorp Nomad a súvisiacich komponentov — Consul a Vault. Preto bola kontajnerizácia aplikácií vybraná ako zjednotený spôsob dodávky hotového riešenia. Keďže v infraštruktúre projektu existujú docker-hosty s verziami OS Windows Server Core 1803 a 1809, je potrebné samostatne zostavovať verzie docker-obrázkov pre 1803 a 1809. V verzii 1803 je dôležité pamätať na to, že číslo revízie zostavovacieho docker-hostu musí zodpovedať číslu revízie základného docker-obrázku a hosta, kde sa kontajner z tohto obrázku spustí. Verzia 1809 tento nedostatok nemá. Viac sa môžete dočítať tu.

Prečo multi-stage?

Inžinieri vývojových tímov nemajú prístup k zostavovacím hostom alebo ho majú veľmi obmedzený, nemajú možnosť operatívne spravovať súbor komponentov pre zostavenie aplikácie na týchto hostoch, napríklad nainštalovať doplnkový toolset alebo workload pre Visual Studio. Preto sme sa rozhodli — všetky komponenty potrebné na zostavenie aplikácie nainštalovať do zostavovacieho docker-obrázka. V prípade potreby môžeme dosť rýchlo zmeniť len dockerfile a spustiť pipeline na vytvorenie tohto obrázka.

Od teórie k praxi

V ideálnej multi-stage zostave docker obrazu sa príprava prostredia na zostavenie aplikácie vykonáva v tom istom dockerfile skripte, ako aj vlastná zostava aplikácie. V našom prípade však bolo pridané medzičlánok, a to krok predbežného vytvorenia docker obrazu so všetkým potrebným na zostavenie aplikácie. Tak sa to spravilo, pretože sme chceli využiť možnosti docker cache na skrátenie času inštalácie všetkých závislostí.

Poďme si rozobrať hlavné Body dockerfile skriptu na vytvorenie tohto obrazu.

Na vytvorenie obrazov rôznych verzií OS v dockerfile môžeme definovať argument, cez ktorý sa pri zostavení odovzdáva číslo verzie, a ten bude zároveň tagom základného obrazu.

Úplný zoznam tagov obrazov Microsoft Windows Server možno nájsť tu.

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

V predvolenom nastavení sa príkazy v inštrukcii RUN v rámci dockerfile v OS Windows vykonávajú v konzole cmd.exe. Na uľahčenie písania skriptov a rozšírenie funkčnosti používaných príkazov predefinujeme konzolu vykonávania príkazov na Powershell prostredníctvom inštrukcie SHELL.

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

Ďalším krokom je inštalácia balíčkového správcu chocolatey a potrebných balíkov:

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'

Aby sme nainštalovali balíky pomocou chocolatey, môžeme jednoducho odovzdať ich zoznam alebo ich nainštalovať jednotlivo v prípade, že potrebujeme odovzdať unikátne parametre pre každý balík. V našej situácii sme použili manifestový súbor vo formáte XML, v ktorom je uvedený zoznam potrebných balíkov a ich parametrov. Jeho obsah vyzerá takto:

Následne nainštalujeme prostredie na zostavenie aplikácie, a to MS Build Tools 2019 — odľahčenú verziu Visual Studio 2019, ktorá obsahuje minimálne potrebnú sadu komponentov na kompiláciu kódu.
Na plnohodnotnú prácu s naším C++ projektom budeme potrebovať ďalšie komponenty, a to:

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

Rozšířený nástrojový set lze nainstalovat automaticky pomocí konfiguračního souboru ve formátu JSON. Obsah konfiguračního souboru:

Úplný seznam dostupných komponentů lze nalézt na webu dokumentace 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"
  ]
}

Ve dockerfile se provádí instalační skript, a pro pohodlí se přidává cesta k spustitelným souborům build tools do proměnné prostředí PATH. Také je žádoucí odstranit nepotřebné soubory a adresáře, aby se snížila velikost obrazu.

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)

V tomto okamžiku je náš obraz pro kompilaci C++ aplikace připraven a můžeme přejít přímo k vytváření docker multi-stage sestavení aplikace.

Multi-stage v akci

Jako sestavovací obraz použijeme vytvořený obraz se vším nástrojem na palubě. Tak jako v předchozím dockerfile skriptu, přidáme možnost dynamicky uvádět číslo verze/tagu obrazu pro pohodlí opětovného použití kódu. Je důležité přidat značku as builder k sestavovacímu obrazu v instrukci FROM.

ARG WINDOWS_OS_VERSION=1809
FROM buildtools:$WINDOWS_OS_VERSION as builder

Nastal čas na sestavování aplikace. Tady je to dost jednoduché: zkopírovat zdrojový kód a vše, co s ním souvisí, a spustit proces kompilace.

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

Závěrečná fáze vytvoření konečného obrazu – uvedení základního obrazu aplikace, kde budou uloženy všechny artefakty kompilace a konfigurační soubory. Pro zkopírování zkompilovaných souborů z mezilehlého sestavovacího obrazu je třeba uvést parametr --from=builder v instrukci KOPÍROVAŤ.

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

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

Teď zbývá přidat potřebné závislosti pro provoz naší aplikace a uvést příkaz pro spuštění prostřednictvím instrukcí ENTRYPOINT alebo CMD.

Záver

V tomto článku vám ukážem, ako vytvoriť plnohodnotné prostredie na kompiláciu aplikácií C++ vo vnútri kontajnera na Windows a ako využiť možnosti docker multi-stage zostavení na vytvorenie plnohodnotných obrazov našej aplikácie.

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster