教學課程:在 Azure 中的 Linux VM 上以 Jenkins、GitHub 及 Docker 建立開發基礎結構Tutorial: Create a development infrastructure on a Linux VM in Azure with Jenkins, GitHub, and Docker

若要將應用程式開發的組建和測試階段自動化,可以使用持續整合和部署 (CI/CD) 管線。To automate the build and test phase of application development, you can use a continuous integration and deployment (CI/CD) pipeline. 在本教學課程中,您會在 Azure VM 上建立 CI/CD 管線,包括如何︰In this tutorial, you create a CI/CD pipeline on an Azure VM including how to:

  • 建立 Jenkins VMCreate a Jenkins VM
  • 安裝並設定 JenkinsInstall and configure Jenkins
  • 建立 GitHub 與 Jenkins 之間的 webhook 整合Create webhook integration between GitHub and Jenkins
  • 從 GitHub 認可建立並觸發 Jenkins 組建作業Create and trigger Jenkins build jobs from GitHub commits
  • 建立應用程式的 Docker 映像Create a Docker image for your app
  • 確認 GitHub 已認可組建的新 Docker 映像,並更新了執行中的應用程式Verify GitHub commits build new Docker image and updates running app

開啟 Azure Cloud ShellOpen Azure Cloud Shell

Azure Cloud Shell 是裝載於 Azure 中的互動式殼層環境,並且會透過瀏覽器來使用。Azure Cloud Shell is an interactive shell environment hosted in Azure and used through your browse. Azure Cloud Shell 可讓您使用 bashPowerShell 殼層來執行各種可與 Azure 服務搭配運作的工具。Azure Cloud Shell allows you to use either bash or PowerShell shells to run a variety of tools to work with Azure services. Azure Cloud Shell 已預先安裝一些命令,可讓您執行本文的內容,而不必在本機環境上安裝任何工具。Azure Cloud Shell comes pre-installed with the commands to allow you to run the content of this article without having to install anything on your local environment.

若要在 Azure Cloud Shell 上執行本文所包含的任何程式碼,請開啟 Cloud Shell 工作階段、使用某個程式碼區塊上的 [複製] 按鈕來複製程式碼,然後使用 Ctrl+Shift+V (在 Windows 和 Linux 上) 或 Cmd+Shift+V (在 macOS 上) 將程式碼貼到 Cloud Shell 工作階段中。To run any code contained in this article on Azure Cloud Shell, open a Cloud Shell session, use the Copy button on a code block to copy the code, and paste it into the Cloud Shell session with Ctrl+Shift+V on Windows and Linux, or Cmd+Shift+V on macOS. 貼上的文字不會自動執行,因此請按 Enter 來執行程式碼。Pasted text is not automatically executed, so press Enter to run code.

您可以使用下列方式來啟動 Azure Cloud Shell:You can launch Azure Cloud Shell with:

選項Option 範例/連結Example/Link
選取程式碼區塊右上角的 [試試看] 。Select Try It in the upper-right corner of a code block. 這__不會__自動將文字複製到 Cloud Shell。This doesn't automatically copy text to Cloud Shell. Azure Cloud Shell 的試試看範例
在瀏覽器中開啟 Azure Cloud ShellOpen Azure Cloud Shell in your browser. <a href="https://shell.azure.com" title="啟動 Azure Cloud Shell
選取 Azure 入口網站右上角功能表上的 [Cloud Shell] 按鈕。Select the Cloud Shell button on the menu in the upper-right corner of the Azure portal. Azure 入口網站中的 [Cloud Shell] 按鈕

如果您選擇在本機安裝和使用 CLI,本教學課程會要求您執行 Azure CLI 2.0.30 版或更新版本。If you choose to install and use the CLI locally, this tutorial requires that you are running the Azure CLI version 2.0.30 or later. 執行 az --version 以尋找版本。Run az --version to find the version. 如果您需要安裝或升級,請參閱安裝 Azure CLIIf you need to install or upgrade, see Install Azure CLI.

建立 Jenkins 執行個體Create Jenkins instance

如何在首次開機時自訂 Linux 虛擬機器的先前教學課程中,您已了解如何使用 cloud-init 自動進行 VM 自訂。In a previous tutorial on How to customize a Linux virtual machine on first boot, you learned how to automate VM customization with cloud-init. 本教學課程使用 cloud-init 檔案在 VM 上安裝 Jenkins 和 Docker。This tutorial uses a cloud-init file to install Jenkins and Docker on a VM. Jenkins 是熱門的開放原始碼 Automation 伺服程式,可順暢地與 Azure 整合,以進行持續整合 (CI) 及持續傳遞 (CD)。Jenkins is a popular open-source automation server that integrates seamlessly with Azure to enable continuous integration (CI) and continuous delivery (CD). 如需如何使用 Jenkins 的更多教學課程,請參閱 Azure 中樞中的 JenkinsFor more tutorials on how to use Jenkins, see the Jenkins in Azure hub.

在您目前的殼層中,建立名為 cloud-init-jenkins.txt 的檔案,並貼上下列設定。In your current shell, create a file named cloud-init-jenkins.txt and paste the following configuration. 例如,在 Cloud Shell 中建立不在本機電腦上的檔案。For example, create the file in the Cloud Shell not on your local machine. 輸入 sensible-editor cloud-init-jenkins.txt 可建立檔案,並查看可用的編輯器清單。Enter sensible-editor cloud-init-jenkins.txt to create the file and see a list of available editors. 請確定已正確複製整個 cloud-init 檔案,特別是第一行:Make sure that the whole cloud-init file is copied correctly, especially the first line:

#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

建立 VM 之前,請先使用 az group create 來建立資源群組。Before you can create a VM, create a resource group with az group create. 下列範例會在 eastus 位置建立名為 myResourceGroupJenkins 的資源群組。The following example creates a resource group named myResourceGroupJenkins in the eastus location:

az group create --name myResourceGroupJenkins --location eastus

現在,使用 az vm create 建立 VM。Now create a VM with az vm create. 使用 --custom-data 參數以傳入 cloud-init 組態檔。Use the --custom-data parameter to pass in your cloud-init config file. 如果您將檔案儲存於目前工作目錄之外的位置,請提供 cloud-init-jenkins.txt 的完整路徑。Provide the full path to cloud-init-jenkins.txt if you saved the file outside of your present working directory.

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

系統需要花幾分鐘的時間來建立及設定 VM。It takes a few minutes for the VM to be created and configured.

為了允許網路流量連線到您的 VM,使用 az vm open-port 開啟連接埠 8080 (用於 Jenkins 流量) 和連接埠 1337 (用於 Node.js 應用程式,此應用程式用來執行範例應用程式)︰To allow web traffic to reach your VM, use az vm open-port to open port 8080 for Jenkins traffic and port 1337 for the Node.js app that is used to run a sample app:

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

設定 JenkinsConfigure Jenkins

若要存取您的 Jenkins 執行個體,取得您的 VM 的公用 IP 位址︰To access your Jenkins instance, obtain the public IP address of your VM:

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

基於安全考量,您必須輸入初始的系統管理員密碼 (儲存在您的 VM 上的文字檔案中),才能啟動 Jenkins 安裝。For security purposes, you need to enter the initial admin password that is stored in a text file on your VM to start the Jenkins install. 使用上一個步驟取得的公用 IP 位址,透過 SSH 連線至您的 VM:Use the public IP address obtained in the previous step to SSH to your VM:

ssh azureuser@<publicIps>

使用 service 命令確認 Jenkins 正在執行中:Verify Jenkins is running using the service command:

$ 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,並複製它︰View the initialAdminPassword for your Jenkins install and copy it:

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

如果檔案尚無法使用,請等待數分鐘,讓 cloud-init 完成 Jenkins 和 Docker 安裝。If the file isn't available yet, wait a couple more minutes for cloud-init to complete the Jenkins and Docker install.

現在開啟瀏覽器,前往 http://<publicIps>:8080Now open a web browser and go to http://<publicIps>:8080. 完成初始 Jenkins 設定,如下所示︰Complete the initial Jenkins setup as follows:

  • 選擇 [選取要安裝的外掛程式]Choose Select plugins to install
  • 在頂端的文字方塊中搜尋 GitHubSearch for GitHub in the text box across the top. 核取 [GitHub] 方塊,然後選取 [安裝]Check the box for GitHub, then select Install
  • 建立第一位管理使用者。Create the first admin user. 輸入使用者名稱,例如 admin,然後提供您自己的安全密碼。Enter a username, such as admin, then provide your own secure password. 最後,輸入完整名稱和電子郵件地址。Finally, type a full name and e-mail address.
  • 選取 [儲存並結束]Select Save and Finish
  • Jenkins 準備就緒之後,選取 [開始使用 Jenkins]Once Jenkins is ready, select Start using Jenkins
    • 如果您開始使用 Jenkins 時,網頁瀏覽器顯示空白頁面,請重新啟動 Jenkins 服務。If your web browser displays a blank page when you start using Jenkins, restart the Jenkins service. 從您的 SSH 工作階段輸入 sudo service jenkins restart,然後重新整理 Web 瀏覽器。From your SSH session, type sudo service jenkins restart, then refresh you web browser.
  • 如有需要,請使用您建立的使用者名稱和密碼登入 Jenkins。If needed, log in to Jenkins with the username and password you created.

建立 GitHub webhookCreate GitHub webhook

若要設定與 GitHub 整合,開啟 Azure 範例存放庫中的 Node.js Hello World 範例應用程式To configure the integration with GitHub, open the Node.js Hello World sample app from the Azure samples repo. 若要將存放庫分支至您自己的 GitHub 帳戶,請選取右上角的 [分支] 按鈕。To fork the repo to your own GitHub account, select the Fork button in the top right-hand corner.

在您建立的分支內建立 webhook︰Create a webhook inside the fork you created:

  • 選取 [設定],然後選取左側的 [Webhook]。Select Settings, then select Webhooks on the left-hand side.
  • 選擇 [新增 Webhook],然後在篩選方塊中輸入 JenkinsChoose Add webhook, then enter Jenkins in filter box.
  • 針對 [承載 URL],輸入 http://<publicIps>:8080/github-webhook/For the Payload URL, enter http://<publicIps>:8080/github-webhook/. 別漏掉最後的斜線 (/)。Make sure you include the trailing /
  • 針對 [內容類型],選取 application/x-www-form-urlencoded。For Content type, select application/x-www-form-urlencoded.
  • 針對 [要由哪些事件觸發此 Webhook?],選取 [僅限推送事件]。For Which events would you like to trigger this webhook?, select Just the push event.
  • 將 [作用中] 設為已勾選。Set Active to checked.
  • 按一下 [新增 Webhook]。Click Add webhook.

將 GitHub webhook 新增至您的分支存放庫

建立 Jenkins 作業Create Jenkins job

為了讓 Jenkins 回應 GitHub 中的事件,例如認可程式碼,請建立 Jenkins 作業。To have Jenkins respond to an event in GitHub such as committing code, create a Jenkins job. 使用您自己的 GitHub 分支 URL。Use the URLs for your own GitHub fork.

在您的 Jenkins 網站中,選取首頁中的 [建立新作業]︰In your Jenkins website, select Create new jobs from the home page:

  • 輸入 HelloWorld 作為作業名稱。Enter HelloWorld as job name. 選擇 [自由樣式專案],然後選取 [確定]。Choose Freestyle project, then select OK.
  • 在 [一般] 區段下,選取 [GitHub 專案],然後輸入您的分支存放庫 URL,例如 https://github.com/cynthn/nodejs-docs-hello-worldUnder the General section, select GitHub project and enter your forked repo URL, such as https://github.com/cynthn/nodejs-docs-hello-world
  • 在 [原始碼管理] 區段中,選取 [Git],輸入您的分支存放庫 .git URL,例如 https://github.com/cynthn/nodejs-docs-hello-world.gitUnder the Source code management section, select Git, enter your forked repo .git URL, such as https://github.com/cynthn/nodejs-docs-hello-world.git
  • 在 [組建觸發程序] 下,選取 [GITScm 輪詢的 GitHub 勾點觸發程序]。Under the Build Triggers section, select GitHub hook trigger for GITscm polling.
  • 在 [組建] 區段中,選擇 [新增組建步驟]。Under the Build section, choose Add build step. 選取 [執行殼層],然後在命令視窗中輸入 echo "Test"Select Execute shell, then enter echo "Test" in the command window.
  • 選取作業視窗底部的 [儲存]。Select Save at the bottom of the jobs window.

測試 GitHub 整合Test GitHub integration

若要測試 GitHub 與 Jenkins 的整合,請認可您分支中的變更。To test the GitHub integration with Jenkins, commit a change in your fork.

回到 GitHub 的 Web UI,選取您的分支存放庫,然後選取 index.js 檔案。Back in GitHub web UI, select your forked repo, and then select the index.js file. 選取鉛筆圖示以編輯此檔案,並將第 6 行改為︰Select the pencil icon to edit this file so line 6 reads:

response.end("Hello World!");

若要認可變更,請選取位於底部的 [認可變更] 按鈕。To commit your changes, select the Commit changes button at the bottom.

在 Jenkins 在作業頁面左下角的 [組建歷程記錄] 區段中會啟動新的組建。In Jenkins, a new build starts under the Build history section of the bottom left-hand corner of your job page. 選擇組建編號的連結,然後選取左側的 [主控台輸出]。Choose the build number link and select Console output on the left-hand side. 在從 GitHub 提取您的程式碼時,您可以檢視 Jenkins 進行的步驟,組建動作會將 Test 訊息輸出到主控台。You can view the steps Jenkins takes as your code is pulled from GitHub and the build action outputs the message Test to the console. 每次在 GitHub 中認可,webhook 就會連線到 Jenkins,以這種方式觸發新的組建。Each time a commit is made in GitHub, the webhook reaches out to Jenkins and triggers a new build in this way.

定義 Docker 組建映像Define Docker build image

為了查看因應您的 GitHub 認可而執行的 Node.js 應用程式,可以組建一個 Docker 映像來執行應用程式。To see the Node.js app running based on your GitHub commits, lets build a Docker image to run the app. 映像是從 Dockerfile 建立,此檔案定義如何設定執行應用程式的容器。The image is built from a Dockerfile that defines how to configure the container that runs the app.

在您的虛擬機器的 SSH 連線中,切換至以上一個步驟建立之作業為名的 Jenkins 工作區目錄。From the SSH connection to your VM, change to the Jenkins workspace directory named after the job you created in a previous step. 在此範例中命名為 HelloWorldIn this example, that was named HelloWorld.

cd /var/lib/jenkins/workspace/HelloWorld

使用 sudo sensible-editor Dockerfile 在此工作區目錄中建立檔案,並貼上下列內容。Create a file in this workspace directory with sudo sensible-editor Dockerfile and paste the following contents. 請確定已正確複製整個 Docker 檔案,特別是第一行:Make sure that the whole Dockerfile is copied correctly, especially the first line:

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,然後複製應用程式檔案並將它初始化。This Dockerfile uses the base Node.js image using Alpine Linux, exposes port 1337 that the Hello World app runs on, then copies the app files and initializes it.

建立 Jenkins 組建規則Create Jenkins build rules

您已在上一個步驟中建立基本 Jenkins 組建規則,將訊息輸出至主控台。In a previous step, you created a basic Jenkins build rule that output a message to the console. 現在要建立組建步驟來使用我們的 Dockerfile 並執行應用程式。Lets create the build step to use our Dockerfile and run the app.

回到您的 Jenkins 執行個體,選取在上一個步驟建立的作業。Back in your Jenkins instance, select the job you created in a previous step. 選取左側的 [設定],然後向下捲動至 [建置] 區段︰Select Configure on the left-hand side and scroll down to the Build section:

  • 移除現有的 echo "Test" 組建步驟。Remove your existing echo "Test" build step. 選取現有建置步驟方塊右上角的紅色叉號。Select the red cross on the top right-hand corner of the existing build step box.

  • 選擇 [新增建置步驟],然後選取 [執行殼層]Choose Add build step, then select Execute shell

  • 在 [命令] 方塊中輸入下列 Docker 命令,然後選取 [儲存]:In the Command box, enter the following Docker commands, then select Save:

    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 組建編號,讓您可以維護映像的歷程記錄。The Docker build steps create an image and tag it with the Jenkins build number so you can maintain a history of images. 系統會停止任何執行應用程式的現有容器,並加以移除。Any existing containers running the app are stopped and then removed. 然後會使用映像啟動新的容器將,並根據 GitHub 中最新的認可執行您的 Node.js 應用程式。A new container is then started using the image and runs your Node.js app based on the latest commits in GitHub.

測試您的管線Test your pipeline

若要查看整個管線的作用情況,請再次編輯您分支 GitHub 存放庫中的 index.js 檔案,然後選取 [認可變更]。To see the whole pipeline in action, edit the index.js file in your forked GitHub repo again and select Commit change. 在 Jenkins 中會依據 GitHub 的 webhook啟動新的作業。A new job starts in Jenkins based on the webhook for GitHub. 系統約需要幾秒鐘來建立 Docker 映像並在新容器中啟動應用程式。It takes a few seconds to create the Docker image and start your app in a new container.

如有需要,再次取得您的 VM 公用 IP 位址:If needed, obtain the public IP address of your VM again:

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

開啟網路瀏覽器,輸入 http://<publicIps>:1337Open a web browser and enter http://<publicIps>:1337. 您的 Node.js 應用程式會顯示,而且會反映您的 GitHub 分支中最新的認可,如下所示︰Your Node.js app is displayed and reflects the latest commits in your GitHub fork as follows:

執行 Node.js 應用程式

現在,對 GitHub 中的 index.js 檔案進行另一次編輯,並認可變更。Now make another edit to the index.js file in GitHub and commit the change. 稍等幾秒鐘讓 Jenkins 中的作業完成,然後重新整理網路瀏覽器以查看在新容器中執行之應用程式的更新版本,如下所示︰Wait a few seconds for the job to complete in Jenkins, then refresh your web browser to see the updated version of your app running in a new container as follows:

在另一次 GitHub 認可後執行 Node.js 應用程式

後續步驟Next steps

在本教學課程中,您設定 GitHub 在每次程式碼認可時執行 Jenkins 組建作業,然後部署 Docker 容器來測試您的應用程式。In this tutorial, you configured GitHub to run a Jenkins build job on each code commit and then deploy a Docker container to test your app. 您已了解如何︰You learned how to:

  • 建立 Jenkins VMCreate a Jenkins VM
  • 安裝並設定 JenkinsInstall and configure Jenkins
  • 建立 GitHub 與 Jenkins 之間的 webhook 整合Create webhook integration between GitHub and Jenkins
  • 從 GitHub 認可建立並觸發 Jenkins 組建作業Create and trigger Jenkins build jobs from GitHub commits
  • 建立應用程式的 Docker 映像Create a Docker image for your app
  • 確認 GitHub 已認可組建的新 Docker 映像,並更新了執行中的應用程式Verify GitHub commits build new Docker image and updates running app

前進到下一個教學課程,以深入了解如何整合 Jenkins 與 Azure DevOps Services。Advance to the next tutorial to learn more about how to integrate Jenkins with Azure DevOps Services.