Docker Compose编排GitLab:从单机部署到生产级配置
1. 为什么选择Docker Compose部署GitLab
第一次接触GitLab时,我尝试过直接在服务器上安装,结果被复杂的依赖关系和配置过程折磨得够呛。后来发现用Docker部署简直像发现了新大陆——特别是配合Docker Compose,所有服务都能通过一个YAML文件搞定。这种"基础设施即代码"的方式,让部署过程变得可重复、可版本控制。
GitLab官方提供的Docker镜像已经预配置了所有必要组件(包括Nginx、PostgreSQL、Redis等),但默认的单容器方案并不适合生产环境。我在实际项目中踩过的坑包括:数据丢失风险、性能瓶颈、升级困难等。而通过Docker Compose编排,可以实现:
- 服务分离:数据库、缓存等组件独立部署
- 资源隔离:为不同服务分配CPU/内存限制
- 灵活扩展:未来可轻松添加CI Runner等组件
2. 基础环境准备
2.1 硬件资源配置建议
根据我的经验,GitLab对资源的需求是这样的:
- 开发测试环境:2核CPU/4GB内存/50GB存储
- 20人团队生产环境:4核CPU/8GB内存/200GB存储
- 100人以上团队:建议8核CPU/16GB内存+SSD存储
特别提醒:GitLab运行时会启动多个Unicorn worker进程,内存不足会导致502错误。我曾在一个2GB内存的机器上部署,结果频繁崩溃,后来发现官方建议至少4GB。
2.2 软件依赖安装
首先确保宿主机已安装最新版Docker和Docker Compose:
# 安装Docker curl -fsSL https://get.docker.com | sh sudo systemctl enable --now docker # 安装Docker Compose sudo curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose验证安装:
docker --version # 应显示Docker版本 docker-compose --version # 应显示Compose版本3. 编写docker-compose.yml文件
3.1 最小化生产配置
这是我经过多个项目验证的基础模板:
version: '3.8' services: gitlab: image: gitlab/gitlab-ce:latest container_name: gitlab hostname: gitlab.yourdomain.com restart: unless-stopped environment: GITLAB_OMNIBUS_CONFIG: | external_url 'https://gitlab.yourdomain.com' gitlab_rails['time_zone'] = 'Asia/Shanghai' 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 shm_size: '256m'关键参数说明:
hostname:必须设置为最终访问的域名GITLAB_OMNIBUS_CONFIG:GitLab的核心配置shm_size:解决Sidekiq内存不足问题
3.2 集成PostgreSQL和Redis
生产环境建议使用独立数据库:
services: postgres: image: postgres:13 container_name: gitlab-postgres environment: POSTGRES_USER: gitlab POSTGRES_PASSWORD: your_strong_password POSTGRES_DB: gitlabhq_production volumes: - ./postgres/data:/var/lib/postgresql/data restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U gitlab"] interval: 10s timeout: 5s retries: 5 redis: image: redis:6 container_name: gitlab-redis command: ["redis-server", "--requirepass yourredispassword"] volumes: - ./redis/data:/data restart: unless-stopped healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 gitlab: depends_on: postgres: condition: service_healthy redis: condition: service_healthy environment: GITLAB_OMNIBUS_CONFIG: | postgresql['enable'] = false redis['enable'] = false gitlab_rails['db_adapter'] = 'postgresql' gitlab_rails['db_host'] = 'postgres' gitlab_rails['db_port'] = 5432 gitlab_rails['db_username'] = 'gitlab' gitlab_rails['db_password'] = 'your_strong_password' gitlab_rails['redis_host'] = 'redis' gitlab_rails['redis_port'] = 6379 gitlab_rails['redis_password'] = 'yourredispassword'4. HTTPS安全配置
4.1 自动获取Let's Encrypt证书
最简便的HTTPS配置方式:
environment: GITLAB_OMNIBUS_CONFIG: | letsencrypt['enable'] = true letsencrypt['contact_emails'] = ['admin@yourdomain.com'] letsencrypt['auto_renew'] = true letsencrypt['auto_renew_hour'] = 0 letsencrypt['auto_renew_minute'] = 30 letsencrypt['auto_renew_day_of_month'] = "*/4"4.2 手动配置已有证书
如果有商业证书,可以这样配置:
mkdir -p gitlab/config/ssl # 将证书文件放入gitlab/config/ssl # 重命名为gitlab.yourdomain.com.crt和gitlab.yourdomain.com.key然后在docker-compose.yml中添加:
environment: GITLAB_OMNIBUS_CONFIG: | nginx['ssl_certificate'] = "/etc/gitlab/ssl/gitlab.yourdomain.com.crt" nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/gitlab.yourdomain.com.key" nginx['redirect_http_to_https'] = true5. 生产环境优化配置
5.1 资源限制与健康检查
防止GitLab占用过多资源:
gitlab: deploy: resources: limits: cpus: '2' memory: 4G reservations: memory: 2G healthcheck: test: ["CMD", "/opt/gitlab/bin/gitlab-healthcheck", "--fail"] interval: 1m timeout: 10s retries: 35.2 邮件通知配置
以腾讯企业邮箱为例:
environment: GITLAB_OMNIBUS_CONFIG: | gitlab_rails['smtp_enable'] = true gitlab_rails['smtp_address'] = "smtp.exmail.qq.com" gitlab_rails['smtp_port'] = 465 gitlab_rails['smtp_user_name'] = "gitlab@yourdomain.com" gitlab_rails['smtp_password'] = "your_password" gitlab_rails['smtp_domain'] = "yourdomain.com" gitlab_rails['smtp_authentication'] = "login" gitlab_rails['smtp_enable_starttls_auto'] = true gitlab_rails['smtp_tls'] = true gitlab_rails['gitlab_email_from'] = 'gitlab@yourdomain.com'测试邮件发送:
docker exec -it gitlab gitlab-rails console Notify.test_email('recipient@example.com', 'Test Subject', 'Test Body').deliver_now6. 日常维护操作
6.1 数据备份与恢复
配置自动备份:
environment: GITLAB_OMNIBUS_CONFIG: | gitlab_rails['backup_path'] = "/var/opt/gitlab/backups" gitlab_rails['backup_keep_time'] = 604800 # 保留7天手动备份命令:
docker exec -it gitlab gitlab-backup create恢复备份:
# 先将备份文件放入gitlab/data/backups docker exec -it gitlab gitlab-backup restore BACKUP=文件名前缀6.2 版本升级步骤
安全升级流程:
- 停止当前容器:
docker-compose stop gitlab - 备份数据:
docker-compose exec gitlab gitlab-backup create - 拉取新镜像:
docker-compose pull gitlab - 启动新版本:
docker-compose up -d gitlab - 监控日志:
docker-compose logs -f gitlab
建议在非工作时间进行升级,大型版本升级(如14→15)可能需要更长时间。
7. 常见问题排查
问题1:502 Whoops错误
- 检查内存是否不足:
docker stats gitlab - 查看日志:
docker logs --tail 100 gitlab - 解决方案:增加内存或调整Unicorn worker数量
问题2:SSH克隆失败
- 确认gitlab_rails['gitlab_shell_ssh_port']与映射端口一致
- 检查防火墙规则:
iptables -L -n
问题3:邮件发送失败
- 测试Telnet连接:
docker exec -it gitlab telnet smtp.exmail.qq.com 465 - 检查垃圾邮件箱
- 尝试更换端口(465/587)
问题4:容器启动超时
- 增加启动超时时间:
gitlab: deploy: resources: limits: cpus: '4' memory: 8G healthcheck: start_period: 10m
记得第一次成功部署GitLab后,我兴奋地给团队发邮件通知,结果因为SMTP配置错误,所有人都没收到邮件。后来通过docker exec -it gitlab tail -f /var/log/gitlab/mailroom/current才找到问题所在——邮箱密码里有个特殊字符需要转义。这种实战经验,才是真正宝贵的知识。
