之前用 Nexus 给团队搭建了一个数据仓库,其中 Docker 仓库配置教程已经整理分享到了博客《Nexus3 最佳实践系列:搭建 Docker 私有仓库》,但是一直有个小问题,使用 docker search 来搜索会返回 500 错误:
[[email protected]:~]# docker search idocker.io/hello-world Error response from daemon: Unexpected status code 500
因为平常不怎么使用搜索,而且 Nexus 前台也有镜像浏览页面,所以一直没花时间去解决。年前封网好不容易有点空闲,寻思着解决下。
经过定位,发现了问题所在:Nexus 里面的 Docker 有 3 种类型仓库:group、hosted、proxy,也就是组合仓库、本地仓库和代理仓库,其中组合仓库就是本地仓库和代理仓库的聚合,通过测试发现只有本地仓库才支持 search 请求,其他 2 种类型仓库都会 500 错误。所以,报错的直接原因就是我将 search 的请求转发到了组合仓库导致的。
解决办法非常简单,在 nginx 转发里面加一条规则即可:
if ($request_uri ~ '/search') { set $upstream "nexus_docker_put"; }
Ps:详见之前的文章:https://zhang.ge/5139.html 。
以下是定位过程,不感兴趣的可以忽略。。。
1、确认 Nginx 代理日志是正常打开状态,并 tail -f idocker.io.log 实时查看日志;
2、执行 docker search 发起搜索:
docker search idocker.io/hello-world
3、回过来查看日志:发现 500 错误的内容如下(我这边 Nginx 改成了 json 格式):
{ "client_ip": "192.168.1.100", "http_host": "idocker.io", "@timestamp": "2019-01-31T10:24:29+08:00", "method": "GET", "url": "/v1/search?q=hello-world&n=25", "status": "500", "http_referer": "-", "body_bytes_sent": "1968", "request_time": "2.372", "http_user_agent": "docker/17.09.1-ce go/go1.8.3 git-commit/19e2cf6 kernel/3.10.107-1-tlinux2-0046 os/linux arch/amd64 UpstreamClient(Docker-Client/17.09.1-ce \\(linux\\))", "total_bytes_sent": "2430", "server_ip": "192.168.1.111" }
2 个重要的信息:搜索请求使用的是 GET 方法,请求路径是 /v1/search?q=hello-world&n=25。
4、直接对仓库后端一次发起请求,首先试了下 group 组合仓库,端口 8082:
[[email protected]:~]# curl -k "http://192.168.1.200:8082/v1/search?q=hello-world&n=25" <!DOCTYPE html> <html lang="en"> <head> <title>500 - Nexus Repository Manager</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <!--[if lt IE 9]> <script>(new Image).src="/goto/aHR0cDovLzE5Mi4xNjguMS4yMDA6ODA4Mi9mYXZpY29uLmljbz8zLjE0LjAtMDQ=" target="_blank"</script> <![endif]--> <link rel="icon" type="image/png" href="/goto/aHR0cDovLzE5Mi4xNjguMS4yMDA6ODA4Mi9mYXZpY29uLTMyeDMyLnBuZz8zLjE0LjAtMDQ=" target="_blank" sizes="32x32"> <link rel="mask-icon" href="/goto/aHR0cDovLzE5Mi4xNjguMS4yMDA6ODA4Mi9zYWZhcmktcGlubmVkLXRhYi5zdmc/My4xNC4wLTA0" target="_blank" color="#5bbad5"> <link rel="icon" type="image/png" href="/goto/aHR0cDovLzE5Mi4xNjguMS4yMDA6ODA4Mi9mYXZpY29uLTE2eDE2LnBuZz8zLjE0LjAtMDQ=" target="_blank" sizes="16x16"> <link rel="shortcut icon" href="/goto/aHR0cDovLzE5Mi4xNjguMS4yMDA6ODA4Mi9mYXZpY29uLmljbz8zLjE0LjAtMDQ=" target="_blank"> <meta name="msapplication-TileImage" content="http://192.168.1.200:8082/mstile-144x144.png?3.14.0-04"> <meta name="msapplication-TileColor" content="#00a300"> <link rel="stylesheet" type="text/css" href="/goto/aHR0cDovLzE5Mi4xNjguMS4yMDA6ODA4Mi9zdGF0aWMvY3NzL25leHVzLWNvbnRlbnQuY3NzPzMuMTQuMC0wNA==" target="_blank"/> </head> <body> <div class="nexus-header"> <a href="/goto/aHR0cDovLzE5Mi4xNjguMS4yMDA6ODA4Mg==" target="_blank"> <div class="product-logo"> <img src="http://192.168.1.200:8082/static/images/nexus.png?3.14.0-04" alt="Product logo"/> </div> <div class="product-id"> <div class="product-id__line-1"> <span class="product-name">Nexus Repository Manager</span> </div> <div class="product-id__line-2"> <span class="product-spec">OSS 3.14.0-04</span> </div> </div> </a> </div> <div class="nexus-body"> <div class="content-header"> <img src="http://192.168.1.200:8082/static/rapture/resources/icons/x32/exclamation.png?3.14.0-04" alt="Exclamation point" aria-role="presentation"/> <span class="title">Error 500</span> <span class="description">Internal Server Error</span> </div> <div class="content-body"> <div class="content-section"> javax.servlet.ServletException: java.lang.IllegalStateException: No case for assetKind: SEARCH </div> </div> </div> </body> </html>
终于看到了关键的报错:
javax.servlet.ServletException: java.lang.IllegalStateException: No case for assetKind: SEARCH
大概意思是不支持 SEARCH,于是继续试了下 hosted 本地仓库,端口 8083:
[[email protected]:~]# curl -k "http://192.168.1.200:8083/v1/search?q=hello-world&n=25" {"query":"hello-world","num_results":3,"num_pages":1,"page":1,"page_size":25,"results":[{"star_count":0,"is_official":false,"name":"192.168.1.200:8083/hello-world-poncexu:latest","is_trusted":false,"is_automated":false,"description":null},{"star_count":0,"is_official":false,"name":"192.168.1.200:8083/hello-world:v1.0","is_trusted":false,"is_automated":false,"description":null},{"star_count":0,"is_official":false,"name":"192.168.1.200:8083/hello-world:v2.0","is_trusted":false,"is_automated":false,"description":null}]}
很明显是可以的,然后再试了下 proxy 代理仓库,都不行。因此确定只有本地仓库是可以搜索的!
回头看了下 Nginx 代理的配置,发现我之前将所有 GET 都丢给了组合仓库,也就是转发了拉取请求,将 PUT 丢给了本地仓库,意思是转发了推送请求。看来,还需要多加一个规则,将搜索请求转发到本地仓库。
也就是得出了上文的规则:
# 设置默认使用推送代理 set $upstream "nexus_docker_put"; # 当请求是 GET,也就是拉取镜像的时候,这里改为拉取代理,如此便解决了拉取和推送的端口统一 if ( $request_method ~* 'GET') { set $upstream "nexus_docker_get"; } # !!! 本次新增的转发规则 !!! # 只有本地仓库才支持搜索,所以把搜索请求转到本地仓库 if ($request_uri ~ '/search') { set $upstream "nexus_docker_put"; }
这个规则明显要加到 PUT 转发规则之后,以覆盖之。
生效后,再次执行 docker search idocker.io/hello-world,结果如下:
[[email protected]:~]# docker search idocker.io/hello-world NAME DESCRIPTION STARS OFFICIAL AUTOMATED idocker.io/hello-world-jager:latest 0 idocker.io/hello-world:v1.0 0 idocker.io/hello-world:v2.0 0
问题得到解决~!
当然,还有点遗憾的是代理和组合仓库不支持搜索~希望后续 Nexus 版本能够考虑加上这个特性。
咦,第一次沙发,好紧张,有没有潜规则 :grin:
不知道为什么,我的网站好像被百度鄙视了,权重一直是零,而且SEO数据一直不更新,郁闷啊
跟着Jager大佬能学习到不少技术 :grin:
请问一下博客,把整个网站都改成docker容器,性能会不会好一点? 我服务器是1h2g的
不会 甚至还有5%的损失
5%就有点夸张了,基本可以忽略估计,而且一般像我们这种网站,这点损失感知不到,不像大站会千万倍的放大。
技术很niu 啊
感谢分享!!!
很棒的教程 一直在找相关的内容 感谢分享
很棒的教程 感谢分享
Jager厉害啊,啥时搞了这么一名牛B的域名呀