我写这篇文章的起因是 npm 安装软件包网速慢,如果使用淘宝的镜像源,一些非主流的包,更新不及时,还出现下载失败。如果使用官方源,网速就太慢了。

我将在这里分享自己的实践经验。

选型

verdaccio

因为考虑单纯为 npm 做本地镜像源,考虑使用 verdaccio,想做成一个后台运行的服务,可以开机自启动,就考虑到 PM2,但是有个问题,如果想 pm2 startup 生效,就必须以 root 用户运行这个命令。对系统侵入性太大了。

就考虑以 docker 的形式运行 verdaccio。

第一版 docker-compose.yml 文件:

version: '3.1'

services:
  verdaccio:
    image: verdaccio/verdaccio
    restart: always
    container_name: 'verdaccio'
    ports:
      - '4873:4873'
    volumes:
      - './storage:/verdaccio/storage'
      - './config:/verdaccio/conf'
      - './plugins:/verdaccio/plugins'

创建 config 文件夹,在里面创建 config.yaml 文件:

mkdir config
cd config
touch config.yaml

config.yaml 文件内容:

#
# This is the default config file. It allows all users to do anything,
# so don't use it on production systems.
#
# Look here for more config file examples:
# https://github.com/verdaccio/verdaccio/tree/master/conf
#

# path to a directory with all packages
storage: /verdaccio/storage
# path to a directory with plugins to include
plugins: /verdaccio/plugins
# print logs
# logs: ./logs

web:
  title: Verdaccio
  # comment out to disable gravatar support
  # gravatar: false
  # by default packages are ordercer ascendant (asc|desc)
  # sort_packages: asc
  # convert your UI to the dark side
  # darkMode: true
  #  HTML tags injected after manifest <scripts/>
  # scriptsBodyAfter:
  #    - '<script type="text/javascript" src="https://my.company.com/customJS.min.js"></script>'
  #  HTML tags injected before ends </head>
  #  metaScripts:
  #    - '<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>'
  #    - '<script type="text/javascript" src="https://browser.sentry-cdn.com/5.15.5/bundle.min.js"></script>'
  #    - '<meta name="robots" content="noindex" />'
  #  HTML tags injected first child at <body/>
  #  bodyBefore:
  #    - '<div id="myId">html before webpack scripts</div>'
  #  Public path for template manifest scripts (only manifest)
  #  publicPath: http://somedomain.org/
# translate your registry, api i18n not available yet
# i18n:
# list of the available translations https://github.com/verdaccio/ui/tree/master/i18n/translations
#   web: en-US

auth:
  htpasswd:
    file: ./htpasswd
    # Maximum amount of users allowed to register, defaults to "+inf".
    # You can set this to -1 to disable registration.
    # max_users: 1000

# a list of other known repositories we can talk to
uplinks:
  npmjs:
    url: https://registry.npmjs.org/
  taobao:
    url: https://registry.npmmirror.com/
  tencent:
    url: https://mirrors.cloud.tencent.com/npm/
packages:
  '@*/*':
    # scoped packages
    access: $all
    publish: $authenticated
    unpublish: $authenticated
    proxy: npmjs

  '**':
    # allow all users (including non-authenticated users) to read and
    # publish all packages
    #
    # you can specify usernames/groupnames (depending on your auth plugin)
    # and three keywords: "$all", "$anonymous", "$authenticated"
    access: $all

    # allow all known users to publish/publish packages
    # (anyone can register by default, remember?)
    publish: $authenticated
    unpublish: $authenticated

    # if package is not available locally, proxy requests to 'npmjs' registry
    proxy: npmjs

server:
  # deprecated
  keepAliveTimeout: 60
#  rateLimit:
#    windowMs: 1000
#    max: 10000

middlewares:
  audit:
    enabled: true
listen: 0.0.0.0:4873

# log settings
logs:
  # Logger as STDOUT
  { type: stdout, format: pretty, level: http }
  # Logger as STDOUT as JSON
  # { type: stdout, format: json, level: http }
  # Logger as STDOUT as JSON
  # { type: stdout, format: pretty-timestamped, level: http }
  # Logger as STDOUT as custom prettifier
  # { type: stdout, plugin: { dest: '@verdaccio/logger-prettify' : options: { foo: 1, bar: 2}}, level: http }
  # Logger as file
  # { type: file, path: verdaccio.log, level: http}
  # FIXME: this should be documented
  # More info about log rotation https://github.com/pinojs/pino/blob/master/docs/help.md#log-rotation

# This affect the web and api (not developed yet)
i18n:
  web: en-US

意外

启动容器

docker-compose up 

报错 permission denied, mkdir

具体见这里

第二版

version: '3.1'

services:
  verdaccio:
    image: verdaccio/verdaccio
    restart: always
    user: 1000:1000
    container_name: 'verdaccio'
    ports:
      - '4873:4873'
    volumes:
      - './storage:/verdaccio/storage'
      - './config:/verdaccio/conf'
      - './plugins:/verdaccio/plugins'

通过修改文件夹的所有者

id 
uid=1000(luo) gid=1000(luo) 组=1000(luo),4(adm),24(cdrom),27(sudo)

sudo  chown -R  1000:100  storage/  config/  plugins/

就解决问题了,user 的设置要你自己 Linux 服务器上一致,通过 id 命令获得,格式为 user: uid: gid

启动

docker-compose up -d 

在网页浏览器里输入 http://ip:4873,然后再终端输入,进行设置,使用本地的软件源

npm set registry http://ip:4873/

----_20230323213523

Nexus 3

选一个通用型软件镜像服务(Nexus 3),大部分的开发语言都支持,一次投入,多次收益,如图:

nexus3

docker-compose.yml 文件

version: "3.6"

services:
  nexus:
    image: sonatype/nexus3:3.49.0
    restart: always
    environment:
      - INSTALL4J_ADD_VM_PARAMS=-Xms2g -Xmx2g -XX:MaxDirectMemorySize=2g -Djava.util.prefs.userRoot=/nexus-data/javaprefs -Duser.time    volumes:
      - ./nexus-data:/nexus-data
    ports:
      - "8081:8081"

Java 应用要限制一下内存,避免把宿主机的内存全吃掉,可根据实际情况调整。

启动

docker-compose up -d 

还是遇到权限问题

mkdir: cannot create directory '../sonatype-work/nexus3/log': Permission denied

mkdir: cannot create directory '../sonatype-work/nexus3/tmp': Permission denied

解决办法:参考资料

sudo chown -R 200 ~/dockerVolume/nexus

重新启动

docker-compose up -d

获得 admin 的登录密码


# 在启动应用的目录中执行

cat nexus-data/admin.password

# 或者直接使用 Docker CLI 执行容器命令
docker exec -it nexus.lab.io cat /nexus-data/admin.password

通过网页浏览器输入 http://ip:8081 访问管理后台。在输入了正确的初始账号和密码后,新版软件会人性化的引导我们设置新密码,以及设置是否允许匿名用户使用。

如果是个人使用,或者团队在内网使用,可以勾选“允许匿名访问”。

然后建个 npm(hosted) 和 npm(proxy),组成一个 npm(grounp),
具体教程可以看 这个,但不要像它里面开放多个端口,没必要。

设置 npm 使用本地软件源(根据你的服务器的实际 IP 或者域名进行修改)

npm set registry  http://192.168.2.114:8081/repository/npm-group/

总结

docker 存储方面的权限设置是个问题,解决办法:

  1. 自己构建 docker 镜像,从根源上解决问题,这难度比较大,要自己不断学习尝试。
  2. 多查找网络资料,通过设置解决。

docker 部署方便,避免对系统的入侵,具有良好的隔离性,并且多平台支持,但是在权限安全方面还有很多要注意的。

如果你对这篇文章有任何疑问,或者如果你想和我探讨更多技术内容,欢迎和我联系。我的邮箱是:luojiyin@hotmail.com。