GitLab Package Registry 与 Composer 集成

解读

国内大厂与二线互联网公司普遍自建 GitLab 私有实例,用来托管代码、CI/CD 与制品库。Composer 作为 PHP 事实上的包管理器,其官方仓库 Packagist 在海外,拉取速度不稳定,且公网传输不符合金融、政企类公司的安全合规要求。因此“把公司自研的 SDK、工具包、业务组件发布到 GitLab Package Registry,并让 Composer 像使用 Packagist 一样一键安装”成为高频面试题。面试官想确认候选人是否真正落地过私有包治理、CI 发布、认证鉴权、性能优化等工程细节,而不仅仅会跑 composer install。

知识点

  1. GitLab Package Registry 的两种 Composer 仓库形态:project-level(单项目)与 group-level(聚合组)。
  2. composer.json 中 repositories 字段的五种类型:composer、vcs、path、artifact、package;本题需使用 composer 类型并配置 https://gitlab.example.com/api/v4/group/xxx/packages/composer/packages.json。
  3. GitLab 的三种认证方式:
    • 私有 token(Personal Access Token,最少权限 read_api、read_repository)
    • 项目部署令牌(Deploy Token,适合 CI 只读)
    • OAuth2(内部 SSO 场景)
  4. auth.json 与 COMPOSER_AUTH 环境变量的优先级、落盘风险、.gitignore 规则。
  5. CI/CD 发布流程:
    • tag 触发 job → composer validate → 生成 composer.lock → 推送到 GitLab Registry → 生成 GitLab Release。
  6. 版本约束与 GitLab 的兼容性:必须遵循 semver,且 tag 需带 v 前缀(v1.2.3),否则 GitLab 不会自动生成包记录。
  7. 缓存与加速:
    • 自建 Satis 或 Packagist China Mirror 做二级代理;
    • 在 Dockerfile 里预置 composer/cache 层,减少重复拉取;
    • 使用 GitLab 的 CDN 域名替代自建 MinIO,提高内网下载速度。
  8. 安全与合规:
    • 私有包禁止泄露到公网 Packagist;
    • 使用 composer audit 与 GitLab Dependency Scanning 做漏洞告警;
    • 对生产镜像做 composer install --no-dev --classmap-authoritative,缩小攻击面。

答案

“我们在集团内部 GitLab 14.x 上搭建了 group-level 的 Composer Registry,解决 200+ 私有包的分发问题。
第一步,在 GitLab 创建群组 common-lib,开启 ‘Packages & Registries → Composer Repository’。
第二步,给每个 PHP 组件仓库写好 composer.json,确保 name 字段统一前缀 common-lib/,并在 tag 推送时使用 semver 规范(v1.0.0)。
第三步,在本地或 CI 中生成 Personal Access Token,权限最小化只保留 read_api,然后写入全局 auth.json:
{ “http-basic”: { “gitlab.company.com”: { “username”: “gitlab-ci-token”, “password”: “{GITLAB_TOKEN}” } } } 第四步,在业务项目根目录 composer.json 里追加仓库地址: “repositories”: [ { “type”: “composer”, “url”: “https://gitlab.company.com/api/v4/group/common-lib/packages/composer” } ] 第五步,执行 composer require common-lib/logger,Composer 会自动拉取 GitLab 返回的 packages.json,再下载对应 zip 包;首次拉取后缓存在 ~/.composer/cache,后续安装耗时 <1s。 第六步,在组件库的 .gitlab-ci.yml 中定义发布阶段: release: stage: deploy only: - tags script: - composer config gitlab-token.CI_SERVER_HOST CIJOBTOKENcomposerinstallnodevoptimizeautoloadercomposerarchiveformat=zipfile=distcurlheader"JOBTOKEN:CI_JOB_TOKEN - composer install --no-dev --optimize-autoloader - composer archive --format=zip --file=dist - 'curl --header "JOB-TOKEN: CI_JOB_TOKEN" --upload-file dist.zip CIAPIV4URL/projects/{CI_API_V4_URL}/projects/{CI_PROJECT_ID}/packages/composer'
通过上述流程,我们把平均构建时长从 3 分钟降到 20 秒,私有包版本完全受控,且满足公司内网隔离与审计要求。”

拓展思考

  1. 多集群场景下,如何让华北、华南机房都能就近拉包?可在两地各部署一台只读 Satis, nightly 同步 GitLab Registry,实现“中心发布、边缘加速”。
  2. 当私有包依赖公网包时,如何防止同时命中 Packagist 与 GitLab 造成版本冲突?可在 composer.json 里禁用 packagist:
    “repositories”: [ {“type”: “composer”, “url”: “https://gitlab.company.com/api/v4/group/common-lib/packages/composer”}, {“packagist”: false} ]
    并搭建内部镜像站,把公网包缓存到 Nexus 或 Artifactory。
  3. 如果 GitLab 升级 15.x 后默认开启 JWT 认证,旧有 CI_JOB_TOKEN 长度变化,如何平滑迁移?提前在 CI 模板里检测版本号,动态写入不同的 auth.json 模板,避免同时修改 300+ 项目。