从混合部署到高可用:在内网环境下搭建 GitLab-Jenkins-OpenResty的完整实战复盘20251014
🚀 从混合部署到高可用:我在内网环境下搭建 GitLab + Jenkins + OpenResty 的完整实战复盘
💡 作者注:本文记录了在构建企业内网 CI/CD 环境中的全过程,从「一体化混合部署」到「分层独立高可用」,完整涵盖 Docker 架构规划、插件离线化、镜像迁移与初始化陷阱等实战经验。
🧭 摘要(Summary)
在内网环境中,GitLab、Jenkins、OpenResty 等组件往往无法联网直接访问外部资源。本文记录了我从最初 单一 docker-compose 统一部署 到 分模块独立部署、离线插件打包、初始化优化 的完整演进过程。
最终实现了一个可稳定运行的企业级 CI/CD 架构,解决了插件下载失败、日志难排查、镜像路径冲突等关键问题。
一、背景与目标
目标:在公司内网环境下构建一套可稳定运行的 CI/CD 系统,包括:
- GitLab 代码仓库
- Jenkins 持续集成与任务编排
- OpenResty 反向代理与 HTTPS 支撑
- 插件离线加载与日志分层管理
二、第一阶段:单一 docker-compose 尝试
version: "3.8"services:gitlab:image: gitlab/gitlab-ce:latestcontainer_name: gitlabrestart: alwaysports:- "8081:8081"- "2222:22"environment:GITLAB_OMNIBUS_CONFIG: |external_url 'https://gitlab.example.local'gitlab_rails['gitlab_shell_ssh_port'] = 2222volumes:- ./gitlab/config:/etc/gitlab- ./gitlab/logs:/var/log/gitlab- ./gitlab/data:/var/opt/gitlabjenkins:image: jenkins/jenkins:ltscontainer_name: jenkinsrestart: alwaysports:- "28002:8080"- "50000:50000"volumes:- ./jenkins_home:/var/jenkins_homeenvironment:JAVA_OPTS: "-Djenkins.install.runSetupWizard=false"openresty:image: openresty/openresty:alpinecontainer_name: openrestyrestart: alwaysports:- "80:80"- "443:443"volumes:- ./conf:/etc/nginx/conf.d- ./logs:/usr/local/openresty/nginx/logs
问题:
- 日志混杂,异常难排查;
- Jenkins 插件下载失败(受限于内网环境);
- 镜像耦合度高。
三、第二阶段:独立部署与日志分层
/usr/local/docker/
├─ gitlab/
│ ├─ docker-compose.gitlab.yml
│ ├─ config/
│ ├─ logs/
│ └─ data/
├─ jenkins/
│ ├─ docker-compose.jenkins.yml
│ ├─ offline-plugins/
│ └─ jenkins_home/
└─ openresty/├─ docker-compose.openresty.yml├─ conf/└─ logs/
独立启动:
docker-compose -f docker-compose.gitlab.yml up -d
docker-compose -f docker-compose.jenkins.yml up -d
docker-compose -f docker-compose.openresty.yml up -d
四、第三阶段:离线 Jenkins 镜像打包
# 海外服务器执行
docker pull jenkins/jenkins:lts
docker run -u root -it jenkins/jenkins:lts /bin/bash
jenkins-plugin-cli --plugins workflow-aggregator git-client token-macro
docker commit <container_id> jenkins-offline:latest
docker save jenkins-offline:latest -o jenkins-offline.tar.gz# 内网导入
docker load -i jenkins-offline.tar.gz
⚠️ 问题:镜像路径差异导致 Jenkins 启动异常。
五、第四阶段:回归插件离线化方案
方案要点:
- 使用官方 Jenkins 镜像;
- 挂载离线插件目录
/usr/share/jenkins/ref/plugins
; - 避免重新构建镜像。
version: "3.8"services:jenkins:image: jenkins/jenkins:ltscontainer_name: jenkins-prodrestart: alwaysports:- "28002:8080"- "50000:50000"volumes:- ./jenkins_home:/var/jenkins_home- ./offline-plugins:/usr/share/jenkins/ref/pluginsenvironment:- JENKINS_ADMIN_ID=admin- JENKINS_ADMIN_PASSWORD=admin123
插件目录示例:
offline-plugins/
├─ workflow-aggregator.hpi
├─ git-client.hpi
├─ token-macro.hpi
└─ configuration-as-code.hpi
六、第五阶段:GitLab 与 Jenkins 初始化密码问题
GitLab 初始密码:
docker exec -it gitlab cat /etc/gitlab/initial_root_password
Jenkins 重置机制:
docker volume rm jenkins_jenkins_home
docker-compose up -d
七、完整部署结构与配置代码
/usr/local/docker/
├─ gitlab/
│ ├─ docker-compose.yml
│ ├─ config/
│ ├─ logs/
│ └─ data/
├─ jenkins/
│ ├─ docker-compose.yml
│ ├─ offline-plugins/
│ └─ jenkins_home/
└─ openresty/├─ docker-compose.yml├─ conf/│ ├─ default.conf│ └─ jenkins_proxy.conf└─ logs/
OpenResty 代理示例:
server {listen 443 ssl;server_name cicd.example.local;ssl_certificate /etc/nginx/certs/server.crt;ssl_certificate_key /etc/nginx/certs/server.key;location /jenkins/ {proxy_pass http://jenkins:8080/;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}location /gitlab/ {proxy_pass http://gitlab:8081/;}
}
八、经验总结
类别 | 关键要点 | 实践体会 |
---|---|---|
架构设计 | 模块独立、日志分层 | 排障效率提升数倍 |
插件管理 | 离线目录挂载 | 无需二次构建镜像 |
网络配置 | 统一代理层(OpenResty) | 安全控制点集中 |
初始化机制 | GitLab、Jenkins 差异理解 | 避免重复初始化 |
路径管理 | 容器路径一致性 | 环境迁移更顺畅 |
🏁 结语
“CICD 的稳定,不在于技术多复杂,而在于层次清晰、边界分明。”
每一次部署失败,都是一次架构进化的契机。