Docker 容器中使用 Jenkins 进行持续集成

前言

持续集成是现代软件开发不可或缺的环节之一, 它能够将多个开发者交付的代码进行集成并自动地进行测试,以保证编写的代码质量。其中, Jenkins 是目前应用最广泛的开源持续集成工具之一。使用 Docker 来构建 Jenkins 环境能够带来诸多好处,如环境隔离、效率提升、易于管理等等。

前置知识

为了更好地理解本文内容,读者需要掌握以下知识:

  • 基本 Docker 使用方法
  • Linux 环境和基本命令
  • Jenkins 持续集成流程和配置

构建 Docker 容器

首先,我们需要构建一个包含 Jenkins 和相关插件的 Docker 容器,并将它运行在我们的本地或者远程服务器上。

Dockerfile 定义如下:

FROM jenkins/jenkins:lts-jdk11

RUN jenkins-plugin-cli --plugins blueocean:1.24.6 docker-workflow:1.26 git:4.7.1

USER root

RUN apt-get update -y && \
    apt-get install -y apt-transport-https \
                       ca-certificates \
                       curl \
                       gnupg-agent \
                       software-properties-common && \
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \
    apt-key fingerprint 0EBFCD88 && \
    add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" && \
    apt-get update -y && \
    apt-get install -y docker-ce docker-ce-cli containerd.io && \
    usermod -aG docker jenkins

USER jenkins

该 Dockerfile 基于 Jenkins 官方镜像构建,并安装了以下插件:

  • Blue Ocean: Jenkins 官方推荐的图形化界面插件,提供更好的用户体验。
  • Docker Pipeline:Jenkins 的 Docker Pipeline 插件提供了 Docker 多阶段构建所需的功能。有了此插件,Jenkins 上的 Shell 脚本就可以运行在 Docker 中。
  • Git:由于使用了 Git 作为代码版本控制系统,我们需要安装 Git 插件。

启动 Jenkins 容器

使用以下命令可启动 Jenkins 容器:

docker run --name my-jenkins \
-p 8080:8080 \
-p 50000:50000 \
-v /var/jenkins_home:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
-d my-jenkins:latest

其中:

  • -p 参数将主机的端口映射到容器端口上。在本例中,我们将 Jenkins 容器的 8080 端口映射到宿主机的 8080 端口上。
  • -v 参数将主机上的目录映射到容器内的目录中。在本例中,我们通过卷挂载技术将 jenkins_home 目录映射到主机的 /var/jenkins_home 目录上。

使用浏览器访问 http://localhost:8080,即可访问 Jenkins 中文界面,并根据提示完成初始配置。完成之后,即可开始创建项目并配置 Jenkins 的持续集成流程。

配置 Jenkins Pipeline

使用 Jenkins 实现持续集成流程的一般做法是将任务流程抽象为一组 Pipeline 脚本, 具体而言, Pipeline 能够自动拉取代码、编译、测试、构建镜像、部署等等,配合 Jenkins 的自动构建和触发机制,自动化地实现单元测试、集成测试、功能测试、性能测试等流程。

在本例中,我们以一个简单的 Node.js 应用程序为例来说明如何使用 Jenkins 来实现持续集成流程。首先,我们需要在 Jenkins 界面创建一个“多分支 Pipeline”类型的项目并添加新的 Pipeline 集成:

然后,我们详细描述 Pipeline 的不同阶段,并且定义 Jenkinsfile 以描述他们。

实现该应用程序的 Pipeline 文件包括以下步骤:

pipeline {
  agent none
  stages {
    stage('Checkout') {
      agent any
      steps {
        git branch: 'main', url: 'https://github.com/USERNAME/REPO_NAME.git'
      }
    }

    stage('Build and Test') {
      agent {
        docker {
          image 'node:14'
          args '-v $PWD:/app -w /app'
          reuseNode true
        }
      }
      steps {
        sh 'npm install'
        sh 'npm run lint'
        sh 'npm run test'
      }
    }

    stage('Build and Push Docker Image') {
      agent {
        docker {
          image 'docker:20.10-dind'
          args '--privileged -v $PWD:/app -w /app'
        }
      }
      steps {
        sh './build.sh'
      }
    }

    stage('Deploy') {
      agent {
        kubernetes {
          kubeconfigId 'kubeconfig'
          containerTemplate {
            name 'my-app'
            image 'my-app:latest'
            ttyEnabled true
          }
        }
      }
      steps {
        sh 'kubectl apply -f kubernetes/deployment.yaml'
      }
    }
  }
}

这段代码描述了以下几个步骤:

  • Checkout 阶段从 GitHub 中获取代码。
  • Build and Test 阶段构建并测试应用程序。
  • Build and Push Docker Image 阶段构建 Docker 镜像,并将其推送到 Docker Hub。
  • Deploy 阶段部署应用程序到 Kubernetes 集群中。

Dockerfile 和 build.sh 脚本

为了启用 Docker 加速功能,需要调整 Dockerfile:

FROM node:14-alpine

COPY . /app

WORKDIR /app

RUN npm install && npm run build

EXPOSE 3000

ENTRYPOINT [ "npm", "start" ]

构建镜像和推送到 Docker Hub:

#!/usr/bin/env bash

NAMESPACE=YOUR_NAMESPACE
IMAGE_NAME=my-app

docker build -t ${NAMESPACE}/${IMAGE_NAME} .
docker push ${NAMESPACE}/${IMAGE_NAME}:latest

该脚本将当前目录下的代码打包到镜像中,并以镜像形式推送到 Docker Hub 的 Registry 上。

总结

本文介绍了如何使用 Docker 容器构建 Jenkins 环境,以及如何在 Jenkins Pipeline 中使用 Docker 进行构建、测试、镜像制作和部署,实现了 Docker 和 Jenkins 的深度整合,形成了一个完整的持续集成流程。

相较于传统的集成方式,使用 Docker 和 Jenkins 进行持续集成可以提升环境隔离和效率,让开发者更加方便地进行持续集成和部署,并且降低了软件交付的难度和风险。

Docker 的应用和发展已经是大势所趋,因此会涌现出更多的解决方案,让我们拭目以待。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65b738e3add4f0e0fffcd0f4