在两年前,我曾经写过一篇类似的文章,里面简单的说了一下步骤。但是那个时候的Jenkins是直接安装在主机上的,Unity也是直接安装在主机上,而且也有桌面环境,可以方便的激活。今天的这篇文章则是介绍怎么使用Docker来将这些环境给一键设立。

本次能够正常的运行,靠的是下面这两个镜像:
Docker Hub – Jenkins
Docker Hub – Unity

下面就来开始我们的教程。

首先,是把Jenkins搭起来。搭Jenkins非常非常简单,只需要编写下面的这样的docker-compose.yml然后启动就可以了

version: '2.0'
services:
  jenkins:
    image: jenkins/jenkins:lts-slim
    ports:
    - "8082:8080"
    - "50000:50000"
    volumes:
    - ./jenkins_home:/var/jenkins_home

第一次安装的时候建议使用 docker-compose up来看控制台输出,因为第一次安装是需要密钥的,而这个密钥则会打印在控制台里面。

安装完Jenkins之后,我们可以准备在里面装Unity的Docker了。先在Jenkins的插件中心找到Docker Pipeline插件并安装,这个插件是用于提供Docker环境命令的。然后到设置中新增Docker的安装。由于我在这里不想修改Jenkins的镜像,所以就让Jenkins自己下载Docker命令了。

接着,我们需要将主机的Docker“映射”到Jenkins的Docker里面,这样才不会出现“Docker on Docker”的情况,以防止一些无法预料的问题发生。此时,我们可以修改前面的docker-compose.yml文件

version: '2.0'
services:
  jenkins:
    image: jenkins/jenkins:lts-slim
    group_add:
    - 112
    ports:
    - "8082:8080"
    - "50000:50000"
    volumes:
    - ./jenkins_home:/var/jenkins_home
    - /var/run/docker.sock:/var/run/docker.sock
    - /etc/docker/daemon.json:/etc/docker/daemon.json

上面的volumes项目将docker.sock给映射到Jenkins中,这样Jenkins里面的Docker就会直接调用主机的Docker环境了。同时,我们在这里新增了一个用户组”112″。这个用户组实际上是docker的用户组,你可以查看你的设备上的对应用户组的ID并修改。添加这个用户组的目的是为了给Jenkins用户执行权限,不然在运行Docker的时候报Permission Deny。

同时,我也把daemon.json给映射进去了,(虽然现在仔细想想好像可能没啥用),是为了让Jenkins上的Docker也能使用对应的Mirror加速下载。

一切就绪后,我们可以来准备运行Unity获取许可证了。

我们先拉取需要的镜像

docker pull gableroux/unity3d:2019.3.7f1

然后运行Unity激活

docker run -it --rm \
-v "$(pwd):/root/project" \
gableroux/unity3d:2019.3.7f1 \
bash

xvfb-run --auto-servernum --server-args='-screen 0 640x480x24' \
/opt/Unity/Editor/Unity \
-logFile /dev/stdout \
-batchmode \
-username "$UNITY_USERNAME" -password "$UNITY_PASSWORD"

运行之后,会出现类似于以下内容的东西,将他们复制并保存为扩展名为alf的文件准备手动激活

<?xml version="1.0" encoding="UTF-8"?><root><SystemInfo><IsoCode>en</IsoCode><UserName>(unset)</UserName>...</SystemInfo>...</root>

访问 https://license.unity3d.com/manual/,上传刚刚的alf文件,然后手动激活并下载许可证文件。许可证文件之后需要放置到~/.local/share/unity3d/Unity/目录下。

然后我们就可以正式的来写Jenkins的Pipeline了。我这里给一个示例,并在下面给出对应的说明

pipeline {
    agent any
    stages {
        stage('prepare') {
            steps {
                script {
                    checkout([$class: 'GitSCM', branches: [[name: '*/master']], serRemoteConfigs: [[credentialsId: 'lotlab_bot', url: 'https://xxxxxxx']]])
                }
                withCredentials([file(credentialsId: 'unity_license', variable: 'UNITY_LICENSE_FILE')]) {
                    sh label: '', script: 'cp $UNITY_LICENSE_FILE $WORKSPACE/Unity_lic.ulf && chmod 664 $WORKSPACE/Unity_lic.ulf'
                }
            }
        }
        stage('Build Windows') {
            steps {
                withDockerContainer(args: "-u root -it -v /path-to-docker-root:/root -v /path-to-docker-workspace:/root/project", image: 'gableroux/unity3d:2019.4.8f1-windows', toolName: 'sample') {
                    sh label: 'Copy Unity License', script: 'mkdir -p /root/.local/share/unity3d/Unity/ && cp /root/project/Unity_lic.ulf /root/.local/share/unity3d/Unity/Unity_lic.ulf'
                    sh label: 'Build', script: '''${UNITY_EXECUTABLE:-xvfb-run --auto-servernum --server-args=\'-screen 0 640x480x24\' /opt/Unity/Editor/Unity} \\
                      -projectPath /root/project \\
                      -quit \\
                      -batchmode \\
                      -CacheServerIPAddress 192.168.114.194:8126 \\
                      -executeMethod CustomBuilder.Editor.Builder.BuildWindows \\
                      -logFile /dev/stdout
                    '''
                    sh label: 'Fix Permission', script: 'chown 1000:1000 /root/project/Build -R'
                }
            }
        }
    }
}

从上到下解释一些可能有坑的地方:
1. withCredentials 一节中,我们将之前的许可证文件给复制到了工作空间目录下。你也可以在后面的Docker运行参数中直接放在对应的文件夹下。
2. Docker 的参数说明
1. -u root: 使用root用户跑这个镜像。这个Unity的镜像只有一个root用户,而这个Docker插件则会尝试使用1000:1000用户运行。我们在这里需要手工将其覆盖。
2. -v /path-to-docker-root:/root: 将root用户目录绑定到某个目录中。因为Unity会在用户目录下生成一些缓存,为了加快缓存速度所以我就将其映射出来持久化保存了。如果你不需要可以删掉这一行命令。
3. -v /path-to-docker-workspace:/root/project: 将工作区映射到设定的目录下。为什么我不在这使用环境变量呢?由于这个Docker实际上是主机的Docker吗,所以这个工作区路径是主机上而非Jenkins镜像上的路径。
3. Unity的运行参数可以参考Unity的手册。我这里调用了一个自定义的构建方法可以构建配置好的Windows目标。
4. 最后一行的Fix Permission:由于是用的root用户打包,所以生成的文件也是root用户的。我们需要将这个权限给改回来。

以上就是要注意的全部内容了,现在你就可以享受Docker化的Unity打包流程了!


1 条评论

RE: Jenkins Docker的配置与使用 – LotLab · 2022 年 3 月 31 日 上午 11:30

[…] 我在两年前和四年前 写过如何使用Jenkins构建Unity项目的教程。现在看来这两个教程都有些不足的地方,所以我又又又来更新这个教程了。 […]

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用*标注