大家好!我叫Andrey,是Exness開發團隊的DevOps工程師。我的主要工作是建置、部署和維護運行在作業系統上的Docker應用程式。 Linux (以下簡稱作業系統)。不久前,我曾接到一個類似的任務,但專案的目標作業系統變成了 Windows Server 以及一系列 C++ 專案。對我來說,這是我第一次在作業系統下與 Docker 容器進行如此深入的接觸。 Windows 以及一般的 C++ 應用程式。這讓我獲得了有趣的經驗,並讓我了解了作業系統中應用程式容器化的一些複雜細節。 Windows.

在這篇文章中,我想告訴你我遇到過哪些困難以及我是如何解決這些困難的。 我希望這對您當前和未來的挑戰有所幫助。 享受閱讀!
為什麼是容器?
該公司已擁有 Hashicorp Nomad 容器編排器及其相關組件(Consul 和 Vault)的現有基礎設施。因此,應用容器化被選為交付最終解決方案的統一方法。由於該專案的基礎設施包含運行作業系統版本的 Docker 主機,因此 Windows Server 如果您同時使用 Core 1803 和 1809,則必須為 1803 和 1809 分別建置不同的 Docker 映像版本。在版本 1803 中,請務必記住 Docker 建置主機的版本號碼必須與基礎 Docker 映像的版本號碼以及將要啟動該映像容器的主機的版本號碼相符。版本 1809 解決了這個問題。您可以點擊此處了解更多。 .
為什麼要多階段?
開發團隊工程師沒有或非常有限地存取建置主機;無法快速管理用於在這些主機上建置應用程式的元件集,例如,為 Visual Studio 安裝附加工具集或工作負載。 因此,我們決定將建置應用程式所需的所有元件安裝到建置 Docker 映像中。 如有必要,您可以快速僅更改 dockerfile 並啟動用於建立此映像的管道。
從理論到行動
在理想的 Docker 多階段映像建置中,建置應用程式的環境是在建置應用程式本身的同一個 Dockerfile 腳本中準備的。 但在我們的例子中,加入了一個中間環節,即初步建立 docker 映像以及建置應用程式所需的一切的步驟。 這樣做是因為我想使用 docker 快取功能來減少所有依賴項的安裝時間。
讓我們來看看建立這個映像的 dockerfile 腳本的要點。
要建立不同作業系統版本的映像,可以在dockerfile中定義一個參數,在建置過程中透過該參數傳遞版本號,同時它也是基礎映像的標籤。
完整的 Microsoft 圖像標籤列表 Windows Server 可以被找尋到 .
ARG WINDOWS_OS_VERSION=1809
FROM mcr.microsoft.com/windows/servercore:$WINDOWS_OS_VERSION
預設使用說明中的命令 RUN 作業系統中的 Dockerfile 內部 Windows 這些命令在 cmd.exe 控制台中執行。為了簡化腳本編寫並擴展所用命令的功能,我們將使用以下指令將命令執行控制台重新定義為 PowerShell: SHELL.
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]
下一步是安裝 Chocolatey 套件管理器和必要的套件:
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'
要使用 Chocolatey 安裝軟體包,您只需將它們作為列表傳遞,或者如果您需要為每個軟體包傳遞唯一的參數,則一次安裝一個。 在我們的範例中,我們使用了 XML 格式的清單文件,其中包含所需套件及其參數的清單。 其內容如下圖所示:
<?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>
接下來,我們安裝應用程式建置環境,即 MS Build Tools 2019 - 這是 Visual Studio 2019 的輕量級版本,其中包含編譯程式碼所需的最少元件集。
為了充分使用我們的 C++ 項目,我們需要額外的元件,即:
- 工作負載 C++ 工具
- 工具集 v141
- Windows 10 SDK(10.0.17134.0)
您可以使用 JSON 格式的設定檔自動安裝一組擴充工具。 設定檔內容:
可用組件的完整清單可以在文件網站上找到 .
{
"version": "1.0",
"components": [
"Microsoft.Component.MSBuild",
"Microsoft.VisualStudio.Workload.VCTools;includeRecommended",
"Microsoft.VisualStudio.Component.VC.v141.x86.x64",
"Microsoft.VisualStudio.Component.Windows10SDK.17134"
]
}
dockerfile運行安裝腳本,為了方便,將建置工具可執行檔案的路徑新增至環境變數中 PATH。 也建議刪除不必要的檔案和目錄以減少圖像的大小。
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)
在此階段,用於編譯 C++ 應用程式的映像已準備就緒,我們可以直接繼續建立應用程式的 docker 多階段建置。
多階段行動
我們將使用創建的映像以及板上的所有工具作為構建映像。 與先前的 dockerfile 腳本一樣,我們將新增動態指定版本號/映像標籤的功能,以便於程式碼重複使用。 添加標籤很重要 as builder 到說明中的組裝圖像 FROM.
ARG WINDOWS_OS_VERSION=1809
FROM buildtools:$WINDOWS_OS_VERSION as builder
現在是時候建立應用程式了。 這裡的一切都非常簡單:複製原始碼和與之相關的所有內容,然後開始編譯過程。
COPY myapp .
RUN nuget restore myapp.sln ;
msbuild myapp.sln /t:myapp /p:Configuration=Release
建立最終映像的最後階段是指定應用程式的基礎映像,所有編譯工件和設定檔都將位於其中。 若要從中間程序集映像複製已編譯的文件,必須指定參數 --from=builder 在說明中 COPY.
FROM mcr.microsoft.com/windows/servercore:$WINDOWS_OS_VERSION
COPY --from=builder C:/x64/Release/myapp/ ./
COPY ./configs ./
現在剩下的就是添加應用程式運行所需的依賴項,並透過說明指定啟動命令 ENTRYPOINT 或 CMD.
結論
本文介紹如何在容器內為 C++ 應用程式建立一個功能齊全的編譯環境。 Windows 以及如何使用 Docker 的多階段建置功能來建立我們應用程式的完整映像。
來源: www.habr.com
