云计算百科
云计算领域专业知识百科平台

02_使用Docker在服务器上部署Jekins实现项目的自动化部署

02_使用Docker在服务器上部署jenkins实现项目的自动化部署

一、使用docker拉取阿里云容器私有镜像仓库内的jenkins镜像

  • 登录阿里云Docker Registry
  • $ sudo docker login username=wxxxo@1xxx registry.cnshanghai.aliyuncs.com

    用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。

    您可以在访问凭证页面修改凭证密码。

  • 从Registry中拉取镜像
  • $ sudo docker pull registry.cnshanghai.aliyuncs.com/xxx/jenkins:[镜像版本号]

    二、创建jenkins容器并运行

    $ sudo docker run d u root \\
    p 8080:8080 \\
    p 50000:50000 \\
    v /home/docker/jenkins_home:/var/jenkins_home \\
    v /var/run/docker.sock:/var/run/docker.sock \\
    v /usr/bin/docker:/usr/bin/docker \\
    v /usr/bin/kubectl:/usr/bin/kubectl \\
    v /root/.kube/config:/root/.kube/config \\
    name jenkins \\
    registry.cnshanghai.aliyuncs.com/xxx/jenkins:xxx

    每个参数的含义:

    • docker run: 运行 Docker 容器的命令。

    • -d: 在后台运行容器,即“detached”模式。

    • -u root: 以 root 用户身份运行容器。这通常用于确保容器内的进程具有足够的权限执行需要的操作。

    • -p 8080:8080: 将容器内部的 8080 端口映射到宿主机的 8080 端口(宿主机端口:容器内部端口)。Jenkins 服务通常在 8080 端口上运行。

    • -p 50000:50000: 将容器内部的 50000 端口映射到宿主机的 50000 端口(宿主机端口:容器内部端口)。这是 Jenkins 使用的用于构建和执行任务的端口。

    • -v /home/docker/jenkins_home:/var/jenkins_home: 将宿主机上的目录(/home/docker/jenkins_home)挂载到容器内的 /var/jenkins_home 目录(宿主机目录:容器内部目录)。这样可以确保 Jenkins 数据和配置持久化,即使容器被删除,数据仍然保存在宿主机上。

      注意:/home/docker/jenkins_home 为自己在Linux系统里创建的用来持久化jenkins数据的目录,而/var/jenkins_home是docker容器内的默认路径,即jenkins_home的路径在docker容器内的/var下。

    • -v /var/run/docker.sock:/var/run/docker.sock

      宿主机上的目录(/var/run/docker.sock)挂载到容器内的 /var/run/docker.sock 目录(宿主机目录:容器内部目录)。挂载 宿主机的 Docker 套接字(socket)到容器内部,让容器能够控制使用宿主机上的 Docker。

    • -v /usr/bin/docker:/usr/bin/docker

      宿主机上的目录( /usr/bin/docker)挂载到容器内的 /usr/bin/docker 目录(宿主机目录:容器内部目录)。将宿主机上的 docker 命令二进制文件挂载到容器内,使容器内部可以直接调用 Docker 命令。

    • -v /usr/bin/kubectl:/usr/bin/kubectl

      宿主机上的目录(/usr/bin/kubectl)挂载到容器内的 /usr/bin/kubectl 目录(宿主机目录:容器内部目录)。将宿主机的 kubectl 命令挂载到容器内部,使 Jenkins 在容器中可以直接执行 kubectl 命令,管理 Kubernetes 集群。

    • -v /root/.kube/config:/root/.kube/config

      宿主机上的目录(/root/.kube/config)挂载到容器内的 /root/.kube/config 目录(宿主机目录:容器内部目录)。将宿主机的 Kubernetes 配置文件挂载到容器内部,使 Jenkins 能够以ROOT权限访问 Kubernetes 集群。

    • –name jenkins: 为容器指定一个名称,即 “jenkins”。

    • registry.cn-shanghai.aliyuncs.com/xxx/jenkins:2.491-jdk17: 指定要运行的 Docker 镜像的名称和版本(镜像名称:版本号)。

    三、登录jenkins

    通过访问[服务器IP]:[jenkins端口]访问jenkins服务,刚使用jenkins服务时,需要使用jenkins提供的默认密码进行验证。

    jenkins提供的默认密码路径(在docker容器内)为:

    /var/jenkins_home/secrets/initialAdminPassword

    (如果将宿主机的某个目录路径挂载到 /var/jenkins_home 路径):如将宿主机上的目录(/home/docker/jenkins_home)挂载到容器内的 /var/jenkins_home 目录,那么默认密码路径为

    /home/docker/jenkins_home/secrets/initialAdminPassword

    安装插件,当然也可以跳过,不过一般推荐按照jenkins的推荐的插件。安装完毕后,可以创建jenkins用户。

    四、配置名为dockerhub的凭证

    在Jenkins中配置名为dockerhub的凭证(实际上就是自己的账号密码),方便Jenkins在构建docker镜像过程中,可以登录阿里云私有仓库,并上传到阿里云私有仓库内。

  • 点击 “Manage Jenkins”(管理 Jenkins)。

  • 进入 “Manage Credentials”(管理凭证)。

  • 点击 “Add Credentials”(添加凭证)。

  • Username(用户名): 阿里云账号

    Password(密码): 阿里云密码

    ID(唯一标识): dockerhub(⚠️ 这个 ID 之后要在 Jenkinsfile 里用,也可以起其他ID名,但是需要和Jenkinsfile里的registryCredential保持一致)。

  • 五、编写dockerfile、K8S/deployment.yaml、jenkinsfile文件

    dockerfile文件:docker打包镜像时,可以读取该文件中的内容,依据文件中的命令进行打包。

    dockerfile示例:

    # FROM 指定使用哪个镜像作为基准
    FROM docker.m.daocloud.io/openjdk:8u191jdkalpine

    # 创建目录, 并设置该目录为工作目录
    RUN mkdir p /aaa
    WORKDIR /aaa

    # 复制文件到镜像中
    # COPY target/aaa-1.0.jar aaa.jar
    COPY aaa1.0.jar ./

    # 设置时区
    ENV TZ=Asia/Shanghai

    # 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
    ENV JAVA_OPTS="-Xms300m -Xmx300m -Djava.security.egd=file:/dev/./urandom"

    # 应用参数,可通过 docker run -e "ARGS=" 来设置,如 -e "ARGS=–spring.profiles.active=prod"
    ENV ARGS=""

    # 暴露 8080 端口
    EXPOSE 8080

    # 启动后端服务
    CMD java ${JAVA_OPTS} jar aaa1.0.jar $ARGS

    K8S/deployment.yaml文件:K8S创建应用时,可以通过该文件中的内容进行创建。

    K8S/deployment.yaml文件:

    apiVersion: v1 # apiVersion: v1:指定 Kubernetes API 版本,v1 适用于 Service 资源
    kind: Service # 定义该资源的类型是一个 Service
    metadata:
    name: aaa # 定义 Service 的名称
    spec: # 定义 Service 的详细配置
    type: NodePort # 指定 Service 类型为 NodePort,即允许外部通过 NodeIP:nodePort 访问服务。
    selector:
    app: aaa # 表示该 Service 只会选择 app: aaa 这个标签的 Pod 作为后端服务。
    ports: # 定义 Service 的端口映射
    protocol: TCP # 指定使用 TCP 作为通信协议
    port: 8080 # 这是 Service 内部的端口,其他 Pod 访问该 Service 时使用这个端口。 port 会转发流量到 targetPort,通常它们可以相同,但不强制相同
    nodePort: 31678 # Kubernetes 在每个节点上分配的端口号,用于外部访问
    targetPort: 8080 # 这是 Pod 内部运行的容器监听的端口,对应 Dockerfile 里 EXPOSE 的端口和后文的里的 containerPort
    name: http # 端口名称(可不写)


    apiVersion: apps/v1 # 指定 Kubernetes API 版本,apps/v1 适用于 Deployment 资源
    kind: Deployment # 定义该资源的类型是一个 Deployment,用于管理 Pod 的创建和更新
    metadata:
    name: aaa # Deployment 的名称
    annotations:
    kubernetes.io/change-cause: registryvpc.cnshanghai.aliyuncs.com/aaa/aaa:{{GIT_COMMIT}} # 用于记录该 Deployment 变更的原因,常用于回滚和版本管理,其中 {{GIT_COMMIT}} 是 Git 提交的版本号,通常在 CI/CD 过程中会被替换为实际值,例如Jenkinsfile文件中有一条命令便是查找{{GIT_COMMIT}}并将其替换为实际的版本号
    spec: # 定义 Deployment 的详细配置
    replicas: 1 # 指定副本数,即 Pod 的数量为 1
    selector:
    matchLabels:
    app: aaa # 表示该 Deployment 只会管理 app: aaa 这个标签的 Pod
    template: # 定义 Pod 模板,所有由该 Deployment 创建的 Pod 都会遵循此模板
    metadata:
    labels:
    app: aaa # 给 Pod 打上 app: aaa 的标签,便于 Service 发现该 Pod
    spec: # 定义 Pod 的详细配置
    containers:
    name: aaa # 容器名称
    image: registryvpc.cnshanghai.aliyuncs.com/aaa/aaa:{{GIT_COMMIT}} # 指定容器的镜像地址,{{GIT_COMMIT}} 代表 Git 版本号,CI/CD 过程中会被替换为实际值
    ports:
    containerPort: 8080 # 定义容器内部监听的端口,应和dockerfile里EXPOSE暴露的端口保持一致
    # 下面是健康检查配置
    # livenessProbe: # (存活探针):检查容器是否存活,若失败 Kubernetes 会重启该容器
    # httpGet:
    # path: /user/health_check # 通过 HTTP GET 请求

    Jenkinsfile文件:Jenkins全流程部署时,根据该文件中的内容,进行全流程部署。

    Jenkinsfile文件:

    pipeline { // 定义一个工作流
    environment { //定义环境变量
    //定义Docker镜像仓库地址
    registry = "registry-vpc.cn-shanghai.aliyuncs.com/aaa/aaa"
    registryCredential = "dockerhub" //docker登录阿里云的凭证,即配置的账号密码,存储在jekins的Credential里
    parentWorkspace = "$WORKSPACE"
    FAILED_STAGE=""
    CURRENT_ENVIRONMENT=""
    BLUE_OR_GREEN=""
    }
    agent any // 定义在哪个 agent 上运行,这里使用任意可用节点
    stages { // 定义流水线中各个阶段(stages)
    stage("Deply Parent") { // 项目构建阶段
    agent {
    docker { //指定使用 Docker 代理运行
    image 'registry.cn-hangzhou.aliyuncs.com/acs/maven:3-jdk-8'
    args '-v $HOME/.m2/repository:/root/.m2/repository -u root'
    }
    }
    steps { // 定义该阶段的步骤(steps),并使用 script 块以脚本形式执行命令
    script {
    FAILED_STAGE=env.STAGE_NAME //将当前阶段名称(env.STAGE_NAME)赋值给变量 FAILED_STAGE,以便在出错时记录是哪一阶段失败了。
    sh "mvn -Dmaven.repo.local=/var/jenkins_home/jenkins_m2_repo -U install -Dmaven.test.skip=true" // 执行一个 shell 命令,通过 Maven 进行项目构建:Dmaven.repo.local=/var/jenkins_home/jenkins_m2_repo 指定 Maven 本地仓库路径,U 表示强制更新 SNAPSHOT 依赖,install 命令用于构建并安装项目,Dmaven.test.skip=true 则跳过测试执行。
    // 拷贝到容器外
    sh "cp target/analyzer-1.0.jar " + parentWorkspace +"/analyzer-1.0.jar" // 执行一个 shell 命令,将 target 目录下生成的 analyzer1.0.jar 文件复制到外部的工作空间路径(由变量 parentWorkspace 指定)。
    }
    }
    }
    stage("Building image") { //构建镜像阶段
    steps {
    script {
    FAILED_STAGE=env.STAGE_NAME // 将当前阶段名称赋值给 FAILED_STAGE,
    docker.build(registry) // 调用 docker.build(registry) 方法,根据之前定义的 registry 变量构建 Docker 镜像。
    sh "docker rmi -f ${registry}:$GIT_COMMIT" // 强制删除本地镜像
    }
    }
    }
    stage("Deploy Image") { // 部署镜像阶段
    steps {
    script {
    FAILED_STAGE=env.STAGE_NAME // 将当前阶段名称赋值给 FAILED_STAGE
    docker.withRegistry('https://registry-vpc.cn-shanghai.aliyuncs.com', registryCredential) { // 使用 docker.withRegistry 方法指定镜像仓库地址 https://registryvpc.cnshanghai.aliyuncs.com 和凭据 registryCredential,
    docker.image(registry).push("$GIT_COMMIT") //将构建的镜像以当前 Git 提交号($GIT_COMMIT)作为标签推送到仓库。
    }
    }
    }
    }
    stage("Update k8s cluster") { // 更新 Kubernetes 集群阶段
    options {
    timeout(time: 5, unit: 'MINUTES') // 本阶段超时时间限定为 5 分钟
    }
    steps {
    script {
    FAILED_STAGE=env.STAGE_NAME // 当前阶段名称赋值给 FAILED_STAGE
    if (env.GIT_BRANCH == "origin/test") { // 判断当前的 Git 分支是否为 "origin/test",分支需要按需选择,这里是在test分支下,使用使用test,也可以改为master等。
    sh "cat k8s/deployment.yml | sed 's/{{GIT_COMMIT}}/$GIT_COMMIT/g' | kubectl apply -n default -f -" // 使用 sed 命令将 k8s/deployment.yml 文件中的占位符 {{GIT_COMMIT}} 替换为实际的 Git 提交号,并通过管道传递给 kubectl apply 命令,应用于 default 命名空间
    sh "kubectl rollout status deployment/aaa -n default" // 使用 kubectl rollout status 命令检查部署状态,确保部署成功
    }else{
    sh "cat k8s/deployment-test.yml | sed 's/{{GIT_COMMIT}}/$GIT_COMMIT/g' | kubectl apply -n test -f -" // 对 k8s/deploymenttest.yml 文件进行替换,并将其应用于 test 命名空间
    sh "kubectl rollout status deployment/aaa -n default" // 检查部署状态
    }
    }
    }
    }
    }
    post { // 流水线的后置操作(post)
    aborted { // 流水线被中止(aborted)时,执行以下 script 脚本
    script {
    if (FAILED_STAGE == "Update k8s cluster") { // 如果最后出错的阶段(FAILED_STAGE)是 "Update k8s cluster",则根据当前 Git 分支进行回滚操作
    if (env.GIT_BRANCH == "origin/test") { // 如果在 origin/test 分支下,分支需要按需选择,这里是在test分支下,使用使用test,也可以改为master等。
    sh "kubectl config use kubernetes" // 切换 kubectl 配置)
    sh "kubectl rollout undo deployment/aaa" // 回滚部署 aaa。
    }else{
    sh "kubectl config use kubernetes" 切换配置
    sh "kubectl rollout undo deployment/aaa-test" 回滚部署
    }
    }
    }
    }
    }
    }

    六、创建任务

    创建一个任务(可以使用模板,如Freestyle project、Pipeline)。

  • 如果使用的是Freestyle project
  • 选择代码源管理(Source Code Management),项目如果在Coding、GitHub、Gitee等托管平台上,则选择Git。
  • 填写仓库路径(Repository URL),HTTP的仓库路径。填写完路径以后,一般会报错。
  • 如果没有Credentials,则需要添加一个新的Credentials。添加时,Username 填仓库所在平台的邮箱,密码填仓库所在平台的用户密码。完成以后,如果账号密码没问题,则此处不会报错。
  • 有时还需要选择分支(Branch Specifier)。
  • 处理构建流程(Steps),需要手动一个一个添加(Add build step)。
  • 如果使用的是Pipeline
  • 一般选择Pipeline-Definition为Pipeline script from SCM。
  • SCM (代码源)选择为 Git
  • 填写仓库路径(Repository URL),HTTP的仓库路径。填写完路径以后,一般会报错。
  • 如果没有Credentials,则需要添加一个新的Credentials。添加时,Username 填仓库所在平台的邮箱,密码填仓库所在平台的用户密码。完成以后,如果账号密码没问题,则此处不会报错。
  • 有时还需要选择分支(Branch Specifier)。
  • Script Path填写自己在项目根目录放置的用于jenkins读取的文件(自动化部署的命令),如jenkinsfile文件等。
  • 赞(0)
    未经允许不得转载:网硕互联帮助中心 » 02_使用Docker在服务器上部署Jekins实现项目的自动化部署
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!