跳到主要内容

私有包管理

在企业级开发中,通常需要管理内部私有包。这些包可能包含专有代码、内部工具或敏感配置,不适合发布到公共仓库。本节介绍如何搭建和使用私有 npm 仓库。

为什么需要私有仓库?

安全性

内部代码可能包含敏感信息,如 API 密钥、加密算法、业务逻辑等,不能暴露到公共仓库。

效率

私有仓库可以作为公共仓库的缓存代理,加速依赖下载,减少网络延迟。

稳定性

不依赖外部网络,即使公共仓库不可用,内部开发也能正常进行。

控制力

可以控制哪些包可以使用,阻止有安全漏洞的包进入项目。

私有仓库方案

1. npm 官方私有包

npm 官方提供私有包服务,适合小型团队。

特点

  • 无需搭建服务器
  • 与 npm 生态无缝集成
  • 支持团队协作

限制

  • 需要付费订阅
  • 私有包数量有限制

使用方式

# 创建 scoped 包
npm init --scope=@mycompany

# 发布私有包
npm publish --access restricted

# 发布公开 scoped 包
npm publish --access public

2. Verdaccio

Verdaccio 是一个轻量级的私有 npm 代理仓库,开源免费。

特点

  • 零配置启动
  • 支持代理公共仓库
  • 内置 Web 界面
  • 支持认证和权限管理
  • Docker 部署简单

安装和启动

# 全局安装
npm install -g verdaccio

# 启动服务
verdaccio

# 默认运行在 http://localhost:4873

配置文件

配置文件位于 ~/.config/verdaccio/config.yaml

# 存储路径
storage: ./storage

# 插件路径
plugins: ./plugins

# 认证配置
auth:
htpasswd:
file: ./htpasswd
max_users: 100

# 上游仓库配置
uplinks:
npmjs:
url: https://registry.npmjs.org/
taobao:
url: https://registry.npmmirror.com

# 包访问规则
packages:
# 私有包
'@mycompany/*':
access: $authenticated
publish: $authenticated
unpublish: $authenticated
proxy: npmjs

# 公共包代理
'**':
access: $all
publish: $authenticated
unpublish: $authenticated
proxy: npmjs taobao

# 日志配置
logs:
- { type: stdout, format: pretty, level: warn }

# 监听地址
listen: 0.0.0.0:4873

用户管理

# 添加用户
npm adduser --registry http://localhost:4873

# 登录
npm login --registry http://localhost:4873

Docker 部署

# 拉取镜像
docker pull verdaccio/verdaccio

# 运行容器
docker run -it --rm --name verdaccio \
-p 4873:4873 \
-v ~/verdaccio/storage:/verdaccio/storage \
-v ~/verdaccio/config:/verdaccio/conf \
verdaccio/verdaccio

# 使用 docker-compose
# docker-compose.yml
version: '3'
services:
verdaccio:
image: verdaccio/verdaccio
ports:
- "4873:4873"
volumes:
- ./storage:/verdaccio/storage
- ./config:/verdaccio/conf

3. Nexus Repository

Sonatype Nexus 是企业级的仓库管理器,支持多种包格式。

特点

  • 支持 npm、Maven、Docker、PyPI 等多种格式
  • 企业级安全和权限管理
  • 高可用和集群支持
  • 详细的审计日志

Docker 部署

# 运行 Nexus
docker run -d --name nexus \
-p 8081:8081 \
-v nexus-data:/nexus-data \
sonatype/nexus3

# 访问 http://localhost:8081
# 默认用户: admin
# 默认密码: admin123 或查看 /nexus-data/admin.password

创建 npm 仓库

  1. 登录 Nexus Web 界面
  2. 进入 Repository → Repositories
  3. 创建 npm 仓库:
    • npm (proxy):代理公共仓库
    • npm (hosted):托管私有包
    • npm (group):组合多个仓库

配置 npm 使用 Nexus

# 设置镜像源
npm config set registry http://localhost:8081/repository/npm-group/

# 或在 .npmrc 中配置
registry=http://localhost:8081/repository/npm-group/

4. JFrog Artifactory

JFrog Artifactory 是另一个企业级仓库管理器。

特点

  • 支持所有主流包格式
  • 高级缓存和复制功能
  • 与 CI/CD 工具集成
  • 企业级安全功能

Docker 部署

# 运行 Artifactory
docker run -d --name artifactory \
-p 8081:8081 -p 8082:8082 \
-v artifactory-data:/var/opt/jfrog/artifactory \
releases-docker.jfrog.io/jfrog/artifactory-oss:latest

# 访问 http://localhost:8082

5. GitHub Packages

GitHub 提供内置的包注册表服务。

特点

  • 与 GitHub 仓库集成
  • 支持多种包格式
  • 使用 GitHub Token 认证
  • 免费额度充足

配置使用

# 创建 .npmrc 文件
@mycompany:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}

# 或使用 npm config
npm config set @mycompany:registry https://npm.pkg.github.com
npm config set //npm.pkg.github.com/:_authToken ${GITHUB_TOKEN}

发布包

{
"name": "@mycompany/my-package",
"publishConfig": {
"registry": "https://npm.pkg.github.com"
}
}
npm publish

6. GitLab Package Registry

GitLab 也提供内置的包注册表。

配置使用

# .npmrc
@mycompany:registry=https://gitlab.com/api/v4/projects/<project_id>/packages/npm/
//gitlab.com/api/v4/projects/<project_id>/packages/npm/:_authToken=${GITLAB_TOKEN}

配置私有仓库

项目级配置

在项目根目录创建 .npmrc 文件:

# 默认镜像源
registry=https://registry.npmmirror.com

# 私有包使用私有仓库
@mycompany:registry=https://npm.mycompany.com

# 认证令牌
//npm.mycompany.com/:_authToken=${NPM_TOKEN}

# 另一个 scope
@internal:registry=https://npm.mycompany.com

用户级配置

在用户目录创建 .npmrc 文件:

# ~/.npmrc

# 私有仓库认证
//npm.mycompany.com/:_authToken=npm_xxxx

# GitHub Packages
//npm.pkg.github.com/:_authToken=ghp_xxxx

使用环境变量

避免在配置文件中硬编码敏感信息:

# .npmrc
//npm.mycompany.com/:_authToken=${NPM_TOKEN}
# 设置环境变量
export NPM_TOKEN=npm_xxxx

# 或在 CI/CD 中设置
# GitHub Actions
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

# GitLab CI
variables:
NPM_TOKEN: $CI_JOB_TOKEN

多仓库配置

当需要同时使用多个私有仓库时:

# .npmrc
registry=https://registry.npmjs.org

@company-a:registry=https://npm.company-a.com
//npm.company-a.com/:_authToken=${NPM_TOKEN_A}

@company-b:registry=https://npm.company-b.com
//npm.company-b.com/:_authToken=${NPM_TOKEN_B}

发布私有包

创建私有包

{
"name": "@mycompany/utils",
"version": "1.0.0",
"private": false,
"publishConfig": {
"registry": "https://npm.mycompany.com",
"access": "restricted"
}
}

发布流程

# 登录私有仓库
npm login --registry=https://npm.mycompany.com

# 发布前检查
npm pack --dry-run

# 发布
npm publish

# 发布到指定仓库
npm publish --registry=https://npm.mycompany.com

使用 CI/CD 发布

GitHub Actions 示例

name: Publish Package

on:
release:
types: [created]

jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://npm.mycompany.com'
scope: '@mycompany'

- run: npm ci
- run: npm run build
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

GitLab CI 示例

publish:
stage: deploy
script:
- npm config set @mycompany:registry https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/
- npm config set //gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken ${CI_JOB_TOKEN}
- npm publish
only:
- tags

安全最佳实践

1. 使用令牌认证

避免使用用户名密码,使用令牌更安全:

# 创建令牌
npm token create --registry=https://npm.mycompany.com

# 查看令牌
npm token list --registry=https://npm.mycompany.com

# 撤销令牌
npm token revoke <token-id> --registry=https://npm.mycompany.com

2. 限制令牌权限

创建只读令牌用于 CI/CD:

npm token create --read-only --registry=https://npm.mycompany.com

3. 使用 .npmignore

排除敏感文件:

# .npmignore
.env
.env.local
*.key
*.pem
secrets/
credentials/

4. 审计依赖

定期检查私有包的安全问题:

npm audit --registry=https://npm.mycompany.com

5. 启用双因素认证

npm profile enable-2fa auth-and-writes --registry=https://npm.mycompany.com

常见问题

1. 认证失败

# 检查认证配置
npm config list

# 重新登录
npm logout --registry=https://npm.mycompany.com
npm login --registry=https://npm.mycompany.com

2. 包找不到

# 检查 scope 配置
npm config get @mycompany:registry

# 检查包是否存在
npm view @mycompany/my-package --registry=https://npm.mycompany.com

3. 发布失败

# 检查权限
npm access list packages @mycompany --registry=https://npm.mycompany.com

# 检查包名是否已存在
npm view @mycompany/my-package --registry=https://npm.mycompany.com

4. 网络问题

# 使用代理
npm config set proxy http://proxy.company.com:8080
npm config set https-proxy http://proxy.company.com:8080

# 或在 .npmrc 中配置
proxy=http://proxy.company.com:8080
https-proxy=http://proxy.company.com:8080
noproxy=localhost,127.0.0.1,npm.mycompany.com

私有仓库对比

方案适用场景优点缺点
npm 官方小型团队无需维护付费
Verdaccio中小型团队轻量、开源功能有限
Nexus企业级功能全面配置复杂
Artifactory企业级高级功能商业许可
GitHub PackagesGitHub 用户集成方便绑定 GitHub
GitLab RegistryGitLab 用户集成方便绑定 GitLab

了解更多