在软件开发的生命周期中,持续集成和持续交付(CI/CD)已经成为现代开发流程的标配。但对于个人开发者或小型团队来说,直接在生产环境部署完整的Kubernetes集群可能显得过于复杂且资源消耗大。这正是Docker Compose方案的价值所在——它能在单台开发机上快速搭建起完整的CI/CD工具链,包括代码托管(GitLab)、自动化构建(Jenkins)和私有镜像仓库(Harbor)。
我曾为多个创业团队搭建过类似的开发环境,发现这种轻量化方案有三大优势:首先,它能在10分钟内完成基础服务的部署;其次,对硬件资源要求极低,8GB内存的笔记本就能流畅运行;最重要的是,所有配置都可以通过代码管理,方便团队共享和版本控制。下面我将分享经过多次实践验证的最佳配置方案。
在开始之前,请确保你的系统满足以下最低配置:
提示:在Windows系统上,建议使用WSL2作为Docker的后端,能获得更好的性能表现。
以下是经过优化的多服务编排文件,解决了常见端口冲突和数据持久化问题:
yaml复制version: '3.7'
services:
gitlab:
image: gitlab/gitlab-ce:latest
container_name: gitlab
restart: always
hostname: 'gitlab.example.com'
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://gitlab.example.com'
gitlab_rails['gitlab_shell_ssh_port'] = 2222
ports:
- "80:80"
- "443:443"
- "2222:22"
volumes:
- gitlab_config:/etc/gitlab
- gitlab_logs:/var/log/gitlab
- gitlab_data:/var/opt/gitlab
networks:
- cicd-net
jenkins:
image: jenkins/jenkins:lts
container_name: jenkins
restart: always
user: root
ports:
- "8080:8080"
- "50000:50000"
volumes:
- jenkins_home:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
environment:
- JAVA_OPTS=-Djenkins.install.runSetupWizard=false
depends_on:
- gitlab
networks:
- cicd-net
harbor:
image: goharbor/harbor-portal:v2.5.0
container_name: harbor
restart: always
depends_on:
- redis
- postgresql
environment:
- HARBOR_ADMIN_PASSWORD=Harbor12345
volumes:
- harbor_data:/data
ports:
- "8081:80"
networks:
- cicd-net
redis:
image: redis:alpine
restart: always
networks:
- cicd-net
postgresql:
image: postgres:13-alpine
restart: always
environment:
POSTGRES_PASSWORD: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- cicd-net
volumes:
gitlab_config:
gitlab_logs:
gitlab_data:
jenkins_home:
harbor_data:
postgres_data:
networks:
cicd-net:
driver: bridge
这个配置解决了几个关键问题:
启动服务后,首次访问GitLab需要设置管理员密码。完成基础设置后,建议进行以下优化:
bash复制# 进入GitLab容器
docker exec -it gitlab bash
# 调整Sidekiq并发数,提高性能
echo "sidekiq['concurrency'] = 5" >> /etc/gitlab/gitlab.rb
# 限制后台作业占用内存
echo "sidekiq['max_memory'] = 1024" >> /etc/gitlab/gitlab.rb
# 重新配置并重启
gitlab-ctl reconfigure
gitlab-ctl restart
关键配置项说明:
| 配置项 | 推荐值 | 说明 |
|---|---|---|
| unicorn['worker_processes'] | 2 | 根据CPU核心数调整 |
| postgresql['shared_buffers'] | 256MB | 数据库缓存大小 |
| prometheus_monitoring['enable'] | false | 开发环境可关闭监控 |
Jenkins首次启动后,需要安装以下核心插件:
推荐使用Jenkinsfile定义构建管道,以下是一个典型的Java项目构建示例:
groovy复制pipeline {
agent any
environment {
DOCKER_REGISTRY = "harbor.example.com"
PROJECT_NAME = "my-spring-app"
}
stages {
stage('Checkout') {
steps {
git branch: 'main',
url: 'http://gitlab.example.com/mygroup/myproject.git'
}
}
stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
}
}
stage('Docker Build') {
steps {
script {
docker.build("${DOCKER_REGISTRY}/${PROJECT_NAME}:${env.BUILD_NUMBER}")
}
}
}
stage('Deploy') {
steps {
script {
docker.withRegistry("http://${DOCKER_REGISTRY}", 'harbor-credentials') {
docker.image("${DOCKER_REGISTRY}/${PROJECT_NAME}:${env.BUILD_NUMBER}").push()
}
}
}
}
}
}
Harbor默认安装后,建议立即修改管理员密码并配置HTTPS访问。对于开发环境,我们可以使用自签名证书:
bash复制# 生成自签名证书
openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key \
-x509 -days 365 -out ca.crt \
-subj "/C=CN/ST=Beijing/L=Beijing/O=Example/OU=IT/CN=harbor.example.com"
# 将证书复制到Harbor配置目录
mkdir -p /data/cert
cp ca.crt ca.key /data/cert/
然后在Harbor的配置文件harbor.yml中启用HTTPS:
yaml复制https:
port: 443
certificate: /data/cert/ca.crt
private_key: /data/cert/ca.key
实现代码推送触发自动构建的完整步骤:
常见问题排查:
安全访问Harbor私有仓库需要配置Docker登录凭证:
harbor-credentials,用户名密码填写Harbor管理员账号docker.withRegistry方法认证:groovy复制docker.withRegistry("https://harbor.example.com", 'harbor-credentials') {
// 构建和推送镜像的操作
}
对于Java项目,可以使用多阶段Docker构建大幅减小镜像体积:
dockerfile复制# 构建阶段
FROM maven:3.8.4-openjdk-11 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
# 运行时阶段
FROM openjdk:11-jre-slim
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
这种构建方式可以将典型的Spring Boot应用镜像从300MB+减小到150MB左右。
使用内置命令监控各容器资源使用情况:
bash复制# 查看所有容器资源占用
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
# GitLab专用监控命令
docker exec gitlab gitlab-ctl status
资源占用过高时的优化策略:
GitLab:
/etc/gitlab/gitlab.rb中的unicorn和sidekiq配置Jenkins:
Harbor:
docker exec harbor harbor garbage-collect问题1:GitLab容器启动后502错误
bash复制# 查看日志定位问题
docker logs -f gitlab
# 常见解决方法
docker exec gitlab gitlab-ctl reconfigure
docker exec gitlab gitlab-ctl restart
问题2:Jenkins插件安装失败
bash复制docker exec jenkins sed -i 's/https:\/\/updates.jenkins.io\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' /var/jenkins_home/hudson.model.UpdateCenter.xml
docker restart jenkins
问题3:Harbor镜像推送失败
检查Docker客户端配置/etc/docker/daemon.json:
json复制{
"insecure-registries": ["harbor.example.com"]
}
然后重启Docker服务。
确保关键数据定期备份:
bash复制# GitLab备份
docker exec -t gitlab gitlab-backup create
# Jenkins备份
docker cp jenkins:/var/jenkins_home ./jenkins_backup
# Harbor备份
docker exec harbor harbor backup --with-db -f /backup/harbor-backup.tgz
推荐备份频率:
在docker-compose.yml中添加Traefik服务实现域名访问:
yaml复制services:
traefik:
image: traefik:v2.6
command:
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- cicd-net
gitlab:
# ...原有配置...
labels:
- "traefik.http.routers.gitlab.rule=Host(`gitlab.example.com`)"
- "traefik.http.services.gitlab.loadbalancer.server.port=80"
jenkins:
# ...原有配置...
labels:
- "traefik.http.routers.jenkins.rule=Host(`jenkins.example.com`)"
- "traefik.http.services.jenkins.loadbalancer.server.port=8080"
harbor:
# ...原有配置...
labels:
- "traefik.http.routers.harbor.rule=Host(`harbor.example.com`)"
- "traefik.http.services.harbor.loadbalancer.server.port=80"
在docker-compose.yml中添加SonarQube服务:
yaml复制services:
sonarqube:
image: sonarqube:lts-community
ports:
- "9000:9000"
environment:
- SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true
volumes:
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
networks:
- cicd-net
然后在Jenkinsfile中添加代码扫描阶段:
groovy复制stage('Code Analysis') {
steps {
withSonarQubeEnv('sonarqube') {
sh 'mvn sonar:sonar'
}
}
}
添加Nexus仓库服务加速依赖下载:
yaml复制services:
nexus:
image: sonatype/nexus3
ports:
- "8082:8081"
volumes:
- nexus_data:/nexus-data
networks:
- cicd-net
配置Maven使用Nexus镜像:
xml复制<!-- settings.xml -->
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://nexus:8081/repository/maven-public/</url>
</mirror>