Dockerを用いたUnityビルド環境の構築

f:id:sumzap_engineer_blog:20200302191745p:plain

はじめに

はじめまして。サムザップで新規プロジェクトチームに所属しています三上です。

新規プロジェクトではCI環境構築も担当しており、今回はUnityビルド環境の構築についてお話ししようと思います。
結論から言うと、私のプロジェクトではオンプレミスのサーバーを用意して、JenkinsのマスターとスレーブのコンテナをDocker上で動かして、Dockerが動くホスト側でUnityプロジェクトをビルドしています。

構築方法の検討

Unityビルド環境の構築にあたり、下記の3つの構築方法の選択肢と、それぞれのメリデメを考えました。

構築方法 メリット デメリット
オンプレミス x Jenkinsをサーバーに直接導入 ・Jenkinsの初期構築工数が少ない ・Jenkins増設時の工数が多くなる
・ホストのビルド環境構築の工数が多い
オンプレミス x JenkinsをDockerコンテナ化 ・Jenkinsコンテナ化により、Jenkins増設時の工数が少なくなる
・同一ホストに複数のJenkinsコンテナを構築できる(今回の構成では,同一ホストにマスター・スレーブのコンテナを動かします)
・コンテナの構成情報はDockerfileで確認できる
・Jenkinsの初期構築工数が多い
・ホストのUnityビルド環境構築の工数が多い
Unity Cloud Build ・ビルドサーバーの構築、管理の工数が不要
・複数のUnityバージョンでのビルドが容易
・利用事例が多くない
・あくまで機能はUnity側のビルドに限られる
・ビルド時間のチューニングがしづらい

これらの構築方法を項目ごとに比較すると、下記の表のようになります。

項目 パイプライン機能 初期構築工数 増設構築工数 ビルド環境の保守性 費用
オンプレミス x Jenkinsをサーバーに直接導入 あり 初期コスト(+増設コスト)
オンプレミス x JenkinsをDockerコンテナ化 あり 初期コスト(+増設コスト)
Unity Cloud Build なし(Unity側のビルドのみ) なし なし サブスクリプション

パイプライン機能については、Unity Cloud BuildはUnityビルド機能のみなので、独自のAssetBundleビルド機能を導入したり、他のサービスと連携するには、上位のCIが必要になります。
Dockerを用いる場合は,初期構築工数はJenkinsを直接導入する場合に比べて多くなりますが、コンテナ化することで増設時にホストにJenkinsを構築する工数は少なくできます。
Unityビルド環境の保守性については、Unity Cloud Buildはビルド時間が長いという話と、事例が少ないので、運用中のトラブルシューティングに懸念がありました。
費用については、オンプレミスの場合は基本的にハードウェアの費用のみで、Unity Cloud Buildはサブスクリプションで費用が発生します。

私のプロジェクトでは、

  • Unityビルド環境の保守性
  • 増設コストの軽減

を優先に考え、「オンプレミス x JenkinsをDockerコンテナ化」を選択しました。

構築したUnityビルド環境

システム構成

構築したシステムの構成は下記のようになっています。
ホスト内に、コンテナ化したJenkinsサーバーをマスター・スレーブ構成で構築しています。
Unityのビルドはホスト側で実行するように構築し、スレーブからホストに処理を実行させており、成果物はApp Centerにアップロードし、Slackに通知を送っています。

f:id:sumzap_engineer_blog:20200225220335p:plain
Unityビルド環境のシステム構成

増設時のシステムの構成は、下記のようになる想定です。

f:id:sumzap_engineer_blog:20200225221611p:plain
Unityビルド環境のシステム構成(増設時)

コンテナ⇄ホストの連携

マスターおよびスレーブのDockerfileは下記のようになっています。

# master
FROM jenkins/jenkins:latest

# install required tools
USER root
RUN apt-get update && apt-get install -y \
openssh-client

# install jenkins plugins
COPY plugins.txt /usr/share/jenkins/plugins.txt
RUN /usr/local/bin/plugins.sh /usr/share/jenkins/plugins.txt

# drop back to the regular jenkins user - good practice
USER jenkins
# slave
FROM jenkins/jenkins:latest

# install required tools
USER root

RUN apt-get update && apt-get install -y \
openssh-server

RUN mkdir -p /var/run/sshd

# install jenkins plugins
COPY plugins.txt /usr/share/jenkins/plugins.txt
RUN /usr/local/bin/plugins.sh /usr/share/jenkins/plugins.txt

# jenkins workspace
RUN mkdir -p /jenkins/ws

# set sshd config
RUN echo "ClientAliveInterval 60" >> /etc/ssh/sshd_config
RUN echo "ClientAliveCountMax 10" >> /etc/ssh/sshd_config
CMD /usr/sbin/sshd -D && tail -f /dev/null

sshd_configに応答確認の設定を入れているのは、Unityのビルド中に接続がクローズされてしまうことが多かったためです。
また、スレーブからホストへの接続は下記のようにして、Pipelineからシェルを実行しています。

ssh ${hostUserName}@host.docker.internal ***.sh

host.docker.internalはDockerコンテナが起動しているホスト名です。

まとめ

新規プロジェクトで構築したUnityビルド環境のシステムについてお話ししました。
今回はUnity Cloud Buildを利用しませんでしたが、今後事例が溜まってきたら、利用を検討したいと思っています。
その際には、Jenkinsサーバーもクラウドで構築して、初期コスト&運用コストを減らすのが良いでしょう。
ビルド用のCI環境があるかないかで、プロジェクトの開発速度はかなり違ってきます。
Jenkinsをコンテナ化しておけば、CI構築も楽になりますし、jenkins_homeをコンテナの共有ボリュームに設定してgit管理すれば、まるまる同じ内容のJenkinsサーバーを複製することも容易です。
プロジェクトの初期からCIを導入しておくことで、チームのパフォーマンスの向上に貢献することができるでしょう。

参考文献

超便利! Unity Cloud Build の使い方