Docker - 持續整合



使用 Docker 進行持續整合是指在開發工作流中自動化建立、測試和部署 Docker 容器的過程。這意味著提交到版本控制系統(如 Git)中的更改將自動在 CI 管道中從更新的程式碼構建 Docker 映象。然後,該映象會透過一系列自動化測試,以檢查應用程式是否按預期工作。

假設測試透過,則可以將映象推送到容器登錄檔並在暫存或生產環境中部署。Docker 與 CI/CD 透過確保從開發到生產的完全相同的環境,在所有開發和部署階段提供一致性。這有助於最大程度地減少與環境相關的問題。

在本章中,讓我們瞭解如何構建一個集成了 Docker 的基本 CI/CD 管道。

如何使用 Docker 構建 CI/CD 管道?

在本節中,我們將瞭解如何使用 Docker 和 Jenkins 建立端到端 CI/CD 管道,並透過它構建、測試和執行 Java 應用程式。

步驟 1:安裝 Docker

第一步是在您的機器上安裝 Docker。您可以參考我們之前的章節之一,並按照適用於您的作業系統的安裝說明進行操作,從 Docker 網站 下載 Docker。

步驟 2:在 Docker 容器中執行 Jenkins

接下來,您可以執行以下命令以在 Docker 容器中啟動 Jenkins:

$ docker run -d --name jenkins -p 8080:8080 -p 50000:50000 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts
Docker Continuous Integration 1

以上命令將拉取最新的 Jenkins LTS 映象並執行它。您可以在 https://:8080 訪問 Jenkins 儀表板。

步驟 3:Jenkins 初始設定

1. 訪問 Jenkins - 開啟您的瀏覽器並導航到 https://:8080。

2. 解鎖 Jenkins - 按照說明獲取初始管理員密碼。

Docker Continuous Integration 2

執行以下命令以獲取密碼:

$ docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
Docker Continuous Integration 3

3. 安裝建議的外掛 - 輸入密碼後,選擇“安裝建議的外掛”。

Docker Continuous Integration 4

Docker Continuous Integration 5

4. 建立管理員使用者 - 建立您的管理員使用者來管理 Jenkins。

Docker Continuous Integration 6

步驟 4:在 Jenkins 中配置 Docker

安裝 Docker Pipeline 外掛

  • 轉到 Jenkins 儀表板 -> 管理 Jenkins -> 管理外掛 -> 可用。
  • 搜尋“Docker Pipeline”並安裝它。
Docker Continuous Integration 7

新增 Docker Hub 憑據

  • 轉到 Jenkins 儀表板 -> 管理 Jenkins -> 管理憑據。
  • 使用您的 Docker Hub 使用者名稱和密碼新增一組新的憑據。
Docker Continuous Integration 8

步驟 5:建立 Java 應用程式

建立一個具有以下結構的簡單 Java 應用程式:

my-java-app/
├── src/
│   ├── main/
│   │   └── java/
│   │       └── org/
│   │           └── example/
│   │               └── Main.java
│   └── test/
│       └── java/
│           └── org/
│               └── example/
│                   └── MainTest.java
├── Dockerfile
├── Jenkinsfile
├── pom.xml

App.java

package org.example;
public class Main {
   public static void main(String[] args) {
      System.out.println("Hello, Docker CI/CD with Jenkins!");
   }
}

AppTest.java

package org.example;

import static org.junit.Assert.assertTrue;

import org.junit.Test;

public class MainTest {
   @Test
   public void shouldAnswerWithTrue() {
      assertTrue(true);
   }
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
   
   <modelVersion>4.0.0</modelVersion>

   <groupId>org.example</groupId>
   <artifactId>my-java-app</artifactId>
   <version>1.0-SNAPSHOT</version>

   <properties>
      <maven.compiler.source>8</maven.compiler.source>
      <maven.compiler.target>8</maven.compiler.target>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   </properties>

   <dependencies>
      <!-- JUnit 4 dependency -->
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.13.2</version>
         <scope>test</scope>
      </dependency>
   </dependencies>
</project>

步驟 6:更新 Dockerfile

在專案的根目錄中建立一個 Dockerfile:

FROM maven:3.6.3-jdk-8 AS build
WORKDIR /app
COPY pom.xml .
COPY src /app/src
RUN mvn clean package

FROM openjdk:8-jre-alpine
WORKDIR /app
COPY --from=build /app/target/my-java-app-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

步驟 7:更新 Jenkinsfile

在專案的根目錄中建立一個 Jenkinsfile 來定義您的 CI/CD 管道:

pipeline {
   agent any

   tools {
      maven 'Maven 3.6.3' // Define the Maven version installed on your Jenkins server
   }

   stages {
      stage('Build') {
         steps {
            script {
               // Build the Docker image
               docker.build("my-java-app:${env.BUILD_ID}")
            }
         }
      }
      stage('Test') {
         steps {
            script {
               // Run tests inside the Docker container
               docker.image("my-java-app:${env.BUILD_ID}").inside {
                  sh 'mvn test'
               }
            }
         }
      }
      stage('Push') {
         steps {
            script {
               // Push the Docker image to Docker Hub
               docker.withRegistry('https://index.docker.io/v1/', 'dockerhub-credentials') {
                  docker.image("my-java-app:${env.BUILD_ID}").push('latest')
               }
            }
         }
      }
      stage('Deploy') {
         steps {
            script {
               // Deploy the Docker image to the production environment
               sh 'docker run -d -p 8080:8080 my-java-app:latest'
            }
         }
      }
   }
   post {
      always {
         cleanWs()
      }
   }
}

步驟 8:配置 Jenkins 作業

1. 建立一個新的作業 - 轉到 Jenkins 儀表板 -> 新建 Item。

  • 選擇“Pipeline”並將其命名為 my-java-app-pipeline。
  • 在管道配置中,選擇“Pipeline 指令碼”並將 Jenkinsfile 內容複製到這裡。
  • 或者,您也可以“從 SCM 獲取 Pipeline 指令碼”並選擇“Git”,並提供託管 Java 應用程式的儲存庫 URL。
  • 指定要構建的分支(例如,main 或 master)。
  • 指定 Jenkinsfile 路徑。
Docker Continuous Integration 9

Docker Continuous Integration 10

2. 構建作業 - 儲存配置並單擊“立即構建”以啟動管道。

步驟 9:監控管道

  • 構建階段 - 使用 Dockerfile 構建 Docker 映象。
  • 測試階段 - 使用 mvn test 命令在 Docker 容器內執行應用程式測試。執行 MainTest.java 檔案,並報告結果。
  • 推送階段 - 將 Docker 映象推送到 Docker Hub。
  • 部署階段 - 將 Docker 映象部署到伺服器。

透過遵循這些步驟,您現在擁有了一個功能齊全的 CI/CD 管道,其中包括使用 Docker 和 Jenkins 對 Java 應用程式進行測試的階段。

結論

在本章中,我們討論瞭如何使用 Docker 和 Jenkins 建立一個功能齊全的 CI/CD 管道,並構建、測試和執行 Java 應用程式。Docker 的容器化確保了開發、測試和部署環境之間的一致性,從而提高了可靠性和可重複性。Jenkins 自動化了從構建 Docker 映象和執行測試到部署應用程式的管道,從而實現了持續改進的快速反饋。

在這種設定中使用 Maven 和 JUnit 的測試方法促進了強大的測試方法,以確保質量和可靠性。憑藉這些最佳實踐,團隊可以推動高效、可擴充套件、彈性的軟體交付,使其繼續與敏捷開發和現代部署週期的需求保持一致。

關於 Docker 持續整合的常見問題

1. 如何將 Docker 與 Jenkins 整合以進行 CI/CD?

將 Docker 與 Jenkins 整合的第一步是在 Jenkins 伺服器上安裝 Docker 外掛,使 Jenkins 可以與 Docker 進行互動,並使其能夠構建映象、執行容器並將它們推送到登錄檔。之後,您可以選擇在 Jenkins 中使用 Docker 命令來構建和部署應用程式定義您的 CI/CD 管道。

2. 如何在 Jenkins 中使用 Docker Compose?

Docker Compose 用於定義和管理多容器應用程式。您可以在 Jenkins 中使用 Docker Compose 外掛進行復雜的部署,例如按正確的順序、配置等啟動多個容器;這在應用程式中有多個服務時特別有用。

3. 如何為構建 Docker 映象設定 Jenkins 管道?

您可以使用 Jenkinsfile 建立一個 Jenkins 管道,其中定義了構建和部署 Docker 映象的所有步驟。此管道從原始碼控制中提取原始碼,建立 Docker 映象,執行測試,將映象推送到某個登錄檔,並將其部署到目標環境。

廣告