Pozdravljeni! Moje ime je Andrej in delam kot DevOps inženir v podjetju Exness v ekipi za razvoj. Moje glavno delo je povezano s sestavljanjem, namestitvijo in podporo aplikacij v dockerju pod operacijskim sistemom Linux (v nadaljevanju — OS). Nedavno sem imel nalogo z enakimi aktivnostmi, vendar je kot ciljna OS projekta postala Windows Server in niz projektov v C++. To je bilo moje prvo tesno sodelovanje s docker kontejnerji pod OS Windows ter nasploh z aplikacijami v C++. Tako sem pridobil zanimivo izkušnjo in izvedel nekaj posebnosti glede kontejnerizacije aplikacij v OS Windows.

V tem članku želim opisati, s katerimi težavami sem se soočil in kako sem jih uspel rešiti. Upam, da bo to koristno pri reševanju vaših trenutnih in bodočih nalog. Uživajte v branju!
Zakaj kontejnerji?
V podjetju obstaja obstoječa infrastruktura orkestra kontejnerjev Hashicorp Nomad in povezanih komponent — Consul in Vault. Zato je bila kontejnerizacija aplikacij izbrana kot poenoten način dostave končnega rešitve. Ker v infrastrukturnem projektu obstajajo docker gostitelji z različicami OS Windows Server Core 1803 in 1809, je potrebno posebej sestaviti različice docker slik za 1803 in 1809. Pri različici 1803 je pomembno, da se številka revizije sestavljalnega docker gostitelja ujema s številko revizije osnovne docker slike in gostitelja, na katerem bo ta kontejner zagnan. Različica 1809 nima te pomanjkljivosti. Več lahko preberete .
Zakaj večstopenjska?
Razvijalci nimajo dostopa do sestavljalnih gostiteljev ali je ta dostop zelo omejen, ni mogoče takoj upravljati z naborom komponent za sestavljanje aplikacije na teh gostiteljih, na primer, namestiti dodatni orodjar ali obremenitve za Visual Studio. Zato smo se odločili, da vse potrebne komponente za sestavljanje aplikacije namestimo v sestavljalni docker image. Po potrebi je mogoče razmeroma hitro spremeniti samo dockerfile in zagnati pipeline za ustvarjanje tega image-a.
Od teorije do prakse
V idealni docker multi-stage sestavi slike se priprava okolja za gradnjo aplikacije odvija v istem dockerfile skriptu kot tudi gradnja same aplikacije. Vendar pa smo v našem primeru dodali vmesni korak, in sicer, korak začetne izdelave docker-slike z vsem potrebnim za gradnjo aplikacije. To je bilo narejeno, ker smo želeli izkoristiti možnost docker cache, da bi skrajšali čas namestitve vseh odvisnosti.
Poglejmo glavne točke dockerfile skriptu za oblikovanje te slike.
Za ustvarjanje slik različnih različic operacijskih sistemov v dockerfile lahko definiramo argument, preko katerega se med gradnjo prenese številka različice, ki je tudi oznaka osnovne slike.
Popoln seznam oznak slik Microsoft Windows Server lahko najdete .
ARG WINDOWS_OS_VERSION=1809
FROM mcr.microsoft.com/windows/servercore:$WINDOWS_OS_VERSIONPrivzeto se ukazi v navodilu RUN znotraj dockerfile v operacijskem sistemu Windows izvajajo v konzoli cmd.exe. Za lažje pisanje skript in širitev funkcionalnosti uporabljanih ukazov bom spremenili konzolo izvrševanja ukazov na Powershell preko navodila SHELL.
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]Naslednji korak je namestitev paketnega upravljalnika chocolatey in potrebnih paketov:
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'Za namestitev paketov z uporabo chocolatey lahko enostavno posredujete seznam ali pa namestite enega po enega, če je potrebno posredovati edinstvene parametre za vsak paket. V naši situaciji smo uporabili manifest datoteko v formatu XML, v kateri je naveden seznam potrebnih paketov in njihovih parametrov. Njeno vsebino je takole:
Nato namestimo okolje za gradnjo aplikacije, in sicer MS Build Tools 2019 — to je poenostavljena različica Visual Studio 2019, ki vsebuje minimalni sklop komponent za kompajliranje kode.
Za popolno delovanje z našim C++ projektom potrebujemo dodatne komponente, in sicer:
- Workload C++ tools
- Toolset v141
- Windows 10 SDK (10.0.17134.0)
Konfiguracijski skup alatki može se automatski instalirati pomoću JSON datoteke s konfiguracijom. Sadržaj datoteke s konfiguracijom:
Puni popis dostupnih komponenti može se pronaći na web stranici dokumentacije .
{
"version": "1.0",
"components": [
"Microsoft.Component.MSBuild",
"Microsoft.VisualStudio.Workload.VCTools;includeRecommended",
"Microsoft.VisualStudio.Component.VC.v141.x86.x64",
"Microsoft.VisualStudio.Component.Windows10SDK.17134"
]
}U dockerfile-u se izvršava skripta za instalaciju, a radi lakšeg korištenja dodaje se put do izvršnih datoteka build tools u varijablu okruženja PATH. Također, poželjno je ukloniti nepotrebne datoteke i direktorije kako bi se smanjila veličina slike.
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)U ovoj fazi naš obraz za kompilaciju C++ aplikacije je spreman, i možemo se posvetiti stvaranju docker multi-stage izgradnje aplikacije.
Multi-stage u akciji
Kao osnovni obraz za izgradnju koristit ćemo stvoreni obraz sa svim alatima na brodu. Kao u prethodnoj skripti dockerfile, dodajmo mogućnost dinamičkog navođenja broja verzije/tag-a slike radi lakšeg ponovnog korištenja koda. Važno je dodati oznaku as builder na osnovni obraz u uputi FROM.
ARG WINDOWS_OS_VERSION=1809
FROM buildtools:$WINDOWS_OS_VERSION as builderDošao je red na izgradnju aplikacije. Ovdje je sve prilično jednostavno: kopirati izvorni kod i sve povezano s njim, te pokrenuti proces kompilacije.
COPY myapp .
RUN nuget restore myapp.sln ;
msbuild myapp.sln /t:myapp /p:Configuration=ReleaseZavršna faza izrade konačne slike — navođenje osnovnog obraza aplikacije, gdje će se nalaziti svi artefakti kompilacije i datoteke konfiguracije. Da bismo kopirali kompilirane datoteke iz međufaznog izgradnog obraza, potrebno je navesti parametar --from=builder u uputi COPY.
FROM mcr.microsoft.com/windows/servercore:$WINDOWS_OS_VERSION
COPY --from=builder C:/x64/Release/myapp/ ./
COPY ./configs ./Sada ostaje dodati potrebne ovisnosti za rad naše aplikacije i navesti naredbu za pokretanje putem uputa ENTRYPOINT ili CMD.
Zaključek
V tem članku bom opisal, kako ustvariti popolno okolje za kompilacijo C++ aplikacij znotraj kontejnerja v sistemu Windows in kako izkoristiti možnosti docker multi-stage gradnje za ustvarjanje popolnih slik našega aplikacije.
Izvor: habr.com
