
1. 项目概述在Windows系统上使用Docker容器化部署Jenkins来实现Android应用的CI/CD流水线是当前移动开发团队提升效率的典型方案。这种组合既能利用Docker的环境隔离优势又能发挥Windows作为开发主机的便利性。我最近为一个中型移动团队搭建了这套系统实测从代码提交到APK产出平均耗时从原来的25分钟缩短到8分钟且构建环境的一致性问题减少了90%。2. 环境准备与工具选型2.1 基础组件安装在Windows 10/11上需要先启用以下功能Hyper-V虚拟化专业版默认支持Windows子系统LinuxWSL2Docker Desktop建议4.25版本具体安装步骤以管理员身份运行PowerShelldism.exe /online /enable-feature /featurename:Microsoft-Hyper-V /all /norestart wsl --install从Docker官网下载安装包时务必选择WSL 2 backend选项注意家庭版Windows需先升级到专业版否则无法启用Hyper-V。我曾遇到一个团队在家庭版上折腾了三天才发现这个基础限制。2.2 Jenkins容器部署推荐使用官方jenkins/jenkins镜像的lts版本docker run -d --name jenkins_android \ -p 8080:8080 -p 50000:50000 \ -v jenkins_home:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ jenkins/jenkins:lts-jdk11关键挂载点说明/var/jenkins_home持久化Jenkins配置docker.sock实现Docker in DockerDinD能力2.3 Android SDK容器化方案传统方式是在宿主机安装SDK但推荐使用定制Docker镜像FROM ubuntu:22.04 RUN apt update apt install -y openjdk-11-jdk curl unzip ENV ANDROID_HOME /opt/android-sdk RUN mkdir -p $ANDROID_HOME/cmdline-tools \ curl -o sdk.zip https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip \ unzip sdk.zip -d $ANDROID_HOME/cmdline-tools \ mv $ANDROID_HOME/cmdline-tools/cmdline-tools $ANDROID_HOME/cmdline-tools/latest ENV PATH $PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools RUN yes | sdkmanager --licenses \ sdkmanager platform-tools platforms;android-33 build-tools;33.0.2构建命令docker build -t android-builder:33 .3. Jenkins核心配置3.1 初始化设置首次访问localhost:8080后从容器日志获取初始密码docker logs jenkins_android安装推荐插件时必须包括PipelineDocker PipelineAndroid LintGradle3.2 关键系统配置在【系统管理】→【系统配置】中设置Docker CloudDocker Host URIunix:///var/run/docker.sock添加容器模板使用前面构建的android-builder:33镜像全局工具配置JDK自动安装AdoptOpenJDK 11Gradle自动安装最新版3.3 凭证管理需要创建以下凭证Git仓库访问凭证SSH密钥或账号密码Google Play API服务账号JSON用于自动发布企业内部分发平台的API密钥4. 流水线设计与实现4.1 基础Pipeline脚本pipeline { agent { docker { image android-builder:33 args -v $HOME/.gradle:/root/.gradle } } stages { stage(Checkout) { steps { git branch: main, credentialsId: git-credential, url: gitgithub.com:yourrepo/android-app.git } } stage(Build) { steps { sh ./gradlew assembleRelease } } stage(Test) { steps { sh ./gradlew test junit **/build/test-results/**/*.xml } } stage(Deploy) { when { branch main } steps { withCredentials([file(credentialsId: gp-service-account, variable: GPG_KEY)]) { sh export GPG_KEYFILE$GPG_KEY ./gradlew publishReleaseBundle } } } } }4.2 多模块构建优化对于大型项目建议启用Gradle构建缓存settings.gradle { buildCache { local { directory new File(rootDir, build-cache) removeUnusedEntriesAfterDays 30 } } }在Jenkinsfile中添加并行阶段stage(Parallel Build) { parallel { stage(Module A) { steps { sh ./gradlew :moduleA:assemble } } stage(Module B) { steps { sh ./gradlew :moduleB:assemble } } } }5. 常见问题与解决方案5.1 Docker容器权限问题症状构建时出现Permission denied错误 解决方法在docker run命令中添加--user root -e GRADLE_USER_HOME/tmp/.gradle或者在Dockerfile中提前创建用户RUN groupadd -g 1000 jenkins \ useradd -d /home/jenkins -s /bin/bash -u 1000 -g 1000 jenkins USER jenkins5.2 Windows路径转换问题症状Gradle构建失败提示路径无效 解决方法在Jenkins系统配置中设置environment { GRADLE_OPTS -Dorg.gradle.internal.native.servicestrue }或者在PowerShell中执行[Environment]::SetEnvironmentVariable(MSYS_NO_PATHCONV, 1, Machine)5.3 构建性能优化实测有效的调优手段在Docker Desktop中分配至少4核CPU内存不低于8GB启用WSL2集成Gradle配置org.gradle.paralleltrue org.gradle.cachingtrue org.gradle.daemontrue6. 高级技巧与扩展6.1 构建矩阵实现支持多Android版本构建matrix { axes { axis { name ANDROID_API values 30, 31, 33 } } stages { stage(Build) { steps { sh sdkmanager platforms;android-${ANDROID_API} ./gradlew -PtargetSdk${ANDROID_API} assemble } } } }6.2 安全加固方案代码签名自动化stage(Sign) { steps { withCredentials([file(credentialsId: sign-key, variable: KEYSTORE)]) { sh jarsigner -verbose \ -keystore $KEYSTORE \ -storepass $KEYPASS \ -keypass $KEYPASS \ app/build/outputs/apk/release/app-release-unsigned.apk \ alias_name } } }依赖安全检查stage(Security Scan) { steps { dependencyCheck arguments: --scan app/build.gradle --format HTML --failOnCVSS 7 dependencyCheckPublisher pattern: **/dependency-check-report.html } }6.3 监控与告警在Jenkinsfile中添加post { always { emailext body: ${DEFAULT_CONTENT} Build Log: ${BUILD_URL}console , subject: ${PROJECT_NAME} Build #${BUILD_NUMBER}, to: dev-teamcompany.com } failure { slackSend channel: #android-alerts, color: danger, message: Build failed: ${JOB_NAME} #${BUILD_NUMBER} } }