教程:使用 GitHub 和 Docker 创建 Jenkins 管道

重要

许多 Azure 服务都有 Jenkins 插件。其中一些插件将从 2024 年 2 月 29 日开始不受支持。 当前推荐通过 Azure CLI 将 Jenkins 与 Azure 服务集成。 有关详细信息,请参阅适用于 Azure 的 Jenkins 插件一文。

要将应用程序开发的生成和测试阶段自动化,可以使用持续集成和部署 (CI/CD) 管道。 本教程介绍如何在 Azure VM 上创建 CI/CD 管道,包括如何:

  • 创建 Jenkins VM
  • 安装并配置 Jenkins
  • 创建 GitHub 与 Jenkins 之间的 Webhook 集成
  • 通过 GitHub 提交创建并触发 Jenkins 生成作业
  • 创建应用的 Docker 映像
  • 验证 GitHub 提交是否生成新的 Docker 映像并更新正在运行的应用

本教程在 Azure Cloud Shell 中使用 CLI,后者已不断更新到最新版本。 若要打开 Cloud Shell,请从任何代码块的顶部选择“试一试” 。

如果选择在本地安装并使用 CLI,本教程要求运行 Azure CLI 2.0.30 或更高版本。 运行 az --version 即可查找版本。 如果需要进行安装或升级,请参阅安装 Azure CLI

创建 Jenkins 实例

在有关如何在首次启动时自定义 Linux 虚拟机的上一个教程中,已了解如何使用 cloud-init 自动执行 VM 自定义。 本教程使用 cloud-init 文件在 VM 上安装 Jenkins 和 Docker。 Jenkins 是一种常用的开放源代码自动化服务器,它与 Azure 无缝集成以支持持续集成 (CI) 和持续交付 (CD)。 有关如何使用 Jenkins 的更多教程,请参阅Azure 中心中的 Jenkins

在当前 shell 中,创建名为 cloud-init.txt 的文件并粘贴下面的配置。 例如,在不处于本地计算机上的 Cloud Shell 中创建文件。 输入 sensible-editor cloud-init-jenkins.txt 以创建文件并查看可用编辑器的列表。 请确保已正确复制整个 cloud-init 文件,尤其是第一行:

#cloud-config
package_upgrade: true
write_files:
  - path: /etc/systemd/system/docker.service.d/docker.conf
    content: |
      [Service]
        ExecStart=
        ExecStart=/usr/bin/dockerd
  - path: /etc/docker/daemon.json
    content: |
      {
        "hosts": ["fd://","tcp://127.0.0.1:2375"]
      }
runcmd:
  - apt install openjdk-8-jre-headless -y
  - wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add -
  - sh -c 'echo deb https://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
  - apt-get update && apt-get install jenkins -y
  - curl -sSL https://get.docker.com/ | sh
  - usermod -aG docker azureuser
  - usermod -aG docker jenkins
  - service jenkins restart

使用 az group create 创建资源组,然后才能创建 VM。 以下示例在 eastus 位置创建名为 myResourceGroupJenkins 的资源组。

az group create --name myResourceGroupJenkins --location eastus

现在,请使用 az vm create 创建 VM。 使用 --custom-data 参数传递到 cloud-init 配置文件中。 如果已将 cloud-init-jenkins.txt 文件保存在现有工作目录的外部,请提供该文件的完整路径。

az vm create --resource-group myResourceGroupJenkins \
    --name myVM \
    --image UbuntuLTS \
    --admin-username azureuser \
    --generate-ssh-keys \
    --custom-data cloud-init-jenkins.txt

创建并配置 VM 需要几分钟的时间。

若要允许 Web 流量抵达 VM,请使用 az vm open-port 为 Jenkins 流量打开端口 8080,并为用于运行示例应用的 Node.js 应用打开端口 1337

az vm open-port --resource-group myResourceGroupJenkins --name myVM --port 8080 --priority 1001
az vm open-port --resource-group myResourceGroupJenkins --name myVM --port 1337 --priority 1002

配置 Jenkins

若要访问 Jenkins 实例,请获取 VM 的公共 IP 地址:

az vm show --resource-group myResourceGroupJenkins --name myVM -d --query [publicIps] --o tsv

出于安全考虑,需要输入 VM 上某个文本文件中存储的初始管理员密码来启动 Jenkins 安装。 使用上一步骤中获取的公共 IP 地址通过 SSH 连接到 VM:

ssh azureuser@<publicIps>

使用 service 命令验证 Jenkins 是否正在运行。

$ service jenkins status
● jenkins.service - LSB: Start Jenkins at boot time
   Loaded: loaded (/etc/init.d/jenkins; generated)
   Active: active (exited) since Tue 2019-02-12 16:16:11 UTC; 55s ago
     Docs: man:systemd-sysv-generator(8)
    Tasks: 0 (limit: 4103)
   CGroup: /system.slice/jenkins.service

Feb 12 16:16:10 myVM systemd[1]: Starting LSB: Start Jenkins at boot time...
...

查看并复制 Jenkins 安装程序的 initialAdminPassword

sudo cat /var/lib/jenkins/secrets/initialAdminPassword

如果文件尚不可用,请再等待几分钟,以便 cloud-init 完成 Jenkins 和 Docker 安装。

现在,请打开 Web 浏览器并转到 http://<publicIps>:8080。 按如下所示完成初始 Jenkins 安装:

  • 选择“选择要安装的插件”
  • 在顶部的文本框中搜索 GitHub。 选中“GitHub”对应的框,然后选择“安装”
  • 创建第一个管理用户。 输入用户名(例如 admin),然后提供自己的安全密码。 最后,键入全名和电子邮件地址。
  • 选择“保存并完成”
  • 准备好 Jenkins 后,选择“开始使用 Jenkins”
    • 如果开始使用 Jenkins 时 Web 浏览器显示空白页,请重启 Jenkins 服务。 在 SSH 会话中键入 sudo service jenkins restart,然后刷新 Web 浏览器。
  • 根据需要使用创建的用户名和密码登录到 Jenkins。

创建 GitHub Webhook

若要配置与 GitHub 的集成,请从 Azure 示例存储库中打开 Node.js Hello World 示例应用。 若要将存储库分叉到自己的 GitHub 帐户,请选择右上角的“分叉”按钮 。

在创建的分叉中创建 Webhook:

  • 选择“设置” ,然后在左侧选择“Webhook” 。
  • 选择“添加 Webhook”,并在筛选框中输入 Jenkins
  • 对于“有效负载 URL”,输入 http://<publicIps>:8080/github-webhook/。 请确保包含尾部的 /
  • 选择 application/x-www-form-urlencoded 作为“内容类型”。
  • 对于“希望通过哪些事件来触发此 webhook?”选项,请选择“仅推送事件”。
  • 将“活动”设置为已勾选。
  • 单击“添加 Webhook” 。

Add GitHub webhook to your forked repo

创建 Jenkins 作业

若要让 Jenkins 对 GitHub 中的事件(例如提交代码)做出响应,请创建 Jenkins 作业。 为自己的 GitHub 分叉使用 URL。

在 Jenkins 网站中的主页上,选择“创建新作业”

  • 输入 HelloWorld 作为作业名称。 选择“自由风格项目”,然后选择“确定”
  • 在“常规”部分下面,选择“GitHub 项目”并输入分叉的存储库的 URL,例如 https://github.com/cynthn/nodejs-docs-hello-world
  • 在“源代码管理”部分下面,选择“Git”并输入分叉的存储库 .git 的 URL,例如 https://github.com/cynthn/nodejs-docs-hello-world.git
  • 在“生成触发器”部分下面,选择“用于 GITscm 轮询的 GitHub 挂钩触发器”。
  • 在“生成”部分下面,选择“添加生成步骤”。 选择“执行 shell”,并在命令窗口中输入 echo "Test"
  • 选择作业窗口底部的“保存”

测试 GitHub 集成

若要测试 GitHub 与 Jenkins 的集成,请提交分叉中的更改。

返回到 GitHub Web UI,选择分叉的存储库,然后选择“index.js”文件。 选择铅笔图标编辑该文件,使第 6 行的内容如下:

response.end("Hello World!");

若要提交更改,请选择底部的“提交更改”按钮

在 Jenkins 中,作业页左下角的“生成历史记录”部分下面启动了一个新的生成。 选择生成号链接,并选择左侧的“控制台输出”。 从 GitHub 提取代码以及生成操作将消息 Test 输出到控制台时,可以查看 Jenkins 执行的步骤。 每次在 GitHub 中提交内容时,Webhook 都以此方式访问 Jenkins 并触发新的生成。

定义 Docker 生成映像

为了查看基于 GitHub 提交内容运行的 Node.js 应用,让我们生成一个 Docker 映像用于运行该应用。 该映像是从定义如何配置运行应用的容器的 Dockerfile 生成的。

通过 SSH 连接到 VM 后,请切换到根据上一步骤创建的作业命名的 Jenkins 工作区目录。 在本示例中,该目录名为 HelloWorld

cd /var/lib/jenkins/workspace/HelloWorld

在此工作区目录中创建包含 sudo sensible-editor Dockerfile 的文件并粘贴以下内容。 请确保已正确复制整个 Dockerfile,尤其是第一行:

FROM node:alpine

EXPOSE 1337

WORKDIR /var/www
COPY package.json /var/www/
RUN npm install
COPY index.js /var/www/

此 Dockerfile 使用基本 Node.js 映像(该映像使用 Alpine Linux),公开运行 Hello World 应用的端口 1337,复制应用文件并初始化应用。

创建 Jenkins 生成规则

在上一步骤中,已创建一个可将消息输出到控制台的基本 Jenkins 生成规则。 让我们创建生成步骤以使用 Dockerfile 并运行应用。

返回到 Jenkins 实例,选择上一步骤创建的作业。 选择左侧的“配置”,并向下滚动到“生成”部分

  • 删除现有的 echo "Test" 生成步骤。 选择现有生成步骤框右上角的红叉。

  • 选择“添加生成步骤”,然后选择“执行 shell”

  • 在“命令”框中输入以下 Docker 命令,然后选择“保存”

    docker build --tag helloworld:$BUILD_NUMBER .
    docker stop helloworld && docker rm helloworld
    docker run --name helloworld -p 1337:1337 helloworld:$BUILD_NUMBER node /var/www/index.js &
    

Docker 生成步骤将创建一个映像,并使用 Jenkins 生成编号对其进行标记,以便可以维护映像的历史记录。 运行应用的任何现有容器会停止,随后被删除。 然后,将使用该映像启动新的容器,并基于 GitHub 中的最新提交内容运行 Node.js 应用。

测试管道

若要查看整个管道的工作状况,请再次在分叉的 GitHub 存储库中编辑 index.js 文件,并选择“提交更改”。 会基于 GitHub 的 Webhook 在 Jenkins 中启动新作业。 创建 Docker 映像并在新容器中启动应用需要几秒钟时间。

如果需要,请再次获取 VM 的公共 IP 地址:

az vm show --resource-group myResourceGroupJenkins --name myVM -d --query [publicIps] --o tsv

打开 Web 浏览器并输入 http://<publicIps>:1337。 将显示 Node.js 应用,其中反映了 GitHub 分叉中的最新提交内容,如下所示:

Running Node.js app

现在,请再次在 GitHub 中编辑 index.js,并提交更改。 等待几秒钟让作业在 Jenkins 中完成,并刷新 Web 浏览器查看新容器中运行的应用的更新版本,如下所示:

Running Node.js app after another GitHub commit

后续步骤

在本教程中,已将 GitHub 配置为每次提交代码后运行 Jenkins 生成作业,然后部署了一个 Docker 容器用于测试应用。 你已了解如何执行以下操作:

  • 创建 Jenkins VM
  • 安装并配置 Jenkins
  • 创建 GitHub 与 Jenkins 之间的 Webhook 集成
  • 通过 GitHub 提交创建并触发 Jenkins 生成作业
  • 创建应用的 Docker 映像
  • 验证 GitHub 提交是否生成新的 Docker 映像并更新正在运行的应用

转到下一教程,详细了解如何将 Jenkins 与 Azure DevOps Services 集成。