香港服务器搭建GitLab自托管 + CI/CD流水线:从代码提交到自动部署全流程配置

香港服务器搭建GitLab自托管 + CI/CD流水线:从代码提交到自动部署全流程配置

GitHub Actions 虽然方便,但代码和 CI/CD 流程都在 GitHub 服务器上运行,对代码保密性有要求的企业不适合。在香港服务器上自托管 GitLab CE(社区版,免费),既保证代码私密性,又获得完整的 CI/CD 能力,且 GitLab 内置的 Container Registry、Issue 追踪、Code Review 工具让研发团队无需额外工具。


一、GitLab CE 系统要求

用户规模最低配置推荐配置
1~10 人团队4核8G4核16G
10~50 人团队8核16G16核32G
50~200 人团队16核32G32核64G

二、Docker Compose 部署 GitLab

<code"># /opt/gitlab/docker-compose.yml
version: '3.8'

services:
  gitlab:
    image: gitlab/gitlab-ce:17.3.0-ce.0
    container_name: gitlab
    restart: unless-stopped
    hostname: gitlab.yourdomain.com
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'https://gitlab.yourdomain.com'

        # HTTPS 配置(使用已有证书)
        nginx['ssl_certificate'] = '/etc/gitlab/ssl/gitlab.crt'
        nginx['ssl_certificate_key'] = '/etc/gitlab/ssl/gitlab.key'
        nginx['redirect_http_to_https'] = true

        # 邮件配置(用于用户注册、通知)
        gitlab_rails['smtp_enable'] = true
        gitlab_rails['smtp_address'] = "smtp.gmail.com"
        gitlab_rails['smtp_port'] = 587
        gitlab_rails['smtp_user_name'] = "gitlab@yourdomain.com"
        gitlab_rails['smtp_password'] = "app_password"
        gitlab_rails['smtp_tls'] = false
        gitlab_rails['smtp_starttls_auto'] = true
        gitlab_rails['gitlab_email_from'] = "gitlab@yourdomain.com"

        # 性能调优(4核8G 服务器)
        puma['worker_processes'] = 3
        sidekiq['max_concurrency'] = 10
        postgresql['shared_buffers'] = "512MB"

        # 禁用不需要的服务(节省资源)
        prometheus_monitoring['enable'] = false
        grafana['enable'] = false

        # 注册限制(仅允许邀请注册)
        gitlab_rails['gitlab_signup_enabled'] = false

    ports:
      - "80:80"
      - "443:443"
      - "22:22"        # SSH Git 操作
    volumes:
      - /opt/gitlab/config:/etc/gitlab
      - /opt/gitlab/logs:/var/log/gitlab
      - /opt/gitlab/data:/var/opt/gitlab
      - /etc/letsencrypt/live/gitlab.yourdomain.com/fullchain.pem:/etc/gitlab/ssl/gitlab.crt:ro
      - /etc/letsencrypt/live/gitlab.yourdomain.com/privkey.pem:/etc/gitlab/ssl/gitlab.key:ro
    shm_size: '256m'
<code"># 首次启动(约3~5分钟)
cd /opt/gitlab && docker compose up -d

# 查看启动进度
docker logs -f gitlab | grep "gitlab Reconfigured"

# 获取初始 root 密码
docker exec gitlab grep 'Password:' /etc/gitlab/initial_root_password

# 访问 https://gitlab.yourdomain.com,使用 root 账号登录

三、注册 GitLab Runner

<code"># 在另一台服务器(或同台)安装 GitLab Runner
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | bash
apt install -y gitlab-runner

# 在 GitLab 界面获取 Runner 注册 Token:
# Settings → CI/CD → Runners → New project runner

# 注册 Runner(Docker 执行器)
gitlab-runner register \
  --url "https://gitlab.yourdomain.com" \
  --token "your_runner_token" \
  --executor "docker" \
  --docker-image "alpine:latest" \
  --description "hk-docker-runner" \
  --tag-list "docker,hk" \
  --run-untagged true \
  --locked false

# 查看 Runner 状态
gitlab-runner status
gitlab-runner list

四、CI/CD 流水线配置(.gitlab-ci.yml)

<code"># .gitlab-ci.yml(放在项目根目录)

stages:
  - test
  - build
  - deploy

variables:
  IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
  DEPLOY_HOST: "root@香港服务器IP"

# ── 阶段1:代码测试 ──
test:unit:
  stage: test
  image: python:3.12-slim
  cache:
    key: "$CI_COMMIT_REF_SLUG"
    paths:
      - .pip-cache/
  script:
    - pip install -r requirements.txt --cache-dir .pip-cache
    - pytest tests/ -v --cov=app --cov-report=xml
  coverage: '/TOTAL.*\s+(\d+%)$/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage.xml
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == "main"

# ── 阶段2:构建 Docker 镜像 ──
build:docker:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build -t $IMAGE_TAG .
    - docker push $IMAGE_TAG
    # 同时打 latest 标签
    - docker tag $IMAGE_TAG $CI_REGISTRY_IMAGE:latest
    - docker push $CI_REGISTRY_IMAGE:latest
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

# ── 阶段3:部署到生产服务器 ──
deploy:production:
  stage: deploy
  image: alpine:latest
  before_script:
    - apk add --no-cache openssh-client
    - eval $(ssh-agent -s)
    # SSH 私钥从 GitLab CI/CD Variables 读取(不硬编码)
    - echo "$DEPLOY_SSH_KEY" | ssh-add -
    - mkdir -p ~/.ssh && chmod 700 ~/.ssh
    - ssh-keyscan -H 香港服务器IP >> ~/.ssh/known_hosts
  script:
    - |
      ssh $DEPLOY_HOST "
        docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY &&
        docker pull $IMAGE_TAG &&
        docker stop myapp 2>/dev/null || true &&
        docker rm myapp 2>/dev/null || true &&
        docker run -d --name myapp \
          --restart unless-stopped \
          -p 127.0.0.1:8000:8000 \
          --env-file /opt/myapp/.env \
          $IMAGE_TAG &&
        sleep 5 &&
        curl -sf http://localhost:8000/health && echo '部署成功 ✓'
      "
  environment:
    name: production
    url: https://yourdomain.com
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  when: manual    # 生产部署需要人工确认

五、在 GitLab 界面配置 CI/CD 变量

「项目 → Settings → CI/CD → Variables」中添加:

变量名是否加密
DEPLOY_SSH_KEY部署用 SSH 私钥内容✅ Masked + Protected
DATABASE_URL生产数据库连接字符串✅ Masked
STRIPE_SECRET_KEYStripe 密钥✅ Masked

六、流水线效果展示

<code">
代码推送到 main 分支
    │
    ▼
✅ test:unit(约 2 分钟)
    ├── 单元测试通过(98% 覆盖率)
    └── 覆盖率报告上传到 GitLab
    │
    ▼
✅ build:docker(约 3 分钟)
    ├── 构建 Docker 镜像
    └── 推送到 GitLab Container Registry
    │
    ▼
⏸️ deploy:production(等待手动确认)
    └── 点击「Run」→ 自动 SSH 到香港服务器 → 拉取新镜像 → 重启容器 → 健康检查

七、总结

GitLab 自托管将代码仓库、CI/CD、镜像仓库集于一身,数据完全在自己的香港服务器上,满足代码保密和合规要求。CI/CD 流水线将「人工测试→人工构建→人工部署」的重复劳动完全自动化,开发团队专注于写代码,其余交给流水线处理。

Telegram