由于Docker Hub主动退出市场,导致国内不能方便的拉取docker镜像,故计划在内网使用Nexus Repository架设私有仓库,行pull through cache之职能,将下载的镜像/包缓存下来以便多次部署供内网的多设备使用,降低对国内高校镜像站的流量使用;同时考虑到PyPI也可能发起制裁导致不能使用,也计划建立PyPI的内网仓库。

目标

  • 架设Nexus Repository OSS
  • 通过高校镜像站提供的HTTP代理缓存Docker Hub
  • 同上,缓存PyPI仓库

Nexus Repository OSS部署

Nexus Repository对Java 8以上的支持并不是特别好,有挺多坑需要留意。根据官网文档部署的情况下还需要注意以下几点:

Java版本选择

目前个人建议使用Java 11,因为当前LTS版本中Java 8太老而Java 17暂不支持OrientDb。我懒得专门部署一个外部数据库所以选择了Java 11,需要进行的改动最小。

# 使用Java 11以上版本的报错
java.lang.IllegalStateException: The maximum Java version for OrientDb is Java 11. Please check current Java version meets this requirement.

JVM选项修改

根据文档,使用Java 9以上版本时需要注释和取消注释掉{NEXUS_HOME}\bin\nexus.vmoptions中的部分内容,理论上来说根据配置文件中的说明进行修改即可。但上述部分在随安装包附带的版本中存在缺失若干等号=和路径不正确的问题,即使按照配置文件中的说明也无法直接使用。修改后的JVM配置文件如下,主要是缺少等号导致选项不能正确解析,再次说明对Java 8以上版本何等不上心,几年前的问题在最新版本中仍未修正。

-Xms2703m
-Xmx2703m
-XX:MaxDirectMemorySize=2703m
-XX:+UnlockDiagnosticVMOptions
-XX:+LogVMOutput
-XX:LogFile=../sonatype-work/nexus3/log/jvm.log
-XX:-OmitStackTraceInFastThrow
-Djava.net.preferIPv4Stack=true
-Dkaraf.home=.
-Dkaraf.base=.
-Dkaraf.etc=etc/karaf
-Djava.util.logging.config.file=etc/karaf/java.util.logging.properties
-Dkaraf.data=../sonatype-work/nexus3
-Dkaraf.log=../sonatype-work/nexus3/log
-Djava.io.tmpdir=../sonatype-work/nexus3/tmp
-Dkaraf.startLocalConsole=false
-Djdk.tls.ephemeralDHKeySize=2048
#
# additional vmoptions needed for Java9+
#
--add-reads=java.xml=java.logging
--add-exports=java.base/org.apache.karaf.specs.locator=java.xml,ALL-UNNAMED
--patch-module=java.base=./lib/endorsed/org.apache.karaf.specs.locator-4.3.9.jar
--patch-module=java.xml=./lib/endorsed/org.apache.karaf.specs.java.xml-4.3.9.jar
--add-opens=java.base/java.security=ALL-UNNAMED
--add-opens=java.base/java.net=ALL-UNNAMED
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED
--add-opens=java.naming/javax.naming.spi=ALL-UNNAMED
--add-opens=java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED
--add-exports=java.base/sun.net.www.protocol.http=ALL-UNNAMED
--add-exports=java.base/sun.net.www.protocol.https=ALL-UNNAMED
--add-exports=java.base/sun.net.www.protocol.jar=ALL-UNNAMED
--add-exports=jdk.xml.dom/org.w3c.dom.html=ALL-UNNAMED
--add-exports=jdk.naming.rmi/com.sun.jndi.url.rmi=ALL-UNNAMED
--add-exports=java.security.sasl/com.sun.security.sasl=ALL-UNNAMED
#
# comment out this vmoption when using Java9+
#
# -Djava.endorsed.dirs=lib/endorsed

配置HTTP代理

部署完成后在System > HTTP > Proxy Settings中填写对应的代理即可,拉到最下方可以添加排除列表,不需要通过高校HTTP代理拉取的站点被排除后则会直连。

配置Docker Hub仓库

创建仓库

  • 新建仓库,选择类型为docker (proxy)
  • 填写仓库名称
  • HTTP选项下填写一个端口;由于Nexus Repo的某些限制,通过port connector连接是最简单的方法(参见官方论坛讨论这个issue)
  • 我勾选了Allow anonymous docker pull,看个人情况
  • Enable Docker V1 API我没勾选,考虑到V1 API已经deprecate了
  • Remote storage填写Docker Hub的registry:https://registry-1.docker.io
  • Docker Index勾选Use Docker Hub
  • 其它均默认,如果有Docker Hub账号的话可以将创建的Token填写到最下方Authentication里,避免匿名帐号每6小时拉取100镜像的限制

配置匿名访问

Security > Realms中将Docker Bearer Token Realm加入Active,参考这个问答

修改使用Docker的终端

在终端上添加/修改配置文件/etc/docker/daemon.json,添加Nexus Repo到非安全registry(因为我没有配置HTTPS)。

{
    "insecure-registries" : [ "mirrors.example.net:5000" ]
}

然后重启Docker服务,随后在用到Docker的地方(我的话主要用Portainer)配置新的registry为mirrors.example.net:5000即可。

配置PyPI仓库

创建仓库

  • 新建仓库,选择类型为pypi (proxy)
  • Remote storage填写https://pypi.org
  • 理论上其它留默认就行了

修改终端pip配置

从Nexus Repo复制出来的PyPI仓库URL可能形如http://mirrors.example.net:4000/repository/pypi/,在填写到pip.ini时注意稍作修改:

[global]
index-url = http://mirrors.example.net:4000/repository/pypi/simple
[install]
trusted-host = mirrors.example.net:4000

此时再通过pip安装包时便会通过Nexus Repo拉取,Nexus Repo也会缓存下这部分包。

缓存效果测试

在红色和绿色两个框内先后拉取了同一个镜像,可以看到第二次拉取时Nexus Repo并未再次下载镜像,而是使用本地缓存向Docker终端提供下载。

Nexus Repo