强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Git 服务器搭建完全指南 / 第 6 章 - GitLab CE 企业方案

第 6 章 - GitLab CE 企业方案

GitLab Community Edition(CE)是最完整的开源 DevOps 平台,涵盖代码管理、CI/CD、包管理、安全扫描等全生命周期能力。

6.1 GitLab CE 概述

6.1.1 功能矩阵

功能模块GitLab CEGitLab EE(付费)
代码托管
CI/CD
Container Registry
Package Registry
Wiki
Issue Tracking
Code Review
Merge Requests
LDAP/SSO
Audit Logs基础完整
Advanced CI/CD
Security Scanning
Dependency Scanning
Code Owners
Epic/Portfolio

6.1.2 资源需求

部署规模用户数CPU内存磁盘
最小1-104 核8 GB50 GB
小型团队10-1008 核16 GB200 GB
中型团队100-50016 核32 GB500 GB+

注意: GitLab 对内存要求较高。低于 8 GB 内存会导致服务不稳定或启动失败。


6.2 安装部署

6.2.1 Omnibus 安装(推荐)

# 安装依赖
sudo apt install -y curl openssh-server ca-certificates postfix

# 添加 GitLab 软件源
curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash

# 安装 GitLab CE
sudo apt install gitlab-ce

# 配置外部 URL
sudo vim /etc/gitlab/gitlab.rb

关键配置:

# /etc/gitlab/gitlab.rb

# 外部访问 URL(必须配置正确)
external_url 'https://git.example.com'

# SSH 配置
gitlab_rails['gitlab_shell_ssh_port'] = 22

# 数据库配置(默认使用内置 PostgreSQL)
# 如使用外部数据库:
# postgresql['enable'] = false
# gitlab_rails['db_adapter'] = 'postgresql'
# gitlab_rails['db_host'] = '127.0.0.1'
# gitlab_rails['db_port'] = 5432
# gitlab_rails['db_database'] = 'gitlabhq_production'
# gitlab_rails['db_username'] = 'gitlab'
# gitlab_rails['db_password'] = 'password'

# 邮件配置
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = 'smtp.example.com'
gitlab_rails['smtp_port'] = 587
gitlab_rails['smtp_user_name'] = 'gitlab@example.com'
gitlab_rails['smtp_password'] = 'smtp_password'
gitlab_rails['smtp_domain'] = 'example.com'
gitlab_rails['smtp_authentication'] = 'login'
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['gitlab_email_from'] = 'gitlab@example.com'

# 备份设置
gitlab_rails['backup_path'] = '/var/opt/gitlab/backups'
gitlab_rails['backup_keep_time'] = 604800  # 7 天

# 内存优化(内存有限时)
# puma['worker_processes'] = 2
# sidekiq['max_concurrency'] = 10
# prometheus_monitoring['enable'] = false
# 应用配置并启动
sudo gitlab-ctl reconfigure

# 查看初始管理员密码
sudo cat /etc/gitlab/initial_root_password

# 访问 https://git.example.com
# 用户名: root
# 密码: 上面命令输出的密码

6.2.2 Docker Compose 部署

# docker-compose.yml
version: '3.6'

services:
  gitlab:
    image: gitlab/gitlab-ce:17.0-ce.0
    container_name: gitlab
    hostname: git.example.com
    restart: always
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'https://git.example.com'
        gitlab_rails['gitlab_shell_ssh_port'] = 2222
        gitlab_rails['lfs_enabled'] = true
        # 性能优化
        puma['worker_processes'] = 2
        sidekiq['max_concurrency'] = 10
    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'
# 启动
docker compose up -d

# 查看初始化进度(首次启动需要几分钟)
docker logs -f gitlab

# 获取初始密码
docker exec gitlab cat /etc/gitlab/initial_root_password

6.2.3 SSL 配置

方式一:Let’s Encrypt(推荐)

# /etc/gitlab/gitlab.rb
external_url 'https://git.example.com'

letsencrypt['enable'] = true
letsencrypt['contact_emails'] = ['admin@example.com']
letsencrypt['auto_renew'] = true
letsencrypt['auto_renew_hour'] = 3
letsencrypt['auto_renew_minute'] = 30
letsencrypt['auto_renew_day_of_month'] = "*/7"
sudo gitlab-ctl reconfigure

方式二:自签名证书(测试环境)

# 生成自签名证书
sudo mkdir -p /etc/gitlab/ssl
sudo openssl req -x509 -nodes -days 3650 \
  -newkey rsa:2048 \
  -keyout /etc/gitlab/ssl/git.example.com.key \
  -out /etc/gitlab/ssl/git.example.com.crt \
  -subj "/CN=git.example.com"

sudo chmod 600 /etc/gitlab/ssl/git.example.com.key
# /etc/gitlab/gitlab.rb
external_url 'https://git.example.com'
nginx['ssl_certificate'] = "/etc/gitlab/ssl/git.example.com.crt"
nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/git.example.com.key"

6.3 GitLab Runner(CI/CD 执行器)

6.3.1 安装 Runner

# 添加 GitLab Runner 软件源
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash

# 安装
sudo apt install gitlab-runner -y

6.3.2 注册 Runner

# 获取注册 Token
# 在 GitLab Web 界面: Admin Area → CI/CD → Runners
# 或项目级别: Settings → CI/CD → Runners

# 注册共享 Runner
sudo gitlab-runner register \
  --non-interactive \
  --url "https://git.example.com" \
  --registration-token "PROJECT_TOKEN" \
  --executor "docker" \
  --docker-image "alpine:latest" \
  --description "docker-runner" \
  --tag-list "docker,linux" \
  --run-untagged="true" \
  --locked="false"

# 注册 Shell Runner(需信任)
sudo gitlab-runner register \
  --non-interactive \
  --url "https://git.example.com" \
  --registration-token "PROJECT_TOKEN" \
  --executor "shell" \
  --description "shell-runner"

6.3.3 Runner 配置

# /etc/gitlab-runner/config.toml

concurrent = 4
check_interval = 3

[[runners]]
  name = "docker-runner"
  url = "https://git.example.com"
  token = "xxxxx"
  executor = "docker"
  
  [runners.docker]
    tls_verify = false
    image = "alpine:latest"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache"]
    shm_size = 0
    
  [runners.cache]
    Type = "local"
    Path = "/var/lib/gitlab-runner/cache"
    Shared = true
sudo systemctl restart gitlab-runner
sudo gitlab-runner verify

6.4 CI/CD 流水线

6.4.1 .gitlab-ci.yml 基础

# .gitlab-ci.yml

# 全局变量
variables:
  DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA

# 阶段定义
stages:
  - build
  - test
  - lint
  - deploy

# 构建阶段
build:
  stage: build
  image: node:20-alpine
  script:
    - npm ci --cache .npm
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 hour
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - .npm/
      - node_modules/

# 测试阶段
test:unit:
  stage: test
  image: node:20-alpine
  script:
    - npm ci --cache .npm
    - npm test
  coverage: '/Statements\s*:\s*(\d+\.?\d*)%/'
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - .npm/
      - node_modules/

# 代码检查
lint:
  stage: lint
  image: node:20-alpine
  script:
    - npm ci
    - npm run lint
  allow_failure: false

# 部署(仅 main 分支)
deploy:staging:
  stage: deploy
  image: alpine:latest
  script:
    - apk add --no-cache openssh-client
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | ssh-add -
    - ssh -o StrictHostKeyChecking=no deploy@staging-server "cd /app && git pull && npm ci && pm2 restart all"
  environment:
    name: staging
    url: https://staging.example.com
  only:
    - main
  when: manual

# 部署生产(Tag 触发)
deploy:production:
  stage: deploy
  image: alpine:latest
  script:
    - echo "Deploying to production..."
    - echo "Version: $CI_COMMIT_TAG"
  environment:
    name: production
    url: https://example.com
  only:
    - tags
  when: manual

6.4.2 Docker 镜像构建

# .gitlab-ci.yml

build:image:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
    - |
      if [ "$CI_COMMIT_BRANCH" == "main" ]; then
        docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA $CI_REGISTRY_IMAGE:latest
        docker push $CI_REGISTRY_IMAGE:latest
      fi
  only:
    - main
    - tags

6.4.3 环境与部署

# 多环境部署

deploy:dev:
  stage: deploy
  script:
    - echo "Deploying to dev"
  environment:
    name: dev
    url: https://dev.example.com
    on_stop: stop:dev
  only:
    - develop

deploy:staging:
  stage: deploy
  script:
    - echo "Deploying to staging"
  environment:
    name: staging
    url: https://staging.example.com
    on_stop: stop:staging
  only:
    - main

deploy:production:
  stage: deploy
  script:
    - echo "Deploying to production"
  environment:
    name: production
    url: https://example.com
  only:
    - tags
  when: manual

stop:dev:
  stage: deploy
  script:
    - echo "Stopping dev environment"
  environment:
    name: dev
    action: stop
  when: manual

6.5 用户和组管理

6.5.1 创建用户和组

通过 Web 界面或 API:

GITLAB_URL="https://git.example.com"
ADMIN_TOKEN="your_admin_token"

# 创建用户
curl -s -X POST -H "PRIVATE-TOKEN: $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  "$GITLAB_URL/api/v4/users" \
  -d '{
    "email": "alice@example.com",
    "username": "alice",
    "name": "Alice Zhang",
    "password": "StrongPassword123!",
    "skip_confirmation": true
  }' | jq '.id'

# 创建组
curl -s -X POST -H "PRIVATE-TOKEN: $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  "$GITLAB_URL/api/v4/groups" \
  -d '{
    "name": "Engineering",
    "path": "engineering",
    "description": "Engineering Team",
    "visibility": "internal"
  }' | jq '.id'

# 将用户添加到组
curl -s -X POST -H "PRIVATE-TOKEN: $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  "$GITLAB_URL/api/v4/groups/GROUP_ID/members" \
  -d '{
    "user_id": USER_ID,
    "access_level": 30
  }'

权限级别:

级别数值说明
Guest10可以创建 Issue
Reporter20可以克隆、查看代码
Developer30可以推送代码、创建 MR
Maintainer40可以管理项目设置
Owner50完全控制

6.6 管理和维护

6.6.1 备份

# 创建备份
sudo gitlab-backup create

# 备份文件位置
ls /var/opt/gitlab/backups/
# 1715300000_2026_05_10_gitlab_backup.tar

# 备份配置文件
sudo cp /etc/gitlab/gitlab.rb /var/opt/gitlab/backups/
sudo cp /etc/gitlab/gitlab-secrets.json /var/opt/gitlab/backups/

# 自动备份(Cron)
# sudo crontab -e
# 0 2 * * * /opt/gitlab/bin/gitlab-backup create CRON=1

6.6.2 恢复

# 停止相关服务
sudo gitlab-ctl stop puma
sudo gitlab-ctl stop sidekiq

# 恢复备份
sudo gitlab-backup restore BACKUP=1715300000_2026_05_10

# 重启
sudo gitlab-ctl start

6.6.3 日常运维命令

# 服务管理
sudo gitlab-ctl status          # 查看所有服务状态
sudo gitlab-ctl restart          # 重启所有服务
sudo gitlab-ctl tail             # 查看日志

# 维护
sudo gitlab-rake gitlab:check    # 健康检查
sudo gitlab-rake db:migrate      # 数据库迁移
sudo gitlab-ctl reconfigure      # 应用配置变更

# 清理
sudo gitlab-rake gitlab:cleanup:repos  # 清理孤立仓库
sudo gitlab-ctl garbage-collect         # Git 仓库 GC

6.7 性能优化

# /etc/gitlab/gitlab.rb

# Puma(Web 服务器)
puma['worker_processes'] = 4        # CPU 核心数
puma['worker_timeout'] = 60

# Sidekiq(后台任务)
sidekiq['max_concurrency'] = 20
sidekiq['min_concurrency'] = 5

# PostgreSQL
postgresql['shared_buffers'] = "2GB"   # 内存的 25%
postgresql['work_mem'] = "16MB"

# Redis
redis['maxmemory'] = "512mb"
redis['maxmemory_policy'] = "allkeys-lru"

# Gitaly(Git RPC 服务)
gitaly['concurrency'] = [
  { "RPC" => "/gitaly.SmartHTTPService/PostReceivePack", "MaxPerRepo" => 3 },
  { "RPC" => "/gitaly.SSHService/SSHUploadPack", "MaxPerRepo" => 3 }
]

# Nginx
nginx['worker_processes'] = 4
nginx['gzip'] = "on"
nginx['gzip_types'] = ["text/plain", "text/css", "application/json", "application/javascript"]

6.8 扩展阅读


本章小结

学到了什么关键要点
安装方式Omnibus 包(生产)/ Docker Compose(快速部署)
资源需求最低 8 GB 内存,建议 16 GB+
CI/CD.gitlab-ci.yml 定义流水线,GitLab Runner 执行任务
备份恢复gitlab-backup create 定时备份,配置文件需单独备份
性能优化Puma/Sidekiq/PostgreSQL 参数调优

下一章:第 7 章 - 多项目管理 — 设计合理的项目组织架构和权限继承体系。