Docker中Poetry安装私有包突然启动失败

Hyn*_*aha 11 pypi docker python-poetry

关于

\n

最小工作示例:https://gitlab.com/hynek.blaha/debug-docker-poetry/-/tree/master

\n

我一直在使用 Poetry 和来自内部 PyPI 注册表的 Python 包构建 Docker 镜像。由于我们的项目位于私有 GitLab 存储库中,并且内部包不是绝密的,因此我们将诗歌凭证直接存储在pyproject.toml.

\n

2022 年 8 月 24 日,我们所有的 Docker 构建在安装内部包时开始失败:

\n
\xe2\x80\xa2 Installing til-bigquery (0.3.4)\n\n  HTTPError\n\n  401 Client Error: Unauthorized for url: https://gitlab.com/api/v4/projects/38869805/packages/pypi/files/7a4731d831d4b37262481002271e359f96017570e9480ef16c89489e0b41252f/til_bigquery-0.3.4-py3-none-any.whl#sha256=7a4731d831d4b37262481002271e359f96017570e9480ef16c89489e0b41252f\n\n  at /usr/local/lib/python3.9/site-packages/requests/models.py:1021 in raise_for_status\n      1017\xe2\x94\x82                 f"{self.status_code} Server Error: {reason} for url: {self.url}"\n      1018\xe2\x94\x82             )\n      1019\xe2\x94\x82 \n      1020\xe2\x94\x82         if http_error_msg:\n    \xe2\x86\x92 1021\xe2\x94\x82             raise HTTPError(http_error_msg, response=self)\n      1022\xe2\x94\x82 \n      1023\xe2\x94\x82     def close(self):\n      1024\xe2\x94\x82         \n      1025\xe2\x94\x82         called the underlying ``raw`` object must not be accessed again.\n\n
Run Code Online (Sandbox Code Playgroud)\n

我发现奇怪的是:

\n
    \n
  • 即使我重试几天前成功通过的部署作业,Docker 构建也会失败。
  • \n
  • 考虑到这个问题可能是由未固定的 Docker 基础镜像或 Poetry 的次要版本引起的python:3.7-slim,我使用了旧版本,但得到了相同的结果。
  • \n
  • 我比较了之前成功构建build_success.log8/22/22,3:00 PM)和相同构建重试build_fail.log8/24/22,6:00 AM)的构建日志,发现两者都使用相同的诗轮poetry-1.1.15-py2.py3-none-any.whl
  • \n
\n

它在我的机器上仍然像以前一样工作,但在 Docker 中失败了。

\n
    \n
  • 当我从存储库 URL 中删除凭据时,它会停止在 localhost 上工作,因此我确信凭据不会存储在其他位置(例如 ~/.netrc)。
  • \n
\n

如何重现:

\n
    \n
  1. 本地主机 - 好的
  2. \n
\n
git clone git@gitlab.com:hynek.blaha/debug-docker-poetry.git\npoetry install\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. Docker - 失败
  2. \n
\n
git clone git@gitlab.com:hynek.blaha/debug-docker-poetry.git\ndocker build .\n
Run Code Online (Sandbox Code Playgroud)\n

我可以通过在 Dockerfile 中显式提供凭据来解决该问题:

\n
RUN pip install poetry --no-cache-dir && \\\n    poetry config virtualenvs.create false && \\\n    poetry config repositories.my_private_repo https://gitlab.com/api/v4/projects/21870843/packages/pypi/simple && \\\n    poetry config http-basic.my_private_repo __token__ glpat-mkEPJ4Rsy2peTCrH23pG\n
Run Code Online (Sandbox Code Playgroud)\n

但它没有解释为什么重建相同的映像开始失败。\n以及为什么它在我的机器上(在 Docker 之外)运行时仍然按预期工作。

\n

有谁知道,可能会发生什么变化?diff即使在build_success.log和上使用时我也无法说出什么build_fail.log

\n

mon*_*ina 10

过去几天我一直在努力解决完全相同的问题。虽然我仍然不确定确切的原因,但我设法避免了这个问题。

我还使用了一个存储库 URL,其中嵌入了凭据,pyproject.toml直到昨天,就像这样。

[[tool.poetry.source]]
name = 'private'
url = 'https://your_username:your_password@gitlabce.example.com/api/v4/projects/<project_id>/packages/pypi/simple'
secondary = true
Run Code Online (Sandbox Code Playgroud)

尽管它与您的解决方案基本相同,但您可以通过poetry.toml在项目根目录下创建来指定每个项目的本地诗歌配置。poetry.toml因此,您可以通过如下方式指定它们,而不是在 URL 中嵌入凭据:

[http-basic]
[http-basic.private]
username = "your_username"
password = "your_password"
Run Code Online (Sandbox Code Playgroud)

这样,您就可以使用嵌入的凭据重现相同的行为,而不会出现身份验证错误。

为什么它在 docker 之外仍然可以工作?

我猜这是由于您本地环境中的存档缓存所致。由于诗歌存储下载的档案~/.cache/pypoetry/artifacts/并在执行时重用它们poetry install,因此您首先不需要访问您的私人 PyPI 服务器。如果您手动删除存档(我不确定,但poetry cache clear命令不适用于我的情况),即使在本地环境中,您也能够重现身份验证错误。

为什么突然开始出现错误?

Poetry 使用嵌入的凭据来查询私有 PyPI 服务器的包链接列表。在此之前它工作正常,但是,在安装实际包时,Poetry 使用从未嵌入凭据的 PyPI 服务器获取的链接。这就是它失败的原因,并且错误消息中显示的 URL 没有嵌入任何凭据。

我仍然不确定为什么凭证嵌入直到几天前才起作用。我猜想 GitLab 方面可能发生了行为变化。

  • 我认为最近 gitlab 的更改可能是造成这种情况的原因。看起来它之前工作的唯一原因是 Gitlab 没有对获取的链接进行任何身份验证(!)。请参阅 https://gitlab.com/gitlab-org/gitlab/-/issues/351438 或者 https://gitlab.com/gitlab-com/gl-infra/product/-/issues/7655 (2认同)