動手搭建一個私有倉儲

艾倫先生發表於2017-12-14

痛點

  • 有時候執行npm install命令安裝某些模組的時候,特別慢,經常安裝失敗
  • 公司內部的模組如何維護?

我們需要一個能夠讓公司內部模組穩定維護的私有倉儲,而且這個倉儲還能夠穩定的提供通過npm install獲取的安裝包,那麼cnpm來了~

CNPM是什麼

CNPM是一個私有的Nodejs庫,使用CNPM 有如下理由:

  • 確保npm服務快速、穩定:對於企業來說,上線生產系統的時候,需要花半小時甚至更久等待npm模組依賴安裝完畢,是不可接受的。部署映象後,可以確保高速、穩定的npm服務。

  • 釋出私有模組:官方的npm上的模組全部是開源的。一些與企業業務邏輯相關的模組可能不適合開源。這部分私有的模組放在私有NPM倉庫中,使用起來各種方便。

  • 控制npm模組質量和安全:npm上的模組質量參差不齊,搭建私有倉庫,可以更嚴格地控制模組的質量和安全,只有經過稽核的模組才允許被加入私有倉庫。

  • 使用MySQL替換了CouchDB,更容易部署。同時由於大部分開發者更熟悉MySQL,因此架設起來更方便。

  • 部署簡單:只需要五分鐘

動手搭建一個私有倉儲

從CNPM的架構圖中,我們可以看出CNPM是對NPM做的映象服務,CNPM會定期同步NPM的資源庫,同時CNPM支援釋出私有的庫,這樣就非常方便地整合了公有庫和私有庫,對於公司內部的開發者來說,基本感覺不到兩種庫的區別。

搭建CNPM服務

從官方文件中,我們看到CNPM伺服器環境,只需要Node(0.11.12) + MySQL(>= 0.5.0),另外我們還需要Linux的環境,接下來就讓我們動手自己搭建一個私有NPM的伺服器

  • 準備:

      Linux 作業系統,如 Ubuntu 12.04.5 LTS
      Node: v6.0.0
      Npm: 3.8.6
      資料庫 ,如 MySQL: 5.5.40
      Git客戶端
    複製程式碼
  • 從github下載專案原始碼,安裝專案依賴

      git clone https://github.com/cnpm/cnpmjs.org.git
      cd cnpmjs.org
      npm install
    複製程式碼
  • 在config目錄下新建一個config.js 檔案,可以參考官方推薦的一些配置

    下面列出一些常用的配置說明

    • enableCluster:是否啟用 cluster-worker 模式啟動服務,預設 false,生產環節推薦為 true;
    • registryPort:API 專用的 registry 服務埠,預設 7001;
    • webPort:Web 服務埠,預設 7002;
    • bindingHost:監聽繫結的 Host,預設為 127.0.0.1,如果外面架了一層本地的 Nginx 反向代理或者 Apache 反向代理的話推薦不用改;
    • sessionSecret:session 用的鹽;
    • logdir:日誌目錄;
    • uploadDir:臨時上傳檔案目錄;
    • viewCache:檢視模板快取是否開啟,預設為 false;
    • enableCompress:是否開啟 gzip 壓縮,預設為 false;
    • admins:管理員們,這是一個 JSON Object,對應各鍵名為各管理員的使用者名稱,鍵值為其郵箱,預設為 { fengmk2: 'fengmk2@gmail.com', admin: 'admin@cnpmjs.org', dead_horse: 'dead_horse@qq.com' };
    • logoURL:Logo 地址,不過對於我這個已經把 CNPM 前端改得面目全非的人來說已經忽略了這個配置了;
    • adBanner:廣告 Banner 的地址;
    • customReadmeFile:實際上我們看到的 cnpmjs.org 首頁中間一大堆冗長的介紹是一個 Markdown 檔案轉化而成的,你可以設定該項來自行替換這個檔案;
    • customFooter:自定義頁尾模板;
    • npmClientName:預設為 cnpm,如果你有自己開發或者 fork 的 npm 客戶端的話請改成自己的 CLI 命令,這個應該會在一些頁面的說明處替換成你所寫的;
    • backupFilePrefix:備份目錄;
    • database:資料庫相關配置,為一個物件,預設如果不配置將會是一個 ~/.cnpmjs.org/data.sqlite 的 SQLite;
    • db:資料的庫名;
    • username:資料庫使用者名稱;
    • password:資料庫密碼;
    • dialect:資料庫介面卡,可選 "mysql"、"sqlite"、"postgres"、"mariadb",預設為 "sqlite";
    • hsot:資料庫地址;
    • port:資料庫埠;
    • pool:資料庫連線池相關配置,為一個物件;
    • maxConnections:最大連線數,預設為 10;
    • minConnections:最小連線數,預設為 0;
    • maxIdleTime:單條連結最大空閒時間,預設為 30000 毫秒;
    • storege:僅對 SQLite 配置有效,資料庫地址,預設為 ~/.cnpmjs/data.sqlite;
    • nfs:包檔案系統處理物件,為一個 Node.js 物件,預設是 fs-cnpm 這個包,並且配置在 ~/.cnpmjs/nfs 目錄下,也就是說預設所有同步的包都會被放在這個目錄下;開發者可以使用別的一些檔案系統外掛(如上傳到又拍雲等),又或者自己去按介面開發一個邏輯層,這些都是後話了;
    • registryHost:暫時還未試過,我猜是用於 Web 頁面顯示用的,預設為 r.cnpmjs.org;
    • enablePrivate:是否開啟私有模式,預設為 false; 如果是私有模式則只有管理員能釋出包,其它人只能從源站同步包; 如果是非私有模式則所有登入使用者都能釋出包;
    • scopes:非管理員釋出包的時候只能用以 scopes 裡面列舉的名稱空間為字首來發布,如果沒設定則無法釋出,也就是說這是一個必填項,預設為 [ '@cnpm', '@cnpmtest', '@cnpm-test' ],據蘇千大大解釋是為了便於管理以及讓公司的員工自覺按需釋出;更多關於 NPM scope 的說明請參見 npm-scope;
    • privatePackages:就如該配置項的註釋所述,出於歷史包袱的原因,有些已經存在的私有包(可能之前是用 Git 的方式安裝的)並沒有以名稱空間的形式來命名,而這種包本來是無法上傳到 CNPM 的,這個配置項陣列就是用來加這些例外白名單的,預設為一個空陣列;
    • sourceNpmRegistry:更新源 NPM 的 registry 地址,預設為 https://registry.npm.taobao.org;
    • sourceNpmRegistryIsCNpm:源 registry 是否為 CNPM,預設為 true,如果你使用的源是官方 NPM 源,請將其設為 false;
    • syncByInstall:如果安裝包的時候發現包不存在,則嘗試從更新源同步,預設為 true;
    • syncModel:更新模式(不過我覺得是個 typo),有下面幾種模式可以選擇,預設為 "none";
      • "none":永不同步,只管理私有使用者上傳的包,其它源包會直接從源站獲取;
      • "exist":定時同步已經存在於資料庫的包;
      • "all":定時同步所有源站的包;
    • syncInterval:同步間隔,預設為 "10m" 即十分鐘;
    • syncDevDependencies:是否同步每個包裡面的 devDependencies 包們,預設為 false;
    • badgeSubject:包的 badge 顯示的名字,預設為 cnpm;
    • userService:使用者驗證介面,預設為 null,即無使用者相關功能也就是無法有使用者去上傳包,該部分需要自己實現介面功能並配置,如與公司的 Gitlab 相對接,這也是後話了;
    • alwaysAuth:是否始終需要使用者驗證,即便是 $ cnpm install 等命令;
    • httpProxy:代理地址設定,用於你在牆內源站在牆外的情況。

    閱讀了上面的配置,你可能會編寫一份如下的配置檔案

      module.exports = {
          debug: false,
          enableCluster: true, // enable cluster mode
          mysqlServers: [
            {
              host: 'localhost',
              port: 3306,
              user: 'root',
              password: 'xxxxxx',
            }
          ],
          mysqlDatabase: 'cnpmjs',
          enablePrivate: true, // enable private mode, only admin can publish, other use just can sync package from source npm
          admins: {
            admin: 'example@example.com',
          },
          scopes:['@IModules'],
          syncModel: 'exist'// 'none', 'all', 'exist'
      };
    複製程式碼
  • 建立並初始化MySQL資料庫

      $ mysql -u yourname -p
      mysql> use cnpmjs;
      mysql> source docs/db.sql
    複製程式碼
  • 啟動CNPM伺服器,預設會開啟兩個埠,7001用於NPM的註冊服務,7002用於Web訪問。

      node --harmony_generators dispatch.js
    複製程式碼

    或者 npm run start npm run dev:除錯模式啟動; npm run test:跑測試; npm run start:啟動 CNPM; npm run status:檢視 CNPM 啟動狀態; npm run stop:停止 CNPM。

  • 瀏覽器訪問CNPM私有倉庫

      127.0.0.1:7002
    複製程式碼

動手搭建一個私有倉儲

終於正常了,這樣就成功搭建了私有的NPM註冊服務。

配置npm源為公司內部倉庫

  • 配置npm 源為公司私有倉庫

      npm config set registry http://cnpm.xxx.cn/ #這個是將上文IP對映的域名
    複製程式碼
  • 檢視是否操作成功

      npm config ls
    複製程式碼

動手搭建一個私有倉儲

執行命令,來安裝一個私有庫(後面的文章會建立)

npm install --save @IModules/IUtils@0.2.0-snapshot
複製程式碼

載的時候指定我們自己的私有庫,這樣就會從我們自己的私有庫中下載。如果私有庫沒有對應的庫,CNPM會自動同步到NPM 找到我們要下載的庫和版本,先在CNPM中存一份,然後再傳給客戶端一份,執行原理和Maven的原理一樣。 或者使用如下命令,臨時安裝 npm install winston --registry=http://127.0.0.1:7002

工具庫

私有倉儲建立起來了,後面就開始動手建立上文中提到的IUtils庫併發布到私有倉儲

這裡我提供一份支援釋出的私有庫檔案,具體的請參考這裡

相關文章