从零开始部署Android环境的Jenkins CI/CD流水线(docker环境,Win系统)

文章目录

  • 前言
  • [1. 容器部署](#1. 容器部署)
  • [2. 初始化gitea,上传Android项目](#2. 初始化gitea,上传Android项目)
  • [3. 初始化jenkins](#3. 初始化jenkins)
  • [4. 部署Android编译环境](#4. 部署Android编译环境)
    • [4.1 Jenkins docker插件](#4.1 Jenkins docker插件)
    • [4.2 Android镜像](#4.2 Android镜像)
  • [5. 添加jenkins凭据](#5. 添加jenkins凭据)
  • [6. JenkinsFile](#6. JenkinsFile)
  • [7. 创建Jenkins PipeLine、构建!](#7. 创建Jenkins PipeLine、构建!)
  • 参考资料

前言

环境和要求

系统环境:win11

配置要求:能跑得动文中服务总和的内存

软件环境:Docker desktop。https://www.docker.com/products/docker-desktop/

网络环境:有办法上外网下载容器和所需要的服务。

说明

在本文中,如无特殊说明,所有需要输入指令的地方都为docker.desktop终端的terminal(其实就是powerShell),下图红框处点一下即可打开。输入docker,没有出现报错时,就算准备完成了。如果出现报错,检查一下你的环境变量是否有把docker加进去,这部分请百度解决。

1. 容器部署

随着我对docker本身的理解加深,这回我们采用docker-compose.yml的形式进行部署容器。

而不是像之前的文章那样一行一行敲指令了。

docker-compose.yml我们可以简单理解成将所有需要的容器部署指令都集成在一个文件中,然后docker只需要运行这个文件,就会自动的执行文件里面的指令,把我们的容器部署上去。那么我们这就开始创建这个文件吧。

  1. 随便找一个你用来放置配置文件的文件夹,新建一个也行,文章的演示文件夹为D:test/docker/config。

  2. 新建一个文件,名称为docker-compose.yml,然后用txt的方式打开它。

  3. 把我们所需要的所有服务和连通网络都写到这个文件里面,把以下文件的内容复制进去。文件看着很长大一串,但是不要担心,这些内容你只需要复制进docker-compose.yml文件即可,不需要做任何修改,我已经把里面一大堆需要配置的参数都改成外部的env引用了。

    yml 复制代码
    # 定义服务(容器)
    services:
      # 数据库服务 (MySQL) - 为 Gitea 提供数据存储
      mysql-db:
        image: ${MYSQL_IMAGE:-mysql:latest}  # 使用 MySQL 
        container_name: ${MYSQL_CONTAINER_NAME:-gitea-mysql}  # 指定容器名,方便其他容器连接
        restart: unless-stopped  # 总是重启,除非手动停止
        environment:
          MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}  # 【必须修改】设置 root 密码
          MYSQL_DATABASE: ${MYSQL_DATABASE:-gitea}  # 自动创建的数据库名
          MYSQL_USER: ${MYSQL_USER:-gitea}  # 自动创建的用户名
          MYSQL_PASSWORD: ${MYSQL_PASSWORD}  # 【必须修改】上述用户的密码
          MYSQL_CHARSET: ${MYSQL_CHARSET:-utf8mb4}
          MYSQL_COLLATION: ${MYSQL_COLLATION:-utf8mb4_unicode_ci}
        volumes:
          - ${MYSQL_DATA_PATH:-./mysql/data}:/var/lib/mysql  # 持久化数据库数据,防止容器销毁后数据丢失
          - ${MYSQL_CONF_PATH:-./mysql/conf}:/etc/mysql/conf.d:ro  # 可选:挂载自定义MySQL配置文件
        networks:
          - gitea-backend-network  # 连接至后端网络,仅允许特定服务访问
        # 注意:不映射端口到主机,保证数据库安全,只能通过Docker网络内部访问
    
      # 代码托管服务 (Gitea)
      gitea:
        image: ${GITEA_IMAGE:-gitea/gitea:latest}
        container_name: ${GITEA_CONTAINER_NAME:-gitea}
        restart: unless-stopped
        depends_on:  # 显式声明依赖,确保 mysql-db 先启动
          - mysql-db
        environment:
          # 数据库连接配置,HOST 使用 service name,Docker 会自动解析
          - GITEA__database__DB_TYPE=mysql
          - GITEA__database__HOST=${MYSQL_CONTAINER_NAME:-mysql-db}:3306  # 【关键】使用服务名`mysql-db`
          - GITEA__database__NAME=${MYSQL_DATABASE:-gitea}
          - GITEA__database__USER=${MYSQL_USER:-gitea}
          - GITEA__database__PASSWD=${MYSQL_PASSWORD}  # 与上方 MYSQL_PASSWORD 一致
          - USER_UID=${GITEA_UID:-1000}
          - USER_GID=${GITEA_GID:-1000}
        volumes:
          - ${GITEA_DATA_PATH:-./gitea/data}:/data  # 持久化 Gitea 的数据(仓库、附件等)
        ports:
          - "${GITEA_HTTP_PORT:-3000}:3000"  # 将容器的3000端口映射到宿主机的3000端口(Web访问)
          - "${GITEA_SSH_PORT:-10022}:22"   # 将容器的22端口映射到宿主机的10022端口(SSH克隆)
        networks:
          - gitea-backend-network  # 连接后端网络,与数据库通信
          - ci-network  # 连接前端网络,与 Jenkins 通信及对外提供服务
    
      # CI/CD 服务 (Jenkins)
      jenkins:
        image: ${JENKINS_IMAGE:-jenkins/jenkins:lts}  # 使用长期支持版本
        container_name: ${JENKINS_CONTAINER_NAME:-jenkins}
        restart: unless-stopped
        user: root  # 为避免权限问题,特别是要操作Docker时,使用root用户
        ports:
          - "${JENKINS_WEB_PORT:-8080}:8080"  # Web 管理界面端口
          - "${JENKINS_AGENT_PORT:-50000}:50000" # Agent 通信端口
        volumes:
          - ${JENKINS_DATA_PATH:-./jenkins/data}:/var/jenkins_home  # 持久化 Jenkins 的所有配置和任务数据
          - /var/run/docker.sock:/var/run/docker.sock  # 【重要】挂载Docker守护进程套接字,使Jenkins能在容器内执行Docker命令
        environment:
          - JAVA_OPTS=-Duser.timezone=${TIMEZONE:-Asia/Shanghai}  # 设置Jenkins时区
        networks:
          - ci-network  # 连接到前端网络,与Gitea通信
    
    
    # 定义网络,实现容器间隔离与通信
    networks:
      gitea-backend-network:  # 后端网络,用于数据库通信,隔离且安全
        driver: bridge
      ci-network:  # 前端网络,用于Jenkins、GiteaWeb界面等对外通信
        driver: bridge
  4. 在该文件夹,再新建一个.env文件,把以下配置参数给复制进去。为了简化我们的思考复杂度,我把一般情况下不需要修改的参数给删了,我们只需要把这几个参数搞明白就行。

    yml 复制代码
    # Docker Compose 环境变量配置文件
    
    # MySQL 配置
    MYSQL_CONTAINER_NAME=gitea-mysql
    MYSQL_ROOT_PASSWORD=your_mysql_root_password_here
    MYSQL_DATABASE=gitea
    MYSQL_USER=gitea
    MYSQL_PASSWORD=your_mysql_password_here
    MYSQL_DATA_PATH=D:\test\docker\mysql\data
    MYSQL_CONF_PATH=D:\test\docker\mysql\conf
    
    # Gitea 配置
    GITEA_CONTAINER_NAME=gitea
    GITEA_DATA_PATH=D:\test\docker\gitea
    GITEA_HTTP_PORT=3000
    GITEA_SSH_PORT=10022
    
    # Jenkins 配置
    JENKINS_CONTAINER_NAME=jenkins
    JENKINS_DATA_PATH=D:\test\docker\jenkins
    JENKINS_WEB_PORT=8080
    JENKINS_AGENT_PORT=50000
    • 如果你在此之前从来没有配置过容器的经验,同时你目前也没有配置过任何容器的话,那么你只需要把MYSQL_ROOT_PASSWORD和MYSQL_PASSWORD这两个参数修改成你的密码,同时将所有的PATH变量都找一个地方放置即可。
    • 如果已经有配置过容器的经验的话,那么你需要把所有的NAME改成和已有容器不重复的,所有的PORT改成和已有容器不重复的,即可。
  5. 最后你的预定文件夹应该是长这样,里面有这两个文件就算准备完毕。

  6. 打开docker.desktop的终端,cd到当前目录。然后执行docker compose up -d,我们就将容器全部部署上去了。

    cmd 复制代码
    cd D:\test\docker\config
    
    docker-compose up -d

2. 初始化gitea,上传Android项目

然后我们打开部署好的gitea容器对应的git网址。也就是图中的这个按钮。

然后会打开一个让我们安装gitea的网页,由于我们的参数啥的乱七八糟的全部都配置好了,所以这个页面的必要参数已经是填好的状态,我们直接点底部的安装即可。

安装完成之后,然后自己注册一个账号,开个仓库。

接下来我们传一个能打包的Android项目,我们这里不要把事情搞得太复杂,直接随便弄一个测试项目即可。在Android Studio->new Project->Empty Activity->项目名称随便取一下,然后把项目new出来即可。本地试一下能跑了就把他传到自己的gitea上,git怎么用这里就不教学了。

3. 初始化jenkins

接下来打开部署好的jenkins网页(8080的那个端口),会有这样一个页面

管理员密码就在你部署的jenkins文件夹\secrets里,比如说我上文的jenkins部署文件夹是 D:\test\docker\jenkins,那么就是 D:\test\docker\jenkins\secrets\initialAdminPassword。

找到之后按照教程继续,直接点左边安装推荐的插件即可,后续还有要装的我们会再安装。装不上应该是连不上外网之类的原因,检查一下自己的网络。

最后注册一个账号,我这边为了方便就账号密码啥的全是jenkins了。

4. 部署Android编译环境

4.1 Jenkins docker插件

这里我们采用虚拟机的方式来编译Android环境,简单来说我们会准备好一个Android环境的ubuntu镜像,每次jenkins要开始构建的时候,就会把这个镜像给直接实例化,然后编译完成后再把镜像关闭。

先做好jenkins的准备,首先安装docker插件,这样jenkins就有了启动其他docker容器的权限。

回到docker.desktop的终端,输入:

xml 复制代码
 # 进入容器,容器名换成自己的
docker exec -it jenkins /bin/bash

# 获取更新列表
apt-get update

# 安装Docker CLI
apt-get install -y docker.io

# 在不退出容器的情况下输入docker ps,看看会不会显示你的容器列表,会显示则无问题
docker ps          

回到我们的docker网页,安装以下docker开头的插件。

安装的时候就先不用管他了,继续做下一步,回头看一下安装是否成功就行。

4.2 Android镜像

接下来我们要准备一个带有Android编译环境的ubuntu镜像。

  1. 找个一个空文件夹用于存放DockerFile文件,路径不要带中文就行,我这边就是D:\test\docker\config\AndroidEnv

  2. 新建一个文件Dockerfile,注意这个文件名必须和我写的完全一样,而且没有后缀,然后把以下内容复制粘贴进文件里面,用txt方式打开后复制进去即可。

    xml 复制代码
    ARG UBUNTU_VERSION=22.04
    
    # 使用官方 Ubuntu 基础镜像
    FROM ubuntu:${UBUNTU_VERSION}
    
    ARG JDK_VERSION=21
    ARG ANDROID_API_LEVEL=34
    ARG ANDROID_BUILD_TOOLS_VERSION=34.0.0
    ENV JDK_VERSION=${JDK_VERSION}
    ENV ANDROID_API_LEVEL=${ANDROID_API_LEVEL}
    ENV ANDROID_BUILD_TOOLS_VERSION=${ANDROID_BUILD_TOOLS_VERSION}
    
    RUN echo "ANDROID_API_LEVEL-${ANDROID_API_LEVEL}"
    
    # 更新包列表并安装必要工具(所有命令合并到一个 RUN 指令中,用 && 连接)
    RUN apt-get update && \
        apt-get install -y --no-install-recommends \
            openjdk-${JDK_VERSION}-jdk \
            wget \
            unzip \
            git && \
        rm -rf /var/lib/apt/lists/*
    
    # 定义基础环境变量
    ENV ANDROID_HOME=/opt/android-sdk
    ENV JAVA_HOME=/usr/lib/jvm/java-${JDK_VERSION}-openjdk-amd64
    
    # 定义 PATH,引用前面定义的变量
    ENV PATH=$JAVA_HOME/bin:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$PATH
    
    # 创建 Android SDK 目录
    RUN mkdir -p $ANDROID_HOME/cmdline-tools
    
    # 下载并安装 Android 命令行工具
    RUN wget -q https://dl.google.com/android/repository/commandlinetools-linux-8512546_latest.zip -O /tmp/sdk-tools.zip && \
        unzip -q /tmp/sdk-tools.zip -d $ANDROID_HOME/cmdline-tools && \
        mv $ANDROID_HOME/cmdline-tools/cmdline-tools $ANDROID_HOME/cmdline-tools/latest && \
        rm /tmp/sdk-tools.zip
    
    # 接受 SDK 许可协议
    RUN mkdir -p $ANDROID_HOME/.android && \
        touch $ANDROID_HOME/.android/repositories.cfg && \
        yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses > /dev/null
    
    # 安装所需的 Android SDK 组件
    RUN yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager \
        "platforms;android-${ANDROID_API_LEVEL}" \
        "build-tools;${ANDROID_BUILD_TOOLS_VERSION}" \
        "platform-tools"
        # "ndk;25.1.8937393" # 可选,如需 NDK 可取消注释
    
    # 清理临时文件(可选,但有助于减小镜像大小)
    RUN apt-get clean && \
        rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
    
    # 设置工作目录
    WORKDIR /workspace

    下面的所有内容你都不用看,重点关注一开始ARG开头的几行,
    把JDK_VERSION、ANDROID_API_LEVEL、ANDROID_BUILD_TOOLS_VERSION这三个值填了就行。这三个值去哪里获取呢,用你的Android Studio打开你的Android项目。

    • JDK_VERSION:File->Settings->Build,Execution,Deployment->Build Tools->Gradle->看你的GradleJDK的JDK版本。比如我这里是11.0.27,所以这个值填入11。
    • ANDROID_API_LEVEL和ANDROID_BUILD_TOOLS_VERSION:这个值直接在你的项目里面全局搜索compileSdkVersion和buildToolsVersion,后面写了多少就填入多少即可。
  3. 接下来回到docker客户端的终端,先把ubuntu的镜像下载下来。下我们ARG中的对应版本就行,比如我这里是22.04。

  4. 然后构建我们的Android镜像,在终端输入以下指令

    xml 复制代码
    # 换成你的路径
    cd D:\test\docker\config\AndroidEnv
    
    # 名称和版本号其实都可以自己取,我建议版本号改成buildTools的版本比较容易管理。
    docker build -t android-builder:33.0.3
  5. 如果发现这个build无论如何都下载不了相关的环境,我们可以改用清华的镜像来下载,将Dockerfile的下载这一部分修改一下。

    xml 复制代码
    # 更新包列表并安装必要工具(所有命令合并到一个 RUN 指令中,用 && 连接)
    RUN sed -i 's/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list && \
        sed -i 's/security.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list && \ 
        apt-get update && \
        apt-get install -y --no-install-recommends \
            openjdk-${JDK_VERSION}-jdk \
            wget \
            unzip \
            git && \
        rm -rf /var/lib/apt/lists/*
  6. 下载结束之后,检查一下我们的ENV有没有问题,如果ANDROID_HOME和JAVA_HOME都非空就算成功。

    xml 复制代码
    # 之前如果有进入容器要先退出,输入exit就能退出了
    docker run --rm android-builder:34.0.0 env

5. 添加jenkins凭据

credentialsId:回到jenkins的网页,点右上角的齿轮进入管理页面,然后下划找到凭据管理。

进入该页面后,再点击该位置。然后再点击全局凭据(没有的话自己点右上角的Add domain加一个,然后再点进去)。

最后点击右上角的Add Credentials,就开始创建我们的凭据了。

类型我们选择Username with password。

  • Username:你的 Gitea 用户名。
  • Password:你的 Gitea 账号密码。
  • ID:留空不写
  • 描述:自己看这些。

然后把创建生成后的id复制下来,我们马上就要用到。

6. JenkinsFile

回到我们的Android项目,在根目录下新建一个JenkinsFile文件。把我们PipeLine的信息都写进去。

java 复制代码
pipeline {
    agent any // 使用任何可用的Jenkins节点

    stages {
        stage('Checkout Code') {
            steps {
                echo '开始拉取代码...'
                // 替换为您的Gitea仓库地址和凭据ID
                git branch: 'master',
                     credentialsId: 'aaaaaaaaaa',
                     url: 'http://192.168.31.39:3000/test/testAndroid.git'
            }
        }

        stage('Build Android') {
            agent {
                docker {
                    image 'android-builder:34.0.0' // 使用您之前构建的Android环境镜像
                    reuseNode true // 重用工作空间
                    args '-v $HOME/.gradle:/root/.gradle' // 挂载Gradle缓存加速构建
                }
            }
            steps {
                echo '开始构建APK...'
                // 修复权限:为 gradlew 脚本添加执行权限
                sh 'chmod +x ./gradlew'
                // 然后执行构建命令
                sh './gradlew clean assembleDebug'
            }
        }
    }

    post {
        success {
            echo '构建成功!'
            archiveArtifacts artifacts: 'app/build/outputs/apk/debug/*.apk', fingerprint: true
        }
        failure {
            echo '构建失败!请检查日志。'
        }
    }
}

我们把开头git那一段改一下就行。

  • git branch:这个不用多说了,你要编译哪个分支就是哪个分支。
  • credentialsId:这个就是我们上一步在jenkins里面复制来的东西了。
  • url:这个应该都会填吧,就是你的git remote origin的url,丢进来就行。

然后把这个文件也传到我们的gitea上,我们就算做好所有构建准备了。

7. 创建Jenkins PipeLine、构建!

回到jenkins网页的首页,点击左边的新建Item,名称随便填,类型选PipeLine,中文的话是流水线。

然后在第二个页面中直接页面拉到下面部分。

  1. 定义选择Pipeline cript from SCM
  2. SCM选择git
  3. Repository URL填入我们的git仓库。
  4. Credentials选择我们刚刚创建的那个。

然后点击应用,最后点击构建,不出意外的话应该是要成功的。

参考资料

deepseek

相关推荐
砖厂小工1 天前
用 GLM + OpenClaw 打造你的 AI PR Review Agent — 让龙虾帮你审代码
android·github
张拭心1 天前
春节后,有些公司明确要求 AI 经验了
android·前端·人工智能
张拭心1 天前
Android 17 来了!新特性介绍与适配建议
android·前端
fetasty1 天前
rustfs加picgo图床搭建
docker
Kapaseker1 天前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
黄林晴1 天前
Android17 为什么重写 MessageQueue
android
蝎子莱莱爱打怪2 天前
GitLab CI/CD + Docker Registry + K8s 部署完整实战指南
后端·docker·kubernetes
阿巴斯甜2 天前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker2 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95272 天前
Andorid Google 登录接入文档
android