next/image 在 docker 容器中使用时加载不一致?

问题描述 投票:0回答:1

首先一些背景信息。我有 2 个 docker 容器正在运行用于开发:api 和前端:

  • API 容器由 Strapi 后端组成,它还托管我们所有的图像。
  • 前端容器由我们的 NextJS“前端”组成。

由于 next/image 会自动优化服务器端的图像,因此我们为图像传递以下基本 url:

http://host.docker.internal:1337/uploads/*filenamehere.ext*

这对于 80% 的图像来说效果很好。但有时由于某种原因它不会使用NextJS图像优化,然后会尝试直接访问图像。

就像你在这里看到的: Image of 2 successful optimized image requests and one unoptimized image

这里的问题是它会尝试直接从客户端访问 url

http://host.docker.internal:1337/uploads/carbon_..etc.svg
,这是不可能的...

有什么好的解决方案吗?我想继续使用 Next 的图像优化。

最简单的可能是从我的主机访问“api”容器,使用:

127.0.0.1:1337
。但就没有别的办法了吗?

我想阻止使用主机网络。

reactjs docker next.js networking
1个回答
0
投票

不起作用的请求是针对 SVG 的。 NextJS 不需要优化 SVG,因为它们是表示为文本的矢量格式。

这意味着默认情况下它不会对它们执行任何操作,因此“原始”图像位置的 URL 最终由 HTML

<img>
标记直接使用。该 URL 被发送到您的上游服务器,该服务器无法公开访问;因此,当浏览器尝试获取它时它不起作用。

这里的问题是人们(至少部分地)出于错误的原因而依赖 NextJS 图像优化。您的图像似乎托管在其他一些上游服务上,该服务无法在您的容器上公开访问。因此,您需要通过 NextJS 服务器反向代理这些图像。

NextJS 图像优化将顺便且仅部分满足此要求。 它仅适用于 NextJS 认为需要优化的图像。对于这些,它从源下载(通过内部网络启用,因此可以这样做)图像,优化它,缓存它,然后从 NextJS 实例上的 URL 提供该图像。

这意味着对于优化的图像,缓存的 URL 最终用于 HTML

<img>
标记,该标记可在浏览器中工作,因为它是可访问的 URL。

这使得启用

dangerouslyAllowSVG
变得很诱人,这将迫使它也采用与 SVG 相同的代码路径。 但是,这并不能解决心智模型/架构缺陷——这是“真正的”问题。它似乎也有安全隐患。 从上游反向代理图像的要求是其自身的业务需求,并且您不应该依靠图像优化本身来实现这一点。 NextJS 图像优化旨在提供一种优化图像的机制。在某些情况下,它充当反向代理是一个技术细节,您现在或将来不能依赖该行为来满足此业务需求。您对此反向代理有一流的要求,因此您必须定义它。

我们可以使用

rewrites

来实现这一点。在next.config.js

module.exports = {
  async rewrites() {
    return [
      {
        source: '/raw/:path*',
        destination: 'http://host.docker.internal:1337/uploads/:path*'
      },
    ]
  },
}

这意味着您的 NextJS 实例上的新 URL 
/raw/<image-path>

可用,其中

image-path
是要从
http://host.docker.internal:1337/uploads
请求的图像的文件名。
然后,当使用 

<Image>

标签时,将传递的

src
属性将是上面
source
目的地的相对路径,并且
not
包含任何完全限定的内部 docker 域。例如。 src="/raw/example-image.svg"
对于 NextJS 不需要做任何优化的情况(例如 SVG),它将执行之前所做的操作,即直接使用 

src

属性作为

src
<img>
HTML 属性。但现在该 URL 将是有效的,指向我们的
/raw
路径,NextJS 将通过我们的重写将其代理到上游。
    

© www.soinside.com 2019 - 2024. All rights reserved.