Helló mindenkinek! André vagyok, DevOps mérnök az Exness cégnél, a fejlesztői csapatban dolgozom. Fő tevékenységem a Docker alkalmazások összeállítása, telepítése és karbantartása Linux (a továbbiakban: OS) operációs rendszeren. Nemrég új feladatot kaptam a fent említett tevékenységekkel, de a projekt céloperációs rendszere a Windows Server és egy C++ projektekből álló készlet lett. Ez volt az első komoly tapasztalatom a Windows OS-en futó Docker konténerekkel és általában a C++ alkalmazásokkal. Ennek köszönhetően érdekes tapasztalatokat szereztem, és megismertem néhány részletet az alkalmazások Windows OS-en történő konténerizálásának folyamatáról.

Ebben a cikkben szeretném elmondani, milyen nehézségekkel szembesültem, és hogyan sikerült megoldani azokat. Remélem, hasznosnak bizonyul a jelenlegi és jövőbeli feladataitok megoldása szempontjából. Jó olvasást!
Miért konténerek?
A cégnél létezik egy Hashicorp Nomad konténer-orkesztrátor infrastruktúra és a hozzá kapcsolódó komponensek — Consul és Vault. Ezért az alkalmazások konténerizálását egységes módszerként választottuk a kész megoldások szállítására. Mivel a projekt infrastruktúrájában Windows Server Core 1803 és 1809 verziókkal rendelkező Docker hosztok találhatók, külön kell összeállítani a Docker képek verzióit 1803-ra és 1809-re. A 1803 verzió esetében fontos figyelembe venni, hogy a Docker hoszt összeállításának revíziós száma meg kell, hogy egyezzen a Docker kép alap revíziós számával és a hoszt revíziós számával, ahol az adott kép konténere futni fog. A 1809-es verziónál ez nem probléma. További részletekért olvasson el .
Miért multi-stage?
A fejlesztői csapat mérnökeinek nem áll rendelkezésére a build hosztokhoz való hozzáférés, vagy az erősen korlátozott. Nincs lehetőségük gyorsan kezelni a szükséges komponensek készletét az alkalmazás buildelési folyamathoz ezeken a hosztokon, például nem tudnak telepíteni további eszközgyűjteményeket vagy munkaterheket a Visual Studiohoz. Ezért döntöttünk úgy, hogy az alkalmazás összeállításához szükséges összes komponenst a build Docker képbe telepítjük. Szükség esetén elég gyorsan megváltoztatható csak a Dockerfile, és elindítható a kép létrehozásának pipeline-ja.
A tudománytól a gyakorlatig
A tökéletes docker multi-stage build során az alkalmazás környezetének előkészítése ugyanabban a dockerfile szkriptben történik, mint maga az alkalmazás összeállítása. Azonban a mi esetünkben egy köztes lépés került hozzáadásra, nevezetesen a docker-kép előzetes elkészítésének fázisa, amely minden szükséges elemet tartalmaz az alkalmazás összeállításához. Ezt azért tettük, mert ki akartuk használni a docker cache lehetőségét, hogy csökkentsük az összes függőség telepítési idejét.
Nézzük át a dockerfile szkript alapvető pontjait, amelyek ezt a képet alkotják.
A dockerfile különböző operációs rendszer verzióinak létrehozásához egy argumentumot definiálhatunk, amelyen keresztül az építés során átadjuk a verzió számát, és ez a báziskép címkéje is.
A Microsoft Windows Server képek teljes címke listáját megtalálhatja .
ARG WINDOWS_OS_VERSION=1809
FROM mcr.microsoft.com/windows/servercore:$WINDOWS_OS_VERSIONAlapértelmezés szerint az utasításokban szereplő parancsok RUN a dockerfile-on belül Windows rendszeren a cmd.exe konzolon futnak. A szkriptek kényelmesebb írása és a használt parancsok funkcióinak bővítése érdekében állítsuk át a parancsok végrehajtási konzolját Powershell-re az utasítás segítségével SHELL.
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]A következő lépés a chocolatey csomagkezelő és a szükséges csomagok telepítése:
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'A csomagok telepítéséhez, a chocolatey segítségével, egyszerűen átadhatjuk őket egy listában, vagy telepíthetjük őket egyesével, ha egyedi paramétereket kell megadnunk minden csomaghoz. A mi esetünkben egy XML formátumú nyilatkozati fájlt használtunk, amely tartalmazza a szükséges csomagok listáját és azok paramétereit. A tartalma így néz ki:
Ezután telepítjük az alkalmazás építési környezetét, nevezetesen a MS Build Tools 2019-et – ez a Visual Studio 2019 egy könnyített verziója, amely tartalmazza a kód fordításához minimálisan szükséges komponenseket.
A C++ projekt teljes körű működéséhez további komponensekre lesz szükség, nevezetesen:
- Workload C++ tools
- Toolset v141
- Windows 10 SDK (10.0.17134.0)
Az előre beállított eszközkészlet automatikus telepítése egy JSON formátumú konfigurációs fájl segítségével lehetséges. A konfigurációs fájl tartalma:
A rendelkezésre álló összes komponens teljes listáját a dokumentációs webhelyen találhatja. .
{
"version": "1.0",
"components": [
"Microsoft.Component.MSBuild",
"Microsoft.VisualStudio.Workload.VCTools;includeRecommended",
"Microsoft.VisualStudio.Component.VC.v141.x86.x64",
"Microsoft.VisualStudio.Component.Windows10SDK.17134"
]
}A dockerfile-ben telepítési szkript fut, és a kényelmes használat érdekében a build tools végrehajtható fájljainak elérési útját hozzáadjuk a környezeti változókhoz. PATH. Ezenkívül ajánlott a szükségtelen fájlok és könyvtárak eltávolítása, hogy csökkentsük a kép méretét.
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)Ez a lépés a C++ alkalmazásunk fordításához szükséges kép elkészítésének folytatása, és most már közvetlenül a docker multi-stage alkalmazás létrehozásához fogunk áttérni.
Multi-stage működés közben
A build képünket fogjuk használni, amely tartalmazza az összes szükséges eszközt. Ahogyan az előző dockerfile szkriptben, lehetőséget adunk a verziószám/dombornyomás dinamikus megadására a kód újrahasznosíthatósága érdekében. Fontos, hogy hozzátegyünk egy címkét as builder a build képhez a parancsban FROM.
ARG WINDOWS_OS_VERSION=1809
FROM buildtools:$WINDOWS_OS_VERSION as builderElérkezett az alkalmazás építésének ideje. Itt minden eléggé egyszerű: másolja át a forráskódot és mindent, ami hozzá tartozik, majd indítsa el a fordítási folyamatot.
COPY myapp .
RUN nuget restore myapp.sln ;
msbuild myapp.sln /t:myapp /p:Configuration=ReleaseA végső kép létrehozásának záró lépése az alkalmazás alap képként való megadása, ahol az összes fordítási artefaktum és konfigurációs fájl található. A fordításhoz szükséges fájlok másolásához a köztes build képből a következő paramétert kell megadni: --from=builder a használati útmutatóban COPY.
FROM mcr.microsoft.com/windows/servercore:$WINDOWS_OS_VERSION
COPY --from=builder C:/x64/Release/myapp/ ./
COPY ./configs ./Most már csak a szükséges függőségeket kell hozzáadni az alkalmazásunk működéséhez, és meg kell adni a futtatási parancsot a parancsok révén. ENTRYPOINT vagy CMD.
Zárás
Ebben a cikkben bemutattam, hogyan lehet teljes körű C++ alkalmazásfejlesztési környezetet létrehozni Windows környezetben, valamint hogyan lehet a docker multi-stage build lehetőségeit felhasználni alkalmazásunk valódi képeinek létrehozásához.
Forrás: habr.com
