Bună ziua tuturor! Numele meu este Andrei și lucrez ca inginer DevOps la compania Exness în echipa de dezvoltare. Activitatea mea principală este legată de construirea, implementarea și întreținerea aplicațiilor în docker pe sistemul de operare Linux (denumit în continuare - OS). Recent, am avut o sarcină similară, dar ca sistem de operare țintă pentru proiect a devenit Windows Server și un set de proiecte pe C++. Pentru mine, aceasta a fost prima interacțiune intensă cu containere docker pe Windows și, în general, cu aplicațiile pe C++. Datorită acestui lucru, am obținut o experiență interesantă și am învățat despre unele specificități ale containerizării aplicațiilor pe Windows.

În acest articol vreau să împărtășesc dificultățile cu care m-am confruntat, modul în care am reușit să le rezolv. Sper că aceasta va fi utilă pentru soluționarea problemelor dvs. actuale și viitoare. Lectură plăcută!
De ce containere?
Compania are o infrastructură existentă pentru orchestrarea containerelor Hashicorp Nomad și componentele asociate - Consul și Vault. Prin urmare, containerizarea aplicațiilor a fost aleasă ca metodă unificată de livrare a soluțiilor complete. Deoarece în infrastructura proiectului există gazde docker cu versiunile de Windows Server Core 1803 și 1809, este necesar să construim separat versiunile docker-imagelui pentru 1803 și 1809. În versiunea 1803, este important să ne amintim că numărul de revizie al gazdei docker de construcție trebuie să coincidă cu numărul de revizie al docker-imagelui de bază și al gazdei pe care va fi lansat containerul din acest imagine. Versiunea 1809 nu are această problemă. Puteți citi mai multe detalii .
De ce multi-stage?
Inginerilor echipelor de dezvoltare nu le este permis accesul la gazdele de construcție sau acesta este foarte limitat, nu există posibilitatea de a gestiona rapid setul de componente pentru construcția aplicației pe aceste gazde, de exemplu, instalarea unui toolset sau a unui workload suplimentar pentru Visual Studio. Din acest motiv, am luat decizia - toate componentele necesare pentru construcția aplicației vor fi instalate în imaginea docker de construcție. Dacă este necesar, se poate schimba destul de repede doar dockerfile-ul și se poate lansa pipeline-ul pentru crearea acestei imagini.
De la teorie la practică
Într-o construcție ideală a imaginii Docker multi-stage, pregătirea mediului pentru compilarea aplicației are loc în același script Dockerfile în care se desfășoară și compilarea efectivă a aplicației. În cazul nostru, a fost adăugat un element intermediar, și anume, un pas de creare preliminară a imaginii Docker cu tot ceea ce este necesar pentru a construi aplicația. Acest lucru a fost realizat deoarece am dorit să folosim funcția de cache Docker pentru a reduce timpul de instalare a tuturor dependențelor.
Să analizăm principalele aspecte ale scriptului Dockerfile pentru formarea acestei imagini.
Pentru a crea imagini cu diferite versiuni de OS în Dockerfile, se poate defini un argument prin care se transmite numărul versiunii în timpul compilării, iar acesta devine eticheta imaginii de bază.
Lista completă a etichetelor imaginilor Microsoft Windows Server poate fi găsită .
ARG WINDOWS_OS_VERSION=1809
FROM mcr.microsoft.com/windows/servercore:$WINDOWS_OS_VERSIONPrin default, comenzile din instrucțiunea comenzi RUN după semnificație. în interiorul Dockerfile pe OS Windows se execută în consola cmd.exe. Pentru a facilita scrierea scripturilor și extinderea funcționalităților comenzilor utilizate, vom redefine consola de execuție a comenzilor pe PowerShell prin instrucțiunea SHELL.
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]Următorul pas este să instalăm managerul de pachete Chocolatey și pachetele necesare:
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'Pentru a instala pachete folosind Chocolatey, se poate pur și simplu transmite o listă sau se pot instala câte unul, în cazul în care este necesar să se transmită parametrii unici pentru fiecare pachet. În situația noastră, am folosit un fișier manifest în format XML, în care se specifică lista pachetelor necesare și parametrii acestora. Conținutul acestuia arată astfel:
Apoi, instalăm mediul pentru compilarea aplicației, și anume, MS Build Tools 2019 — aceasta este o versiune redusă a Visual Studio 2019, care conține setul minim necesar de componente pentru compilarea codului.
Pentru o funcționare completă a proiectului nostru C++, ne vor fi necesare componente suplimentare, și anume:
- Workload C++ tools
- Toolset v141
- Windows 10 SDK (10.0.17134.0)
Pentru a instala setul extins de instrumente în mod automat, puteți utiliza un fișier de configurare în format JSON. Conținutul fișierului de configurare:
Lista completă de componente disponibile poate fi găsită pe site-ul documentației .
{
"version": "1.0",
"components": [
"Microsoft.Component.MSBuild",
"Microsoft.VisualStudio.Workload.VCTools;includeRecommended",
"Microsoft.VisualStudio.Component.VC.v141.x86.x64",
"Microsoft.VisualStudio.Component.Windows10SDK.17134"
]
}În dockerfile se execută un script de instalare, iar pentru comoditate se adaugă calea către fișierele executabile build tools în variabila de mediu PATH. De asemenea, este de preferat să ștergeți fișierele și directorile inutile pentru a reduce dimensiunea imaginii.
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)În această etapă, imaginea noastră pentru compilarea aplicației C++ este gata, și putem începe direct procesul de construire a aplicației docker multi-stage.
Multi-stage în acțiune
Ca imagine de construire, vom folosi imaginea creată cu toate instrumentele la bord. Asemenea scriptului dockerfile anterior, vom adăuga capacitatea de a specifica dinamic numărul versiunii/taga imaginii pentru a facilita reutilizarea codului. Este important să adăugăm eticheta as builder la imaginea de construire în instrucțiunea FROM.
ARG WINDOWS_OS_VERSION=1809
FROM buildtools:$WINDOWS_OS_VERSION as builderA venit vremea construirii aplicației. Aici totul este destul de simplu: copiați codul sursă și tot ce este legat de el și porniți procesul de compilare.
COPY myapp .
RUN nuget restore myapp.sln ;
msbuild myapp.sln /t:myapp /p:Configuration=ReleaseEtapa finală a creării imaginii finale este specificarea imaginii de bază a aplicației, unde vor fi localizate toate artefactele de compilare și fișierele de configurare. Pentru a copia fișierele compilate din imaginea intermediară de construire, trebuie să specificați parametrul --from=builder în manualul de utilizare COPIE.
FROM mcr.microsoft.com/windows/servercore:$WINDOWS_OS_VERSION
COPY --from=builder C:/x64/Release/myapp/ ./
COPY ./configs ./Acum rămâne să adăugăm dependențele necesare pentru funcționarea aplicației noastre și să specificăm comanda de rulare prin instrucțiuni ENTRYPOINT sau CMD.
Concluzie
În acest articol, am discutat despre cum să creăm un mediu complet de compilare pentru aplicații C++ în interiorul unui container pe Windows și despre cum să utilizăm funcționalitățile construcțiilor multi-stage docker pentru a crea imagini complete ale aplicației noastre.
Sursa: habr.com
