GitLab 是目前最流行的自托管 DevOps 平台之一,提供代码托管、CI/CD、容器注册表、项目管理等一站式服务。本文将详细介绍如何在 Ubuntu 22.04 上使用 Docker Compose 部署 GitLab 社区版,并进行生产级的配置优化。
1. 部署方案选择
在部署 GitLab 之前,需要根据团队规模和资源情况选择合适的方案。
| 方案 | 适用场景 | 优点 | 缺点 |
| Omnibus 一键包 | 单机部署、小团队 | 安装简单、开箱即用 | 升级复杂、隔离性差 |
| Docker Compose | 中小团队、容器化环境 | 部署快、版本管理清晰、易于备份 | 需先部署 Docker |
| Kubernetes Helm | 大型团队、高可用场景 | 弹性伸缩、滚动升级 | 运维门槛高、资源消耗大 |
本文采用 Docker Compose 方案,兼顾部署效率与可维护性。
2. 前提条件
2.1 硬件要求
GitLab 对系统资源有一定要求,建议配置如下:
| 用户数 | CPU | 内存 | 磁盘 |
| 1-10 人 | 2 核 | 4 GB | 50 GB SSD |
| 10-50 人 | 4 核 | 8 GB | 100 GB SSD |
| 50-200 人 | 8 核 | 16 GB | 200 GB SSD |
2.2 软件环境
- Ubuntu 22.04 LTS
- Docker Engine 24.0+
- Docker Compose V2(推荐)或 V1
2.3 安装 Docker
如果尚未安装 Docker,执行以下命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| sudo apt remove docker docker-engine docker.io containerd runc
sudo apt update sudo apt install -y ca-certificates curl gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \ sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \ "deb [arch=$(dpkg --print-architecture) \ signed-by=/etc/apt/keyrings/docker.gpg] \ https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo usermod -aG docker $USER newgrp docker
|
3. 部署 GitLab
3.1 创建目录结构
1 2
| mkdir -p /opt/gitlab/{config,logs,data} cd /opt/gitlab
|
3.2 编写 docker-compose.yml
创建 /opt/gitlab/docker-compose.yml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| version: '3.8'
services: gitlab: image: gitlab/gitlab-ce:17.2.0-ce.0 container_name: gitlab restart: always hostname: 'gitlab.example.com' environment: GITLAB_OMNIBUS_CONFIG: | # 外部访问 URL external_url 'https://gitlab.example.com'
gitlab_rails['time_zone'] = 'Asia/Shanghai'
gitlab_rails['smtp_enable'] = true gitlab_rails['smtp_address'] = 'smtp.qq.com' gitlab_rails['smtp_port'] = 465 gitlab_rails['smtp_user_name'] = 'your-email@qq.com' gitlab_rails['smtp_password'] = 'your-smtp-auth-code' gitlab_rails['smtp_domain'] = 'qq.com' gitlab_rails['smtp_authentication'] = 'login' gitlab_rails['smtp_enable_starttls_auto'] = true gitlab_rails['smtp_tls'] = true gitlab_rails['gitlab_email_from'] = 'your-email@qq.com' gitlab_rails['gitlab_email_reply_to'] = 'your-email@qq.com'
gitlab_rails['backup_keep_time'] = 604800 gitlab_rails['backup_path'] = '/var/opt/gitlab/backups'
gitlab_rails['gitlab_signup_enabled'] = false gitlab_rails['gitlab_signin_oauth_auto_ldap_sync'] = false
gitlab_rails['gitlab_shell_ssh_port'] = 2222
gitaly['configuration'] = { storage: [ { name: 'default', path: '/var/opt/gitlab/git-data/repositories', } ] }
puma['worker_processes'] = 3 puma['min_threads'] = 4 puma['max_threads'] = 16
sidekiq['concurrency'] = 10 ports: - '2222:22' - '80:80' - '443:443' volumes: - /opt/gitlab/config:/etc/gitlab - /opt/gitlab/logs:/var/log/gitlab - /opt/gitlab/data:/var/opt/gitlab shm_size: '256m' healthcheck: test: ["CMD", "curl", "-f", "http://localhost/-/health"] interval: 30s timeout: 10s retries: 5 start_period: 120s
|
3.3 启动 GitLab
1 2
| cd /opt/gitlab docker compose up -d
|
首次启动需要 3-5 分钟完成初始化配置,可以通过以下命令观察启动日志:
1
| docker compose logs -f gitlab
|
当看到类似 GitLab is ready! 的日志时,服务即启动完成。
3.4 获取初始管理员密码
1
| sudo docker exec -it gitlab grep 'Password:' /etc/gitlab/initial_root_password
|
默认用户名为 root,请首次登录后立即修改密码。
4. Nginx 反向代理与 HTTPS
在生产环境中,建议使用独立 Nginx 作为反向代理终止 HTTPS,而不是直接暴露 GitLab 的 80/443 端口。
4.1 安装 Nginx 和 Certbot
1
| sudo apt install -y nginx certbot python3-certbot-nginx
|
4.2 配置 Nginx 反向代理
创建 /etc/nginx/sites-available/gitlab:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| upstream gitlab { server 127.0.0.1:80; keepalive 32; }
server { listen 80; server_name gitlab.example.com; return 301 https://$server_name$request_uri; }
server { listen 443 ssl http2; server_name gitlab.example.com;
ssl_certificate /etc/letsencrypt/live/gitlab.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/gitlab.example.com/privkey.pem; ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=63072000" always;
location / { proxy_pass http://gitlab; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Ssl on; proxy_redirect off; proxy_buffering off;
proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
proxy_read_timeout 300s; proxy_connect_timeout 75s; } }
|
4.3 修改 GitLab external_url
配置 Nginx 后,需要更新 GitLab 的 external_url:
1 2 3 4 5 6 7 8 9 10
| environment: GITLAB_OMNIBUS_CONFIG: | external_url 'https://gitlab.example.com' nginx['listen_port'] = 80 nginx['listen_https'] = false nginx['proxy_set_headers'] = { 'X-Forwarded-Proto' => 'https', 'X-Forwarded-Ssl' => 'on' }
|
然后重启 GitLab:
1 2 3
| cd /opt/gitlab docker compose down docker compose up -d
|
5. 备份与恢复
5.1 手动备份
1 2 3 4 5
| docker exec -it gitlab gitlab-backup create
tar -czf /opt/gitlab-backups/gitlab-config-$(date +%Y%m%d).tar.gz /opt/gitlab/config
|
备份文件默认存储在 /opt/gitlab/data/backups/ 目录下。
5.2 定时自动备份
创建备份脚本 /opt/gitlab/backup.sh:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #!/bin/bash
BACKUP_DIR="/opt/gitlab-backups" RETENTION_DAYS=7 DATE=$(date +%Y%m%d_%H%M%S) LOG_FILE="/var/log/gitlab-backup.log"
echo "[$(date)] 开始 GitLab 备份" >> "$LOG_FILE"
docker exec gitlab gitlab-backup create STRATEGY=copy >> "$LOG_FILE" 2>&1 if [ $? -ne 0 ]; then echo "[$(date)] ❌ 备份失败!" >> "$LOG_FILE" exit 1 fi
mkdir -p "$BACKUP_DIR" tar -czf "$BACKUP_DIR/gitlab-config-$DATE.tar.gz" -C /opt/gitlab config >> "$LOG_FILE" 2>&1
find "$BACKUP_DIR" -name "gitlab-config-*.tar.gz" -mtime +$RETENTION_DAYS -delete find /opt/gitlab/data/backups -name "*.tar" -mtime +$RETENTION_DAYS -delete
echo "[$(date)] ✅ GitLab 备份完成" >> "$LOG_FILE"
|
添加执行权限并设置定时任务:
1 2 3 4
| chmod +x /opt/gitlab/backup.sh
echo "0 3 * * * /opt/gitlab/backup.sh" | sudo crontab -
|
5.3 恢复备份
1 2 3 4 5 6 7 8 9 10 11 12
| docker exec gitlab gitlab-ctl stop puma docker exec gitlab gitlab-ctl stop sidekiq
docker exec gitlab gitlab-backup restore BACKUP=1712345678_2026_06_17_17.2.0
docker exec gitlab gitlab-ctl restart
docker exec gitlab gitlab-ctl reconfigure
|
注意:恢复操作需要版本号完全匹配,建议在恢复前记录当前运行版本。
6. GitLab Runner 注册
GitLab Runner 是执行 CI/CD 任务的组件,以 Docker 方式部署方便灵活。
6.1 部署 Runner
1 2 3 4 5 6 7 8
| mkdir -p /opt/gitlab-runner/{config,data}
docker run -d --name gitlab-runner --restart always \ -v /opt/gitlab-runner/config:/etc/gitlab-runner \ -v /var/run/docker.sock:/var/run/docker.sock \ gitlab/gitlab-runner:latest
|
6.2 注册 Runner
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| docker exec -it gitlab-runner gitlab-runner register
docker exec -it gitlab-runner gitlab-runner register \ --non-interactive \ --url "https://gitlab.example.com" \ --registration-token "YOUR_REGISTRATION_TOKEN" \ --executor "docker" \ --docker-image alpine:latest \ --docker-volumes /var/run/docker.sock:/var/run/docker.sock \ --description "docker-runner" \ --tag-list "docker,linux" \ --run-untagged="true" \ --locked="false"
|
Runner Token 可以在 GitLab 管理界面获取:Settings → CI/CD → Runners → Expand → Specific runners。
6.3 Runner 配置优化
编辑 /opt/gitlab-runner/config/config.toml,对 Runner 配置进行调优:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| concurrent = 4
[[runners]] name = "docker-runner" url = "https://gitlab.example.com" token = "YOUR_TOKEN" executor = "docker" [runners.docker] image = "alpine:latest" privileged = false disable_cache = false volumes = ["/cache"] shm_size = 256m pull_policy = "if-not-present" oom_kill_disable = false memory_limit = "2g" cpus = "2" helper_image = "gitlab/gitlab-runner-helper:x86_64-latest" [runners.cache] Type = "s3" Path = "gitlab-runner-cache" Shared = true
|
7. GitLab CI/CD 基础配置
7.1 基础 .gitlab-ci.yml 模板
在项目根目录创建 .gitlab-ci.yml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| stages: - test - build - deploy
variables: DOCKER_IMAGE_TAG: $CI_COMMIT_SHORT_SHA
test: stage: test image: node:20-alpine script: - npm install - npm run lint - npm test only: - main - merge_requests
build: stage: build image: docker:24 services: - docker:24-dind script: - docker build -t registry.example.com/myapp:$DOCKER_IMAGE_TAG . - docker push registry.example.com/myapp:$DOCKER_IMAGE_TAG only: - main
deploy: stage: deploy image: alpine:latest before_script: - apk add --no-cache openssh-client script: - scp -o StrictHostKeyChecking=no docker-compose.yml deploy@server:/opt/app/ - ssh deploy@server "cd /opt/app && docker compose pull && docker compose up -d" only: - main when: manual
|
7.2 注册表配置(可选)
如需使用 GitLab 内置的 Container Registry:
1 2 3 4 5 6 7 8 9 10
| environment: GITLAB_OMNIBUS_CONFIG: | # 启用 Container Registry registry_external_url 'https://registry.example.com' registry_nginx['listen_port'] = 5050 registry_nginx['listen_https'] = false
ports: - '5050:5050'
|
8. 性能优化
8.1 GitLab 内核参数调优
1 2 3 4 5 6 7 8
| echo "fs.file-max = 100000" | sudo tee -a /etc/sysctl.conf
echo "net.netfilter.nf_conntrack_max = 262144" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
|
8.2 Docker 资源限制
1 2 3 4 5 6 7 8 9 10 11
| services: gitlab: deploy: resources: limits: cpus: '4' memory: 8G reservations: cpus: '2' memory: 4G
|
8.3 数据库优化
GitLab 使用 PostgreSQL 作为数据库,可以单独优化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| services: gitlab: environment: GITLAB_OMNIBUS_CONFIG: | # 使用外部数据库 postgresql['enable'] = false gitlab_rails['db_adapter'] = 'postgresql' gitlab_rails['db_username'] = 'gitlab' gitlab_rails['db_password'] = 'secure_password' gitlab_rails['db_host'] = 'postgresql' gitlab_rails['db_port'] = 5432
postgresql: image: postgres:16-alpine container_name: gitlab-postgresql restart: always environment: POSTGRES_USER: gitlab POSTGRES_PASSWORD: secure_password POSTGRES_DB: gitlabhq_production volumes: - /opt/gitlab/postgresql:/var/lib/postgresql/data deploy: resources: limits: memory: 2G
|
9. 安全加固
9.1 防火墙配置
1 2 3 4 5 6
| sudo ufw allow 22/tcp sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw allow 2222/tcp sudo ufw deny 5050 sudo ufw enable
|
9.2 安全配置清单
| 配置项 | 建议值 | 说明 |
| 开放注册 | 关闭 | 防止恶意注册 |
| 密码复杂度 | 最低12位,含大小写+数字+特殊字符 | GitLab 默认已启用 |
| 2FA 强制 | 管理员强制启用 | Settings → General → Sign-in restrictions |
| Session 超时 | 12 小时 | Settings → General → Session duration |
| IP 白名单 | 仅允许内网访问管理面板 | 可通过 Nginx 限制 |
| Runner 权限 | 非 privileged 模式 | 防止容器逃逸 |
| HTTPS 强制 | 启用 | Nginx 重写所有 HTTP 到 HTTPS |
| 数据加密 | AES-256 | 备份文件加密存储 |
9.3 定期更新
GitLab 社区版每月 22 日左右发布新版本,建议定期更新:
1 2 3 4 5 6 7
| docker exec gitlab cat /opt/gitlab/embedded/service/gitlab-rails/VERSION
cd /opt/gitlab docker compose pull docker compose up -d
|
10. 常见问题排查
| 问题 | 可能原因 | 解决方法 |
| 502 Bad Gateway | Puma/Sidekiq 未完全启动 | 等待 2-3 分钟或检查日志 docker compose logs gitlab |
| SSH 连接被拒绝 | SSH 端口映射冲突 | 确认主机 2222 端口未被占用,ss -tlnp | grep 2222 |
| 邮件发送失败 | SMTP 配置错误 | 检查 SMTP 地址、端口、认证码,测试 docker exec gitlab gitlab-rails console |
| 磁盘空间不足 | 备份文件未清理 | docker exec gitlab du -sh /var/opt/gitlab/backups,清理过期备份 |
| Runner 无法连接 | 注册 Token 过期或网络问题 | 重新注册 Runner,确认 --url 参数正确 |
| 容器频繁重启 | 系统资源不足 | docker stats 查看资源使用,增加主机内存 |
| API 返回 413 | Nginx 上传大小限制 | 在 Nginx 配置中添加 client_max_body_size 0; |
| Git push 超时 | Nginx proxy_read_timeout 不足 | 增加超时时间至 600s |
11. 总结
本文详细介绍了在 Ubuntu 22.04 上使用 Docker Compose 部署 GitLab 社区版的完整流程,涵盖:
- Docker 环境准备与 GitLab 容器化部署
- Nginx 反向代理与 HTTPS 配置
- 自动备份与恢复方案
- GitLab Runner 注册与 CI/CD 基础配置
- 性能优化与安全加固
- 常见问题排查
GitLab 是一个非常成熟的 DevOps 平台,通过容器化部署可以极大降低运维复杂度。建议在生产环境中配合独立的 PostgreSQL 和 Redis 实例以提升性能和可用性,同时定期检查安全配置和版本更新。
本文由AI辅助生成,内容仅供参考