こんにちは、金融ソリューション事業部の孫です。
本記事ではUEアプリ用のカスタムWindows Node AMIを作成します。
これまでの記事ではLinuxベースのノードで運用しておりました。
しかし、開発プロジェクトによってはWindowsノードは必須となるケースがあるので、その場合に本記事の知見が読者の皆様にご参考になれば幸いです。
前編では、Unreal Editorを動作させるためのコンテナイメージの構築に焦点を当てています。
後編では、そのUnreal EditorコンテナイメージをWindows AMIに統合し、EKSでノードとして使用できるようにします。
- はじめに
- コンテナイメージの構築環境
- 実施手順
- 1. 既存のLinuxコンテナイメージの構築プロセス
- 2. Windowsコンテナイメージ構築方法の検討
- 3. Windowsコンテナ用のDockerfileの作成
- 4.Windowsコンテナのテスト
- 問題集
- おわりに
- 参考文献
はじめに
まず、Unreal EngineのRuntimeとDevelopmentコンテナイメージの違いを説明します:
- Runtimeコンテナイメージ:このタイプのコンテナは、パッケージ化されたUEアプリケーションを実行するための環境のみを含み、完全な開発機能は含まれていません。これは
Java Runtime
や.NET Runtime
に例えることができます。 - Developmentコンテナイメージ:このタイプのコンテナにはUnreal Editorおよびその他のビルドツールが含まれており、完全なUnreal Engineのバージョンに相当します。これは
Java SDK
や.NET SDK
に例えることができます。
UEの公式ドキュメントより、技術的および法的な制約のため、WindowsベースのDockerイメージは Runtimeコンテナイメージのみ提供という制限がわかりました。
制限を乗り越えるために、TensorWorksとue4-dockerプロジェクトのドキュメントを参考にし、実作のWindows Developmentコンテナイメージを作成します。
コンテナイメージの構築環境
Unreal Engine 5のWindows Developmentコンテナイメージを構築するために、以下の環境を使用しました:
- OS:Windows 11 Pro 64ビット
- CPU:Intel Core i5-13500k
- メモリ:32GB
- GPU:NVIDIA GeForce RTX 3080
- Unreal Engine:5.1.1
- Docker Desktop:4.30.0
※注意:Docker DesktopはWindowsコンテナモードに切り替えてください。
実施手順
1. 既存のLinuxコンテナイメージの構築プロセス
Epic社はLinux DevelopmentコンテナイメージのDockerfileを公開しており、これを参考にWindows Developmentコンテナイメージの構築プロセスを設計します。
- ベースイメージと環境の設定
まず、Dockerfileで必要なベースイメージを設定します。
Linuxの配布版はUbuntu、CentOS、Red Hatなど多岐にわたるため、ベースイメージは開発者が選択するパラメーター形式で設定されます。
ARG BASEIMAGE
FROM ${BASEIMAGE} as prerequisites
次に、NVIDIA GPU Driverをインストールするために、環境変数を設定しています。
ENV DEBIAN_FRONTEND=noninteractive
ENV NVIDIA_DRIVER_CAPABILITIES ${NVIDIA_DRIVER_CAPABILITIES},compute,display,video
RUN apt-get update && apt-get install -y --no-install-recommends build-essential
...
libxv1 x11-xkb-utils xauth xfonts-base xkb-data
- ユーザー作成
非ルートユーザーを作成し、Git LFSを設定し、Gitクローン操作のための認証ヘルパーをインストールします。
RUN useradd --create-home --home /home/ue4 --shell /bin/bash --uid 1000 ue4
RUN git lfs install
...
RUN mkdir /home/ue4/UnrealEngine && \
cd /home/ue4/UnrealEngine && \
git init && \
git remote add origin "$GIT_REPO" && \
git fetch --progress --depth 1 origin "$GIT_BRANCH" && \
git checkout FETCH_HEAD
- UE Dependenciesのインストール
Setup.shスクリプトを実行してUEに必要なパッケージをインストールします。
RUN --mount=type=cache,target=/home/ue4/gitdeps,uid=1000,gid=1000 sudo apt-get update && \
./Setup.sh --exclude=Android --exclude=Mac --exclude=Win32 --exclude=Win64
RUN ./Engine/Build/BatchFiles/Linux/Build.sh UnrealHeaderTool Linux Development -SkipBuild
RUN ./Engine/Build/BatchFiles/RunUAT.sh ...
- 最終イメージの作成
UEの実行ファイルを新しいクリーンなイメージにコピーし、最終的な成果物にします。
COPY --from=builder --chown=ue4:ue4 /home/ue4/UnrealEngine/LocalBuilds/Engine/Linux /home/ue4/UnrealEngine
...
2. Windowsコンテナイメージ構築方法の検討
LinuxのDevelopment Dockerfileを解析した上で、UEを実行するコンテナを作成する方法を理解しました。
その中でも、最も重要なのはUEのソースコードをコンパイルすることです。
WindowsシステムでUEをインストールする際、 Epic Games Launcher
というGUIツールがありますが、このツールはコンテナ内では使用できません。
したがって、WindowsコンテナにUEを搭載するには、ソースコードからのコンパイルのみ可能です。
Linuxコンテナの構築プロセスを参考にして、以下の三つの主要プロセスを設計しました。
① ソースコードのコンパイル環境の設定と必要なツール・ライブラリのダウンロード
Windowsには、Linuxと同様にコマンドラインからソフトウェアをインストールできるツールChocolatey
があります。
まずはそれをインストールします。そして、
Chocolatey
を利用してソースビルドと実行用のVisual Studio 2019
DirectX
Vulkan
.Net Framework
などのツールをインストールします。
※ Visual Studioのバージョンについては、公式の推奨バージョンがあり、 公式ドキュメントを確認して選定してください。② UEのソースコードのダウンロードとコンパイル
ソースコードのダウンロードは、LinuxのDockerfileの処理を参考にします。ソースコードのコンパイルには、UEのソース内にある
\Engine\Build\BatchFiles\RunUAT.bat
ビルドツールを使用します。また、イメージサイズを縮小するために、デバッグ時にのみ使用されるDebugSymbolsやプロジェクト作成時に含まれるテンプレートプロジェクトおよびサンプルを削除します。
③ コンパイル済みの実行ファイルを新しいクリーンなイメージに移動して構築を完了
このプロセスは、LinuxのDockerfileの処理を参考にします。また、WindowsのRuntimeイメージのDockerfileも確認すると、
vendor-specific graphics APIs
を有効にするためのPowershellスクリプトがあります。それも忘れずコンテナ内にコピーします。
※Windowsのコアアーキテクチャに関連しているため、詳細はこのブログを確認してください。
3. Windowsコンテナ用のDockerfileの作成
上記に検討したプロセスに従って、Dockerfileを作成します。
ARG BASEIMAGE="mcr.microsoft.com/windows/server:ltsc2022" FROM ${BASEIMAGE} as prerequisites SHELL ["cmd", "/S", "/C"] # Install Chocolatey RUN powershell -NoProfile -ExecutionPolicy Bypass -Command "$env:chocolateyVersion = '1.4.0'; Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && echo. && echo.RUN directive complete. Docker will now commit the filesystem layer to disk. && echo.Note that for large filesystem layers this can take quite some time. && echo.Performing filesystem layer commit... && echo. # Install the rest of our build prerequisites and clean up afterwards to minimise image size COPY install-prerequisites.ps1 C:\ ARG VISUAL_STUDIO_BUILD_NUMBER=16 RUN powershell -ExecutionPolicy Bypass -File C:\install-prerequisites.ps1 %VISUAL_STUDIO_BUILD_NUMBER% && echo. && echo.RUN directive complete. Docker will now commit the filesystem layer to disk. && echo.Note that for large filesystem layers this can take quite some time. && echo.Performing filesystem layer commit... && echo.
install-prerequisites.ps1 の内容は以下です。
# variable and importing the Chocolatey profile module. $env:ChocolateyInstall = Convert-Path "$( (Get-Command choco).Path )\..\.." Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" # Install the chocolatey packages we need choco install --no-progress -y git --params "'/GitOnlyOnPath /NoAutoCrlf /WindowsTerminal /NoShellIntegration /NoCredentialManager'" # pdbcopy.exe from Windows SDK is needed for creating an Installed Build of the Engine choco install --no-progress -y choco-cleaner python vcredist-all windows-sdk-10-version-1809-windbg # Reload our environment variables from the registry so the `git` command works Update-SessionEnvironment # Gather the required DirectX runtime files, since Windows Server Core does not include them Invoke-WebRequest -Uri "https://download.microsoft.com/download/8/4/A/84A35BF1-DAFE-4AE8-82AF-AD2AE20B6B14/directx_Jun2010_redist.exe" -OutFile "$env:TEMP\directx_redist.exe" Start-Process -FilePath "$env:TEMP\directx_redist.exe" -ArgumentList "/Q", "/T:$env:TEMP" -Wait expand "$env:TEMP\APR2007_xinput_x64.cab" -F:xinput1_3.dll C:\Windows\System32\ expand "$env:TEMP\Jun2010_D3DCompiler_43_x64.cab" -F:D3DCompiler_43.dll C:\Windows\System32\ expand "$env:TEMP\Feb2010_X3DAudio_x64.cab" -F:X3DAudio1_7.dll C:\Windows\System32\ expand "$env:TEMP\Jun2010_XAudio_x64.cab" -F:XAPOFX1_5.dll C:\Windows\System32\ expand "$env:TEMP\Jun2010_XAudio_x64.cab" -F:XAudio2_7.dll C:\Windows\System32\ # Retrieve the DirectX shader compiler files needed for DirectX Raytracing (DXR) Invoke-WebRequest -Uri "https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.6.2104/dxc_2021_04-20.zip" -OutFile "$env:TEMP\dxc.zip" Expand-Archive -Path "$env:TEMP\dxc.zip" -DestinationPath "$env:TEMP" Copy-Item -Path "$env:TEMP\bin\x64\dxcompiler.dll" C:\Windows\System32\ Copy-Item -Path "$env:TEMP\bin\x64\dxil.dll" C:\Windows\System32\ # Gather the Vulkan runtime library Invoke-WebRequest -Uri "https://sdk.lunarg.com/sdk/download/latest/windows/vulkan-runtime-components.zip?u=" -OutFile "$env:TEMP\vulkan-runtime-components.zip" Expand-Archive -Path "$env:TEMP\vulkan-runtime-components.zip" -DestinationPath "$env:TEMP" Copy-Item -Path "*\x64\vulkan-1.dll" -Destination C:\Windows\System32\ $visual_studio_build = $args[0] $windows_sdk_version = 20348 Invoke-WebRequest -Uri "https://aka.ms/vs/17/release/vs_buildtools.exe" -OutFile "$env:TEMP\vs_buildtools.exe" # NOTE: Microsoft.NetCore.Component.SDK only exists for VS2019+. And it is actually *needed* only for UE5 $vs_args = @( "--quiet", "--wait", "--norestart", "--nocache", "--installPath", "C:\BuildTools", "--channelUri", "https://aka.ms/vs/$visual_studio_build/release/channel", "--installChannelUri", "https://aka.ms/vs/$visual_studio_build/release/channel", "--channelId", "VisualStudio.$visual_studio_build.Release", "--productId", "Microsoft.VisualStudio.Product.BuildTools", "--locale", "en-US", "--add", "Microsoft.VisualStudio.Workload.VCTools", "--add", "Microsoft.VisualStudio.Workload.MSBuildTools", "--add", "Microsoft.VisualStudio.Component.NuGet", "--add", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "--add", "Microsoft.VisualStudio.Component.Windows10SDK.$windows_sdk_version", "--add", "Microsoft.Net.Component.4.5.TargetingPack", "--add", "Microsoft.Net.Component.4.6.2.TargetingPack", "--add", "Microsoft.Net.ComponentGroup.DevelopmentPrerequisites", "--add", "Microsoft.NetCore.Component.SDK", "--add", "Microsoft.NetCore.Component.Runtime.3.1" ) # Install the Visual Studio Build Tools workloads and components we need Start-Process -FilePath "$env:TEMP\vs_buildtools.exe" -ArgumentList $vs_args -Wait # Clean up any temp files generated during prerequisite installation Remove-Item -LiteralPath "$env:TEMP" -Recurse -Force New-Item -Type directory -Path "$env:TEMP" # This shaves off ~300MB as of 2021-08-31 choco-cleaner if (Test-Path "$env:APPDATA\NuGet") { Remove-Item -LiteralPath "$env:APPDATA\NuGet" -Recurse -Force } # Display a human-readable completion message Write-Output "Finished installing build prerequisites and cleaning up temporary files."
- ステップ2:UEのソースコードのダウンロードとコンパイル
UEのソースコードをダウンロードするためには、EpicのGitHubで登録開発者になる必要があります。詳細は公式ガイドを参照してください。
git clone
コマンドを実行する前に、GitHubアカウントにログインし、システムにログイン状態を保存してください。
FROM prerequisites as source # Enable verbose output for steps that patch files? ARG VERBOSE_OUTPUT=0 ARG GIT_REPO="https://github.com/EpicGames/UnrealEngine.git" # The git branch/tag/commit that we will checkout ARG GIT_BRANCH="5.1" # Clone the UE5 git repository using the host-supplied credentials WORKDIR C:\ RUN mkdir C:\UnrealEngine && ` cd C:\UnrealEngine && ` git init && ` git remote add origin %GIT_REPO% && ` git fetch --progress --depth 1 origin %GIT_BRANCH% && ` git checkout FETCH_HEAD && echo. && echo.RUN directive complete. Docker will now commit the filesystem layer to disk. && echo.Note that for large filesystem layers this can take quite some time. && echo.Performing filesystem layer commit... && echo. # Run post-clone setup steps # (Note that the `-no-cache` flag disables caching of dependency data in `.git/ue4-gitdeps`, saving disk space) WORKDIR C:\UnrealEngine RUN Setup.bat -no-cache --exclude=Android --exclude=Mac --exclude=Linux && echo. && echo.RUN directive complete. Docker will now commit the filesystem layer to disk. && echo.Note that for large filesystem layers this can take quite some time. && echo.Performing filesystem layer commit... && echo. # Remove the sample `XXX` example platform cod RUN rmdir /s /q C:\UnrealEngine\Engine\Platforms\XXX 2>NUL || exit 0 && echo. && echo.RUN directive complete. Docker will now commit the filesystem layer to disk. && echo.Note that for large filesystem layers this can take quite some time. && echo.Performing filesystem layer commit... && echo. # escape=` FROM source as builder # Set the changelist number in Build.version to ensure our Build ID is generated correctly ARG CHANGELIST COPY set-changelist.py C:\set-changelist.py RUN python C:\set-changelist.py C:\UnrealEngine\Engine\Build\Build.version %CHANGELIST% && echo. && echo.RUN directive complete. Docker will now commit the filesystem layer to disk. && echo.Note that for large filesystem layers this can take quite some time. && echo.Performing filesystem layer commit... && echo. # Remove the .git directory to disable UBT `git status` calls and speed up the build process RUN if exist C:\UnrealEngine\.git rmdir /s /q C:\UnrealEngine\.git && echo. && echo.RUN directive complete. Docker will now commit the filesystem layer to disk. && echo.Note that for large filesystem layers this can take quite some time. && echo.Performing filesystem layer commit... && echo. # Create an Installed Build of the Engine WORKDIR C:\UnrealEngine RUN .\Engine\Build\BatchFiles\RunUAT.bat BuildGraph ` -target="Make Installed Build Win64" ` -script=Engine/Build/InstalledEngineBuild.xml ` -set:HostPlatformOnly=true ` -set:WithDDC=true ` -set:VS2019=true && ` (if exist C:\UnrealEngine\LocalBuilds\InstalledDDC rmdir /s /q C:\UnrealEngine\LocalBuilds\InstalledDDC) && ` rmdir /s /q C:\UnrealEngine\Engine && echo. && echo.RUN directive complete. Docker will now commit the filesystem layer to disk. && echo.Note that for large filesystem layers this can take quite some time. && echo.Performing filesystem layer commit... && echo.
- ステップ3:コンパイル済みの実行ファイルを新しいクリーンなイメージに移動して構築を完了
コンパイル済みのファイルを新しいコンテナイメージに移動し、最終イメージの容量を削減するためにクリーンアップを行います。
# Copy the Installed Build into a clean image, discarding the source tree FROM prerequisites as minimal # Copy the Installed Build files from the builder image COPY --from=builder C:\UnrealEngine\LocalBuilds\Engine\Windows C:\UnrealEngine COPY --from=builder C:\UnrealEngine\Components\DDC C:\UnrealEngine WORKDIR C:\UnrealEngine # Enable NVIDIA API Support COPY enable-graphics-apis.ps1 C:\ RUN powershell -ExecutionPolicy Bypass -File C:\enable-graphics-apis.ps1 && echo. && echo.RUN directive complete. Docker will now commit the filesystem layer to disk. && echo.Note that for large filesystem layers this can take quite some time. && echo.Performing filesystem layer commit... && echo.
以上で、Dockerfileの作成は完了しました。
そして、以下のコマンドを実行し、ビルドします。
$ docker build -t unreal-engine-dev-windows-5.1 .
4.Windowsコンテナのテスト
テスト1:コンテナを利用してプロジェクトを編集する
Runtimeコンテナとは異なり、今回はUnreal Editorもイメージに含めました。
これにより、プロジェクトを開いて開発作業が行えます。
テスト前に、Unreal Editor GUIを使用してUEプロジェクトを作成します。
※コマンドを使用してプロジェクトの作成も可能ですが、UEプラグインのインストールはGUIで行う方が便利ですので、今回はGUIを使用してプロジェクトを作成しました。
Unreal Editorを開き、テンプレートを使用して WinContainerTest
という新しいプロジェクトを作成します。
作成が完了したら、Pixel Streamingプラグインを有効にします。
メニューバーから Edit
⇒ Plugins
を選択し、検索ボックスに Pixel Streaming
を入力します。
プラグインをチェックしてUnreal Editorを再起動し、インストールを完了します。
全部完了したら、コンテナを使用してこのプロジェクトを起動し、Web上で確認できるかを確認します。
以下のDockerコマンドを実行して、プロジェクトをコンテナ内のUnreal Editorで開きます:
$ docker run --rm -ti \ --isolation process --device class/5B45201D-F2F2-4F3B-85BB-30FF1F953599 \ -v "D:\Unreal Projects\WinContainerTest:C:\WinContainerTest" \ -p 8080:80 --entrypoint "cmd.exe" unreal-engine-dev-windows-5.1:latest \ /S /C C:\\UnrealEngine\\Engine\\Binaries\\Win64\\UnrealEditor-Cmd.exe \ C:\\wincontainertest\\WinContainerTest.uproject -AudioMixer \ -RenderOffscreen -stdout -FullStdOutLogOutput -unattended \ -EditorPixelStreamingStartOnLaunch=true
※ここで注意していただきたい点は以下のとおりです:
- WindowsでコンテナのGPUサポートについて
- GPUリソースを取得するために、以下のパラメータを追加する必要
--isolation process --device class/5B45201D-F2F2-4F3B-85BB-30FF1F953599
- 参照文献: WindowsコンテナでのGPUアクセラレーション
- GPUリソースを取得するために、以下のパラメータを追加する必要
- 起動パラメータについて:
-EditorPixelStreamingStartOnLaunch=true
パラメータを使用すると、バックグラウンド起動時に自動的にPixel Streamingサービスが開始されます-stdout -FullStdOutLogOutput
パラメータを使用すると、フルログが出力されます-unattended
パラメータを使用すると、UEプロセスが終了したときにDialogBoxW
やMessageBoxW
GUIポップアップを呼び出さず、正常に閉じられます
プロジェクトのロードが完了したら、ログにPixelStreamingサービスの開始ログが確認できます。
この時点で、ブラウザを開いて URL127.0.0.1:8080
を入力すると、UEプロジェクトの編集画面が表示されます。
このWebブラウザ上で、遠隔操作でUnreal Editorを使用してプロジェクトを開発することができ、非常に便利でしょう。
テスト2:コンテナを使用してアプリケーションをパッケージングする
コマンドラインを開き、以下のDockerコマンドを実行します:
$ docker run --rm -ti -v "D:\Unreal Projects\WinContainerTest:C:\WinContainerTest" \ --entrypoint "cmd.exe" unreal-engine-dev-windows-5.1:latest /S /C \ C:\\UnrealEngine\\Engine\\Build\\BatchFiles\\RunUAT.bat BuildCookRun \ -clientconfig=Development -serverconfig=Development \ -project=C:\\WinContainerTest\\WinContainerTest.uproject \ -utf8output -nodebuginfo -allmaps -noP4 -cook -build -stage \ -prereqs -pak -archive \ -archivedirectory=C:\\WinContainerTest\\Packages \ -platform=Win64
完了後、[project]/Packages
フォルダで、パッケージされたファイルが確認できます。
問題集
今回のコンテナを使用しているときに、いくつかの問題が発見されました、ここで共有いたします。
- 新規作成されたUEプロジェクトは、GUIで一度も開いたことがない場合、コンテナで直接開くことができません。
- これは、プロジェクトを起動する前に、最新のエディターDLLを取得する必要があるためです。
- 解決するには、開く前に、コンテナでプロジェクトのエディターターゲットを一回コンパイルしてください。
bash Build/BatchFiles/Build.bat <ProjectName>Editor Win64 Development <PathToProjectFile>.uproject -WaitMute
- 参考文献:https://blog.mi.hdm-stuttgart.de/index.php/2017/02/11/uat-automation/
- コンテナでプロジェクトを開く速度が遅い。
- これは、キャッシュ(DDC)を再作成する必要があるためです。
- Shared DDCを設定することで解決できます
- 参考文献:Derived Data Cache
Shared DDCの設定方法
まず、プロジェクト用のDDCを作成します。
以下のコマンドを実行すると、プロジェクトフォルダーに Project/DerivedDataCache/DDC.ddp
キャッシュファイルが生成されます。
$ Engine\Binaries\Win64\UnrealEditor.exe ProjectName -run=DerivedDataCache -fill -DDC=CreatePak
次にShared DDCのパスを指定します。[ProjectPath]/Config/DefaultEngine.ini
の最後に以下のコードを追加します。
#Default Engine.ini [DerivedDataBackendGraph] Shared=(Type=FileSystem, ReadOnly=false, Clean=false, Flush=false, DeleteUnused=true, UnusedFileAge=10, FoldersToClean=10, MaxFileChecksPerSec=1, Path=%GAMEDIR%DerivedDataCache/DDC.ddp, EnvPathOverride=UE-SharedDataCachePath, EditorOverrideSetting=SharedDerivedDataCache, CommandLineOverride=SharedDataCachePath)
※Pathをプロジェクトフォルダー内の DerivedDataCache/DDC.ddp
を設定してください。
Shared=(Type=FileSystem,... Path=%GAMEDIR%DerivedDataCache/DDC.ddp,...)
おわりに
今回の記事では、Unreal Editorを含めるWindowsコンテナイメージの構築方法をご紹介しました。
次の後編で、このWindowsコンテナイメージをEKS用のWindows AMIに統合し、Windowsノードとして稼働させる方法を紹介します。
現在、電通総研はweb3領域のグループ横断組織を立ち上げ、Web3およびメタバース領域のR&Dを行っております(カテゴリー「3DCG」の記事はこちら)。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください!
私たちと同じチームで働いてくれる仲間をお待ちしています!
電通総研の採用ページ
参考文献
- Unreal Engine Containers Overview
- Known Limitations
- ue4-docker
- Setting Up Visual Studio
- Unreal Engine Dockerfiles
- Amazon EKS
- Unreal Editor interface
- Derived Data Cache
- Automate deployment with the Unreal Engine using the Unreal Automation Tool (UAT)
- Enabling vendor-specific graphics APIs in Windows containers
執筆:@chen.sun、レビュー:@akutsu.masahiro
(Shodoで執筆されました)