Korzystanie z wieloetapowego okna dokowanego do tworzenia obrazów systemu Windows

Cześć wszystkim! Nazywam się Andrey i pracuję jako inżynier DevOps w firmie Exness w zespole programistów. Moja główna działalność związana jest z budowaniem, wdrażaniem i obsługą aplikacji w dockerze pod systemem operacyjnym Linux (zwanym dalej OS). Nie tak dawno temu miałem zadanie z tymi samymi czynnościami, ale docelowym systemem operacyjnym projektu był Windows Server i zestaw projektów C++. Dla mnie była to pierwsza bliska interakcja z kontenerami dokowymi w systemie operacyjnym Windows i ogólnie z aplikacjami C++. Dzięki temu przeżyłem ciekawe doświadczenie i poznałem niektóre zawiłości konteneryzacji aplikacji w Windowsie.

Korzystanie z wieloetapowego okna dokowanego do tworzenia obrazów systemu Windows

W tym artykule chcę opowiedzieć z jakimi trudnościami musiałam się zmierzyć i jak udało mi się je rozwiązać. Mam nadzieję, że będzie to pomocne w obliczu obecnych i przyszłych wyzwań. Miłego czytania!

Dlaczego kontenery?

Firma posiada istniejącą infrastrukturę dla orkiestratora kontenerów Hashicorp Nomad i powiązanych komponentów - Consul i Vault. Dlatego też jako ujednoliconą metodę dostarczenia kompletnego rozwiązania wybrano konteneryzację aplikacji. Ponieważ infrastruktura projektu zawiera hosty dokowane z systemem Windows Server Core OS w wersjach 1803 i 1809, konieczne jest zbudowanie oddzielnych wersji obrazów doków dla wersji 1803 i 1809. W wersji 1803 należy pamiętać, że numer wersji hosta dokowanego kompilacji musi odpowiadać numerowi wersji podstawowego obrazu okna dokowanego i hostowi, na którym zostanie uruchomiony kontener z tego obrazu. Wersja 1809 nie ma takiej wady. Możesz przeczytać więcej tutaj.

Dlaczego wieloetapowy?

Inżynierowie zespołu programistów nie mają żadnego dostępu do kompilowania hostów lub mają je bardzo ograniczony; nie ma możliwości szybkiego zarządzania zestawem komponentów do tworzenia aplikacji na tych hostach, na przykład instalowania dodatkowego zestawu narzędzi lub obciążenia dla programu Visual Studio. Dlatego podjęliśmy decyzję o zainstalowaniu wszystkich komponentów niezbędnych do zbudowania aplikacji w obrazie Dockera. Jeśli to konieczne, możesz szybko zmienić tylko plik dokowany i uruchomić potok tworzenia tego obrazu.

Od teorii do działania

W idealnej wieloetapowej kompilacji obrazu Dockera środowisko do budowania aplikacji jest przygotowywane w tym samym skrypcie Dockerfile, w którym budowana jest sama aplikacja. Jednak w naszym przypadku dodano łącze pośrednie, a mianowicie krok wstępnego utworzenia obrazu dokera ze wszystkim, co niezbędne do zbudowania aplikacji. Zrobiono to, ponieważ chciałem użyć funkcji pamięci podręcznej okna dokowanego, aby skrócić czas instalacji wszystkich zależności.

Przyjrzyjmy się głównym punktom skryptu dockerfile służącym do tworzenia tego obrazu.

Aby utworzyć obrazy różnych wersji systemu operacyjnego, możesz zdefiniować w pliku dockerfile argument, przez który numer wersji będzie przekazywany podczas kompilacji. Jest on także znacznikiem obrazu bazowego.

Można znaleźć pełną listę znaczników obrazów systemu Microsoft Windows Server tutaj.

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

Domyślnie polecenia zawarte w instrukcjach RUN wewnątrz pliku dokowanego w systemie operacyjnym Windows są one wykonywane w konsoli cmd.exe. Dla wygody pisania skryptów i rozszerzenia funkcjonalności używanych poleceń na nowo zdefiniujemy konsolę wykonywania poleceń w Powershell za pomocą instrukcji SHELL.

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

Następnym krokiem jest instalacja menedżera pakietów Chocolatey i niezbędnych pakietów:

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 zainstalować pakiety przy użyciu Chocolatey, możesz po prostu przekazać je jako listę lub zainstalować pojedynczo, jeśli chcesz przekazać unikalne parametry dla każdego pakietu. W naszej sytuacji wykorzystaliśmy plik manifestu w formacie XML, który zawiera listę wymaganych pakietów i ich parametrów. Jego zawartość wygląda następująco:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="python" version="3.8.2"/>
  <package id="nuget.commandline" version="5.5.1"/>
  <package id="git" version="2.26.2"/>
</packages>

Następnie instalujemy środowisko budowy aplikacji, czyli MS Build Tools 2019 – jest to lekka wersja Visual Studio 2019, która zawiera minimalny wymagany zestaw komponentów do kompilacji kodu.
Aby w pełni współpracować z naszym projektem w C++ będziemy potrzebować dodatkowych komponentów, a mianowicie:

  • Obciążenie narzędziami C++
  • Zestaw narzędzi v141
  • Zestaw SDK systemu Windows 10 (10.0.17134.0)

Możesz zainstalować rozszerzony zestaw narzędzi automatycznie, korzystając z pliku konfiguracyjnego w formacie JSON. Zawartość pliku konfiguracyjnego:

Pełną listę dostępnych komponentów można znaleźć w witrynie dokumentacji 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"
  ]
}

Plik dokera uruchamia skrypt instalacyjny i dla wygody dodaje ścieżkę do plików wykonywalnych narzędzi do budowania do zmiennej środowiskowej PATH. Wskazane jest również usunięcie niepotrzebnych plików i katalogów, aby zmniejszyć rozmiar 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)

Na tym etapie nasz obraz do kompilacji aplikacji w C++ jest gotowy i możemy od razu przystąpić do tworzenia dockerowego, wieloetapowego buildu aplikacji.

Wieloetapowe działanie

Wykorzystamy utworzony obraz ze wszystkimi narzędziami na pokładzie jako obraz kompilacji. Podobnie jak w poprzednim skrypcie pliku dockerfile, dodamy możliwość dynamicznego określania numeru wersji/tagu obrazu, aby ułatwić ponowne wykorzystanie kodu. Ważne jest, aby dodać etykietę as builder do obrazu montażu w instrukcji FROM.

ARG WINDOWS_OS_VERSION=1809
FROM buildtools:$WINDOWS_OS_VERSION as builder

Teraz czas na zbudowanie aplikacji. Wszystko tutaj jest dość proste: skopiuj kod źródłowy i wszystko z nim związane i rozpocznij proces kompilacji.

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

Ostatnim etapem tworzenia finalnego obrazu jest określenie obrazu bazowego aplikacji, w którym będą znajdować się wszystkie artefakty kompilacji oraz pliki konfiguracyjne. Aby skopiować skompilowane pliki z obrazu złożenia pośredniego, należy określić parametr --from=builder w instrukcji COPY.

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

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

Teraz pozostaje tylko dodać niezbędne zależności, aby nasza aplikacja działała i określić polecenie uruchomienia za pomocą instrukcji ENTRYPOINT lub CMD.

wniosek

W tym artykule mówiłem o tym jak stworzyć pełnoprawne środowisko kompilacji dla aplikacji C++ wewnątrz kontenera pod Windows oraz jak wykorzystać możliwości wieloetapowych buildów dockera do stworzenia pełnoprawnych obrazów naszej aplikacji.

Źródło: www.habr.com

Dodaj komentarz