解决Nexus Docker仓库搜索镜像返回500错误

之前用 Nexus 给团队搭建了一个数据仓库,其中 Docker 仓库配置教程已经整理分享到了博客《Nexus3 最佳实践系列:搭建 Docker 私有仓库》,但是一直有个小问题,使用 docker search 来搜索会返回 500 错误:

[root@localhost:~]# 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:

[root@localhost:~]# 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:

[root@localhost:~]# 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,结果如下:

[root@localhost:~]# 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 版本能够考虑加上这个特性。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇