• 内网离线安装docker并配置使用nexus为docker私服


    背景#

    本文简单记录下最近在内网服务器离线安装docker及配置nexus作为docker私服,踩的一些坑。docker和k8s这块技术我跟得不是很紧,18年的时候用过一阵docker,后来发现它并不能解决当时我们遇到的问题,后来就没用了,再一个就是,在宿主机上啥命令都有,也太爽了,反观docker里面啥命令都没有,痛苦,所以没啥必要的话,我一般比较少docker部署。

    现在docker,k8s这块已经是事实上标准了,我们工作里也在筹备上云的事情,这块技术也得跟上了。最近工作正好需要选型一个内网搭建的文档中心,知识库那种,可以拿来存各种markdown的文档,看了下网上,各种技术太多了,这次干脆就用docker部署,快速试错。

    只是,刚在内网搭个docker,都一堆问题。

    网络环境#

    开发环境的服务器,全都没有外网,除非提申请给网工,比如,nexus maven私服服务器(ip:1.1.1.1),要访问阿里的maven私服(maven.aliyun.com),那么,提申请就是1.1.1.1访问maven.aliyun.com的80/443端口。

    另外,开发环境服务器也是访问不了办公电脑的网段的。

    这些网络管控其实也很正常,只是搞工作有点麻烦。

    安装过程#

    yum#

    先是在开发服务器A上准备安装docker,但也没办法使用yum安装,需要配置docker官方的yum源:

    Copy
    https://docs.docker.com/engine/install/centos/ sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo [docker-ce-stable] name=Docker CE Stable - $basearch baseurl=https://download.docker.com/linux/centos/$releasever/$basearch/stable enabled=1

    然后里面都是去https://download.docker.com下载,我又没网络,内网yum源的docker版本又比较旧,看来只能rpm安装了。

    rpm安装#

    然后我就去找rpm,在下面这个网址,下了6,7个rpm:

    https://download.docker.com/linux/centos/7/x86_64/stable/Packages/

    然后安装:

    Copy
    [root@monitor upload]# rpm -ivh *.rpm warning: docker-ce-24.0.6-1.el7.x86_64.rpm: Header V4 RSA/SHA512 Signature, key ID 621e9f35: NOKEY error: Failed dependencies: container-selinux >= 2:2.74 is needed by docker-ce-3:24.0.6-1.el7.x86_64 containerd.io >= 1.6.4 is needed by docker-ce-3:24.0.6-1.el7.x86_64 docker-ce-rootless-extras is needed by docker-ce-3:24.0.6-1.el7.x86_64 libcgroup is needed by docker-ce-3:24.0.6-1.el7.x86_64 libseccomp >= 2.3 is needed by docker-ce-3:24.0.6-1.el7.x86_64 docker-buildx-plugin is needed by docker-ce-cli-1:24.0.6-1.el7.x86_64 docker-compose-plugin is needed by docker-ce-cli-1:24.0.6-1.el7.x86_64

    我服了,怎么还依赖这么多rpm,这些rpm,在上面网址里还没有,看来这条路太累了,换个方式。

    找一台能任意上外网的机器(比如本地虚拟机、个人的云服务器等),用yum的方式,把所有rpm包都拿到手,再拷贝到这边来装。

    云服务器获取全部rpm#

    yum remove方式卸载失败#

    我是采用如下方式(--downloadonly),以获取tcpdump的rpm为例:

    Copy
    yum install --downloadonly --downloaddir=/root/download tcpdump 执行完成后,就在/root/download拿到了tcpdump的依赖包: [root@strategy-stg-app-2 download]# ll total 564 -rw-r--r-- 1 root root 141376 Jun 21 15:45 libpcap-1.5.3-11.el7.x86_64.rpm -rw-r--r-- 1 root root 431300 Jun 21 15:45 tcpdump-4.9.2-3.el7.x86_64.rpm

    行吧,我就把docker那几个包给卸载了,然后继续用上面的方式:

    Copy
    yum remove docker-ce docker-ce-cli ... 然后再安装: yum install --downloadonly --downloaddir=/root/mypackage/ docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

    执行完了去看,发现下载目录下也只有docker相关的几个包,docker依赖的包的rpm是一个没有。

    看来,是我卸载的时候,卸的不干净,没把docker那些依赖给卸载掉。

    yum history方式完全卸载#

    yum history这个命令,可以将你过往的yum历史操作记录找出来:

    image-20230929143400215

    我这边不知道为啥,只找到两年前的,我查了网上,好像说默认只能看到最近的20个历史事务。

    https://users.fedoraproject.narkive.com/bkvqvTY0/how-to-make-yum-history-show-more-than-the-last-20-transactions

    当然了,我们还可以查询某个包相关的事务:

    Copy
    [root@VM-0-6-centos ~]# yum history info docker-ce Transaction ID : 46 Begin time : Mon Nov 23 10:01:31 2020 End time : 10:01:56 2020 (25 seconds) User : root <root> Return-Code : Success Command Line : install -y docker-ce-19.03.9-3.el7 docker-ce-cli-19.03.9-3.el7 containerd.io Transaction performed with: Installed rpm-4.11.3-43.el7.x86_64 @os Installed yum-3.4.3-167.el7.centos.noarch @os Installed yum-plugin-fastestmirror-1.1.31-54.el7_8.noarch @updates Packages Altered: Dep-Install audit-libs-python-2.8.5-4.el7.x86_64 @os Dep-Install checkpolicy-2.5-8.el7.x86_64 @os Dep-Install container-selinux-2:2.119.2-1.911c772.el7_8.noarch @extras Install containerd.io-1.3.7-3.1.el7.x86_64 @docker-ce-stable Install docker-ce-3:19.03.9-3.el7.x86_64 @docker-ce-stable Install docker-ce-cli-1:19.03.9-3.el7.x86_64 @docker-ce-stable Dep-Install libcgroup-0.41-21.el7.x86_64 @os Dep-Install libsemanage-python-2.5-14.el7.x86_64 @os Dep-Install policycoreutils-python-2.5-34.el7.x86_64 @os Dep-Install python-IPy-0.75-6.el7.noarch @os Dep-Install setools-libs-3.3.8-4.el7.x86_64 @os Scriptlet output: 1 setsebool: SELinux is disabled.

    这里可以看到时间是2020年,确实就是那时候安装的了,然后可以看到,很多依赖也一起安装了。

    此时,我们可以回退这整个事务:

    Copy
    从上面的Transaction ID : 46,拿到事务id,46,然后回退: yum history undo 46

    此时,可以卸载全部的依赖包。当然,这个undo操作执行完成后,也变成了一个事务,也可以回退的。

    参考:

    https://www.tecmint.com/view-yum-history-to-find-packages-info/

    https://unix.stackexchange.com/questions/303754/how-to-remove-all-installed-dependent-packages-while-removing-a-package-in-cento

    https://blog.csdn.net/mighty13/article/details/122412447

    重新执行,获取全部rpm#

    Copy
    yum install --downloadonly --downloaddir=/root/mypackage/ docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

    此时,再把rpm拷贝到目标服务器上,rpm -ivh *.rpm就可以安装完成了。

    私服问题#

    查看私服上docker仓库的connector地址#

    docker安装完成后,启动:

    Copy
    systemctl start docker 拉取: docker run hello-world

    没外网,自然是报错,所以还要配置私服。我们内网有一个之前其他组搭的nexus,里面好像有docker仓库,看看能不能用吧。

    我们nexus上(10.0.218.28),一共2个docker 仓库(一个host类型,存放公司内部镜像,一个proxy类型,连接了https://hub-mirror.c.163.com作为镜像源),最后又搞了一个group类型,聚合了上面两个仓库,对外就用这个group类型就可以,其connector地址为:

    image-20230929150127539

    所以,在docker这边,只需要修改为如下:

    Copy
    [root@monitor upload]# vim /etc/docker/daemon.json(如没有可新建) { "registry-mirrors": ["http://10.0.218.28:8083"], "insecure-registries": ["http://10.0.218.28:8083"] }

    就算是可以使用该私服了。

    想当然犯的错#

    接下来就是拉取,听说wordpress这个很多拿来做网站,模版很多,我就拉取试试:

    Copy
    [root@monitor upload]# docker pull wordpress Using default tag: latest latest: Pulling from library/wordpress Get "https://registry-1.docker.io/v2/": dial tcp: lookup registry-1.docker.io on [::1]:53: dial udp [::1]:53: connect: no route to host

    网上查了下,乱七八糟的,后面跟着其中一个,配了下dns:

    Copy
    [root@monitor upload]# vim /etc/resolv.conf

    然后,这次换了个错误:

    Copy
    [root@monitor upload]# docker pull wordpress Using default tag: latest latest: Pulling from library/wordpress Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

    这个错我真是花了不少时间,因为我认为我私服都配好了,为啥还会报这种问题(看起来还是去docker官方拉取),肯定是哪里配置没搞对吧。

    当时没有想到好办法,https的,抓包也不好抓;strace跟踪了docker daemon进程,也没看到啥东西。

    上网看了会,说,要好像pull时候要单独指定私服仓库地址:

    Copy
    [root@monitor ~]# docker pull 10.0.218.28:8083/wordpress Using default tag: latest latest: Pulling from wordpress manifest for 10.0.218.28:8083/wordpress:latest not found: manifest unknown: manifest unknown

    嗯,这次的报错不一样了,什么manifest unknown

    这次试着tcpdump抓了下和私服之间的网络包:

    Copy
    tcpdump -i any tcp port 8083 -w wordpress.pcap

    简单分析了下,一共有几个http请求:

    • 请求根地址
    Copy
    GET /v2/ HTTP/1.1 Host: 10.0.218.28:8083 响应: HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer realm="http://10.0.218.28:8083/v2/token",service="http://10.0.218.28:8083/v2/token" {"errors":[{"code":"UNAUTHORIZED","message":"access to the requested resource is not authorized","detail":null}]}

    意思是 需要认证。

    • 获取token

      Copy
      GET /v2/token?account=admin&scope=repository%3Awordpress%3Apull&service=http%3A%2F%2F10.0.218.28%3A8083%2Fv2%2Ftoken HTTP/1.1 Host: 10.0.218.28:8083 返回: HTTP/1.1 200 OK {"token":"DockerToken.c1a93413-7ade-389f-9231-4a153f644b74"}
    • 获取wordpress镜像的元数据标识

      Copy
      HEAD /v2/wordpress/manifests/latest HTTP/1.1 Host: 10.0.218.28:8083 HTTP/1.1 200 OK Docker-Content-Digest: sha256:a078d12a76827322cf95c1e3ae470d30bd518af6e0bdb42f4f49919b2b3ba74b

      我是第一次实际看到head类型的请求,返回的header里有一个sha256开头的字符串,下面要用

    • 获取元数据

      Copy
      GET /v2/wordpress/manifests/sha256:a078d12a76827322cf95c1e3ae470d30bd518af6e0bdb42f4f49919b2b3ba74b HTTP/1.1 Host: 10.0.218.28:8083 返回: HTTP/1.1 200 OK body为json,里面是元数据

      image-20230929153906750

    • 根据架构对应的digest串,获取具体镜像

      Copy
      GET /v2/wordpress/manifests/sha256:b4aabd2efdd7cf033b1f3b883c404ce2a260a27d83294f3a76c8e14b201572e4 HTTP/1.1 Host: 10.0.218.28:8083 HTTP/1.1 404 Not Found body: { "errors": [ { "code": "MANIFEST_UNKNOWN", "message": "manifest unknown", "detail": [ { "Name": "wordpress" }, { "Revision": "sha256:b4aabd2efdd7cf033b1f3b883c404ce2a260a27d83294f3a76c8e14b201572e4" } ] } ] }

      最后报的这个错,我就真的不是理解了。

    因为是通过nexus访问163那边,前面折腾了半天,后面想起来去nexus看下日志:

    Copy
    2023-09-29 16:34:36,211+0800 WARN [qtp1782934700-19476] admin org.sonatype.nexus.repository.docker.internal.V2Handlers - Is the remote url a valid docker endpoint? Remote host https://hub-mirror.c.163.com/ with path /v2/library/wordpress/manifests/sha256:b4aabd2efdd7cf033b1f3b883c404ce2a260a27d83294f3a76c8e14b201572e4 did not return the expected response. Error message: manifest unknown

    意思是感觉163那边返回的有问题。

    我就拿日志里这个地址去请求:

    image-20230929164403551

    意思是被限流了,还说,要提升限额,请访问docker官网的xx网站。

    docker login疯狂踩坑#

    因为上面那个报错信息,我怀疑是我这边请求太频繁了,网上查了下,说是docker从2020年开始限制匿名用户拉取频率为每6个小时分别限制为100,登录的用户为200个。

    https://blog.csdn.net/llg___/article/details/127230106

    方法嘛,看起来,要么是换个源,要么是docker login,提升到200个。

    我就想着,内网nexus服务器只开了到163这个源的网络,开网又麻烦,还是先搞个登录吧,解决目前的问题。

    登录就登录,我拿出了docker hub网站的用户名密码,然后docker login,发现他么登不进去啊。

    又以为是nexus私服的啥问题。后面就下班了,下班路上看了会docker login这块,思路清晰了一点,决定回家后,先去看看163源官网,看看有没有接口文档,看看这个报错要怎么弄(毕竟是他们报的错)。

    后面继续开整,网上找163镜像源的官网都找半天,最终发现是这个:

    https://sf.163.com/help/documents/15587821142962176

    https://sf.163.com/

    最终注册了个用户。

    后面在nexus服务器上,试着docker login登录网易私服,没想到还登上了,用的刚在网易注册的用户名和密码。

    Copy
    docker login hub-mirror.c.163.com:443

    此时,我才反应过来,原来登录不是传docker hub的密码,而是传私服的密码,艹,我还以为它们只是个代理呢,帮忙转发密码过去(现在想想也确实不对,密码一般不会转发,但也说不准啊)

    行吧,看来我登私服的话,得传私服的用户名密码了:

    Copy
    docker login 10.0.218.28:8083 -u admin -p xxxxxx

    还真是这样。

    后来我就想,我现在是通过nexus服务器去163拉取,163说我们过于频繁,那我通过nexus登录163不就行了吗。

    image-20230929161516178

    后面在网上找了半天nexus的文档,也没发现有这个功能。

    哎,看来靠登录来解决163限流的办法,是走不下去了。

    后面想着,不是限流吗,至少6小时内还是能拉取100次的,结果第二天去了,发现还是拉不下来镜像。

    原来是163源挂了,我他么#

    后面就是在网上溜达,看看有没有类似情况的,发现一篇公众号里提到这些事。

    Docker 镜像国内加速的几种方法,推荐收藏!

    说有个仓库在实时监测这些国内源的情况:

    https://github.com/docker-practice/docker-registry-cn-mirror-test/actions

    检测脚本(https://github.com/docker-practice/docker-registry-cn-mirror-test/blob/master/.github/workflows/ci.yaml)

    执行过程:

    https://github.com/docker-practice/docker-registry-cn-mirror-test/actions/runs/6333166370

    image-20230929162245184

    我看到检测结果是,163已经挂了,我看了执行日志,163这边的报错也是一模一样。

    image-20230929162407754

    哎,原来是源头的问题。

    另外,发现这个仓库里有些资料不错:

    https://github.com/yeasy/docker_practice/blob/master/install/mirror.md

    docker daemon打开debug日志#

    这些年习惯了抓包解决问题,有时候遇到https就没辙(手机端https还能靠代理来搞搞,服务器端这个暂时没研究)

    手里有了锤子,看哪里都是钉子,后面反应过来,https的话看日志应该也不错。

    方式1#

    将systemctl安装的docker停掉,用下面的方法启动:

    Copy
    /usr/bin/dockerd -l debug

    这个是前台启动,仅限自己掌控的docker这么操作。

    方式2#

    Copy
    systemctl stop docker vim /etc/docker/daemon.json { "registry-mirrors": ["http://10.0.218.28:8083"], "insecure-registries": ["http://10.0.218.28:8083"], "debug": true } systemctl start docker

    增加debug:true即可。

    然后docker info |grep debug 可以查看是否生效。

    日志位置#

    一般在tailf /var/log/messages或者 :

    Copy
    journalctl -u docker

    docker pull 10.0.218.28:8083/wordpress时,dockerd的日志大概如下:

    Copy
    Sep 29 16:33:13 monitor dockerd: time="2023-09-29T16:33:13.348868678+08:00" level=debug msg="Fetching manifest from remote" digest="sha256:a078d12a76827322cf95c1e3ae470d30bd518af6e0bdb42f4f49919b2b3ba74b" error="" remote="10.0.218.28:8083/wordpress:latest" Sep 29 16:33:13 monitor dockerd: time="2023-09-29T16:33:13.359405144+08:00" level=error msg="Not continuing with pull after error: manifest unknown: manifest unknown"

    虽然也不怎么详细,也能多点信息吧。

    另外,也可以看下nexus的日志:

    Copy
    lsof -p 38134(nexus pid)|grep log

    找到了日志位置:

    Copy
    /usr/local/nexus/sonatype-work/nexus3/log/nexus.log

    nexus的日志在协助甩锅到163那边,也发挥了巨大作用。

    总结#

    我不知道大家有没有遇到这么多问题,反正我这边感觉问题层出不穷的,don't know why.

    参考资料#

    https://docs.docker.com/config/daemon/

    https://platform9.com/kb/kubernetes/enable-debug-logging-for-docker-daemon

    https://docs.docker.com/engine/release-notes/24.0/

    https://www.cnblogs.com/xiongzaiqiren/p/16900429.html




  • 相关阅读:
    10. awd 层(数据集市层)
    【今天聊聊生产力】提升研发生产力的神器推荐
    FTX:这个加密货币冬天与以前的冬天非常相似
    VSCode 调试 u-boot
    java基础---NIO
    判断文件为文本文件还是二进制文件
    UE4,UE5虚幻引擎源码版下载
    如何在使用 ES Modules 的 Node.js 应用中创建和使用 __dirname 和 __filename 这两个全局变量
    【无标题】
    【备考网络工程师】如何备考2023年网络工程师之错题集篇(2)
  • 原文地址:https://www.cnblogs.com/grey-wolf/p/17737100.html