Ahoj všichni! Jsem Andrej a pracuji jako DevOps inženýr ve společnosti Exness v týmu vývoje. Moje hlavní činnost se týká sestavení, nasazení a podpory aplikací v dockeru na operačním systému Linux (dále jen - OS). Nedávno se mi objevila úloha se stejnými aktivitami, ale cílovým OS projektu se stal Windows Server a sada projektů v C++. Pro mě to bylo první intenzivní setkání s docker kontejnery na OS Windows a obecně s aplikacemi v C++. Díky tomu jsem získal zajímavé zkušenosti a naučil se některé nuancím kontejnerizace aplikací v OS Windows.

V tomto článku bych chtěl vyprávět, s jakými obtížemi jsem se musel potýkat, jakým způsobem se mi je podařilo vyřešit. Doufám, že to bude užitečné při řešení vašich současných a budoucích úkolů. Příjemné čtení!
Proč kontejnery?
Ve společnosti existuje stávající infrastruktura orchestrace kontejnerů Hashicorp Nomad a souvisejících komponent — Consul a Vault. Proto byla kontejnerizace aplikací vybrána jako jednotný způsob dodání hotového řešení. V infrastruktuře projektu jsou docker hostitelé se verzemi OS Windows Server Core 1803 a 1809, a proto je nutné samostatně sestavovat verze docker obrazů pro 1803 a 1809. U verze 1803 je důležité si pamatovat, že číslo revize sestavovacího docker hostitele musí odpovídat číslu revize základního docker obrazu a hostitele, kde bude kontejner z tohoto obrazu spuštěn. Verze 1809 tento nedostatek postrádá. Podrobněji si můžete přečíst .
Proč multi-stage?
Inženýři vývojových týmů nemají přístup k sestavovacím hostitelům, nebo je tento přístup silně omezen, nemají možnost pružně spravovat soubor komponent pro sestavení aplikace na těchto hostitelích, například nainstalovat další toolset nebo workload pro Visual Studio. Proto jsme se rozhodli - všechny potřebné komponenty pro sestavení aplikace nainstalovat do sestavovacího docker obrazu. V případě potřeby lze relativně rychle změnit pouze dockerfile a spustit pipeline pro vytvoření tohoto obrazu.
Od teorie k praxi
V ideální docker multi-stage sestavě obrazu se příprava prostředí pro sestavení aplikace odehrává ve stejném dockerfile skriptu jako sestavení samotné aplikace. V našem případě však bylo přidáno mezistupně, a to krok předběžného vytvoření docker-obrazu se vším potřebným pro sestavení aplikace. Bylo to provedeno proto, že jsme chtěli využít možnosti docker cache, abychom zkrátili dobu instalace všech závislostí.
Pojďme si rozebrat základní body dockerfile skriptu pro vytvoření tohoto obrazu.
Pro vytvoření obrazů různých verzí OS lze v dockerfile definovat argument, pomocí kterého se při sestavení předává číslo verze, a ten je zároveň tagem základního obrazu.
Úplný seznam tagů obrazů Microsoft Windows Server lze najít. .
ARG WINDOWS_OS_VERSION=1809
FROM mcr.microsoft.com/windows/servercore:$WINDOWS_OS_VERSIONVe výchozím nastavení se příkazy v instrukci RUN uvnitř dockerfile v OS Windows vykonávají v konzoli cmd.exe. Pro usnadnění psaní skriptů a rozšíření funkčnosti používaných příkazů předefinujeme konzoli pro vykonávání příkazů na Powershell pomocí instrukce SHELL.
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]Dalším krokem je instalace balíčkového manažera chocolatey a nezbytných balíčků:
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'Abyste mohli instalovat balíčky pomocí chocolatey, stačí je jednoduše předat jako seznam nebo nainstalovat jeden po druhém, pokud je třeba předat jedinečné parametry pro každý balíček. V naší situaci jsme použili manifestový soubor ve formátu XML, který uvádí seznam potřebných balíčků a jejich parametrů. Jeho obsah vypadá takto:
Dále instalujeme prostředí pro sestavení aplikace, a to MS Build Tools 2019 — to je zjednodušená verze Visual Studio 2019, která obsahuje minimálně potřebnou sadu komponent pro kompilaci kódu.
Pro plnohodnotnou práci s naším C++ projektem budeme potřebovat další komponenty, a to:
- Nástroje pro zátěž C++
- Nástrojový set v141
- Windows 10 SDK (10.0.17134.0)
Rozšířenou sadu nástrojů lze nainstalovat automaticky pomocí konfiguračního souboru ve formátu JSON. Obsah konfiguračního souboru:
Úplný seznam dostupných komponentů naleznete na webu dokumentace .
{
"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 souboru dockerfile se spouští instalační skript a pro usnadnění se přidává cesta k spustitelným souborům build tools do proměnné prostředí cest. 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 této fázi je náš obraz pro kompilaci C++ aplikace připraven a můžeme přistoupit k samotnému vytváření docker multi-stage sestavy aplikace.
Multi-stage v akci
Jako základní obraz pro sestavení použijeme vytvořený obraz se všemi nástroji. Jak bylo uvedeno v předchozím skriptu dockerfile, přidáme možnost dynamicky zadávat číslo verze/tagu obrazu pro snadnost opakovaného použití kódu. Je důležité přidat značku as builder k základnímu obrazu v instrukci FROM.
ARG WINDOWS_OS_VERSION=1809
FROM buildtools:$WINDOWS_OS_VERSION as builderNastal čas na sestavení aplikace. Tady je to docela 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=ReleaseZávěrečná fáze vytváření konečného obrazu — určení základního obrazu aplikace, kde budou umístěny všechny artefakty kompilace a konfigurační soubory. Pro kopírování zkompilovaných souborů z mezilehlého sestavovacího obrazu je třeba uvést parametr --from=builder v pokynech COPY.
FROM mcr.microsoft.com/windows/servercore:$WINDOWS_OS_VERSION
COPY --from=builder C:/x64/Release/myapp/ ./
COPY ./configs ./Nyní zbývá přidat potřebné závislosti pro běh naší aplikace a uvést spouštěcí příkaz pomocí instrukcí ENTRYPOINT nebo CMD.
Závěr
V tomto článku jsem popsal, jak vytvořit plnohodnotné prostředí pro kompilaci aplikací C++ uvnitř kontejneru na Windows a jak využívat možnosti vícefázových sestavení Dockeru pro vytváření plnohodnotných obrazů naší aplikace.
Zdroj: habr.com
