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'] = true

5. 生产环境优化配置

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: 3

5.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_now

6. 日常维护操作

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 版本升级步骤

安全升级流程:

  1. 停止当前容器: docker-compose stop gitlab
  2. 备份数据: docker-compose exec gitlab gitlab-backup create
  3. 拉取新镜像: docker-compose pull gitlab
  4. 启动新版本: docker-compose up -d gitlab
  5. 监控日志: 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 才找到问题所在——邮箱密码里有个特殊字符需要转义。这种实战经验,才是真正宝贵的知识。

更多推荐