Aldebaran

人生最棒的感觉,就是你做到别人说你做不到的事。

0%

生产环境下使用cnpm搭建私有npm服务

指原莉乃

为什么需要私有npm

官方的 npm 可以说是最大的 JavaScript 模块仓库,大约有 60 多万个开源的 JavaScript 模块。那为什么我们还需要一个私有 npm 仓库呢?

总结起来,有以下几点原因:

保证 npm 服务的快速、稳定。由于国内网络环境的原因,从官方 npm 上安装模块依赖时,可能需要花费很长的时间。在部署私有 npm 后,可以把经过审核的 npm 模块加入到私有仓库,这样在开发环境和生产环境中就可以对模块进行快速安装了。另外还能避免类似 left-pad 事件的发生1。
发布私有 npm 模块。官方 npm 上的模块全部是开源的,然而在实际开发过程中,我们需

方案

最终选择的是cnpmjs,因为sinopia虽然有web权限控制,但是其项目本身截至(2018-7-16 18:2:29)有三年未有更新;verdaccio是sinopia的fork.

cnpm简介

CNPM 是一个Nodejs的库,致力于打造私有的 NPM 注册服务。当然,除了私有库功能以外,CNPM官网 (http://cnpmjs.org/) 还提供了NPM同步的服务。

CNPM官方发布的架构图:

00

从CNPM的架构图中,我们可以看出CNPM是对NPM做的镜像服务,CNPM会定期同步NPM的资源库,同时CNPM支持发布私有的库,这样就非常方便地集成了公有库和私有库,对于公司内部的开发者来说,基本感觉不到两种库的区别。

另外,我们使用NPM下载依赖包时,经常性地会遇到一些包下载失败的情况,主要原因了NPM的注册服务器在国外,国内的网络环境访问国外的IP并不是太好。所以,直接配置到国内的NPM镜像,可以减少NPM下载出错机会。

安装

  • 最低要求

    • NodeJS >= 4.3.1
    • Databases: only required one type
      • sqlite3 >= 3.0.2, we use sqlite3 by default
      • MySQL >= 0.5.0, include mysqld and mysql cli. I test on mysql@5.6 and 5.7
      • MariaDB
      • PostgreSQL
    • Python 2.7
    • 磁盘尽量大
  • MySQL

      ## 这里没有优化参数,大并发的需求,因此不选择用编译安装
      ## 以ubuntu为例
      $ cd /usr/local/src
      $ wget https://repo.mysql.com//mysql-apt-config_0.8.10-1_all.deb
      $ apt-get update
      $ apt-get install mysql-server
    
  • NodeJS

      $ cd /usr/local/src
      $ wget https://nodejs.org/dist/v8.11.3/node-v8.11.3-linux-x64.tar.xz
      $ tar xf node-v8.11.3-linux-x64.tar.xz
      $ mv node-v8.11.3-linux-x64 /usr/local
      $ ln -s /usr/local/node-v8.11.3-linux-x64 /usr/local/node
      $ ln -s /usr/local/node/bin/npm /usr/local/bin/npm
      $ ln -s /usr/local/node/bin/node /usr/local/bin/node
      $ ln -s /usr/local/node/bin/npx /usr/local/bin/npx
    
  • 代码拉取

      $ apt-get install python sqlite3
    
      $ mkdir -p /data/wwwroot && cd /data/wwwroot
      $ git clone https://github.com/cnpm/cnpmjs.org.git
      $ cd cnpmjs.org
      ## 最新的(2018-7-16 17:54:37)3.x不稳定,建议暂时用2.x
      $ git checkout remotes/origin/2.x
      $ git branch
    
      $ sudo npm install
      ## 可选: 国内下载如果过慢,开源指定源下载
      $ sudo npm install --registry=https://registry.npm.taobao.org
      ## 可选: 如果用root用户直接运行npm install,那么需要加入--unsafe-perm参数)
      $ npm install --registry=https://registry.npm.taobao.org --unsafe-perm
    

    01

  • MySQL创建数据库和数据库权限

      ## 新建数据库名
      mysql> CREATE DATABASE IF NOT EXISTS cnpmjs_dev DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
    
      ## 新建用户
      mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, CREATE VIEW, SHOW VIEW ON cnpmjs_dev.* TO 'cnpmjs_root'@'192.168.%.%' IDENTIFIED BY 'conDH55ds9n1p11DH55d';
      mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, CREATE VIEW, SHOW VIEW ON cnpmjs_dev.* TO 'cnpmjs_root'@'localhost' IDENTIFIED BY 'conDH55ds9n1p11DH55d';
      mysql> flush privileges;
    
      ## 导入建表文件
      mysql> source /data/wwwroot/cnpmjs.org/docs/db.sql;
    
  • 当前使用的配置文件(有删改)

      ...
      var dataDir = path.join('/data/download/.cnpmjs.org');
      ...
        registryPort: 7001,
        webPort: 7002,
        bindingHost:'192.168.99.131', // only binding on 127.0.0.1 for local access
      ...
        // enable gzip response or not
        // enableCompress:是否开启gzip压缩支持,推荐为true
        enableCompress: true,
    
        // default system admins
        admins: {
          // name: email
          ccqq: '1314@qq.com',
          fengmk2: 'fengmk2@gmail.com',
          admin: 'admin@cnpmjs.org',
          dead_horse: 'dead_horse@qq.com',
        },
      ...
        database: {
          db: 'cnpmjs_dev',
          username: 'cnpmjs_root',
          password: 'conDH55ds9n1p11DH55d',
    
          // the sql dialect of the database
          // - currently supported: 'mysql', 'sqlite', 'postgres', 'mariadb'
          dialect: 'mysql',
    
          // custom host; default: 127.0.0.1
          host: '127.0.0.1',
    
          // custom port; default: 3306
          port: 3306,
    
          sessionSecret: '37376.com cnpmjs.org session secret',
      ...
        // enable private mode or not
        // private mode: only admins can publish, other users just can sync package from source npm
        // public mode: all users can publish
        // “none”:永不同步,只管理私有用户上传的包,其他源包会直接从源站获取;
        // “exist”:定时同步已经存在于数据库的包;
        // “all”:定时同步所有源站的包;
        enablePrivate: true,
    
        // registry scopes, if don't set, means do not support scopes
        //也就是在 install 的时候遇到含有 scope 的包就会去私有npm下载包 如:@cnpm/demo ,公共的 npm 会去 sourceNpmRegistry: 'https://registry.npm.taobao.org', 下载包 。
        // scopes: [ '@cnpm', '@cnpmtest', '@cnpm-test' ],
        scopes: [ '@cnpm', '@cnpmtest', '@cnpm-test', '@37376test', '@37376demo', '@37376' ],
      ...
        // upstream registry is base on cnpm/cnpmjs.org or not
        // if your upstream is official npm registry, please turn it off
        sourceNpmRegistryIsCNpm: true,
    
        // if install return 404, try to sync from source registry
        syncByInstall: true,
    
        // sync mode select
        // none: do not sync any module, proxy all public modules from sourceNpmRegistry
        // exist: only sync exist modules
        // all: sync all modules
        syncModel: 'exist', // 'none', 'all', 'exist'
      ...
        // sync devDependencies or not, default is false
        syncDevDependencies: true,
        // try to remove all deleted versions from original registry
        syncDeletedVersions: true,
      ...
      };
    
  • 启动

    $ node start
    
    or
    
    $ nohup node /data/wwwroot/cnpmjs.org/dispatch.js > /data/download/.cnpmjs.org/logs/nodejs_stdout.log 2>&1 &
    

使用cnpm

下载

如果私有库没有对应的库,cnpm会自动同步到NPM 找到我们要下载的库和版本,先在CNPM中存一份,然后再传给客户端一份,运行原理和Maven的原理一样。

$ npm install request --registry=http://192.168.99.131:7001

上传

默认cnpm只有admin组才有权限上传。

# make sure you have login cnpm
$ cnpm publish