如何使用 Docker 通过 imgproxy 服务下一代图像

作者选择了 多样性在技术基金作为 写给捐款计划的一部分接受捐款。

介绍

网页开发者使用的最常见的图像格式是 JPEGPNG.jpg 文件最适用于照片,而 .png 文件最适用于具有相似颜色的大块图像,如标志或图表。然而,这些格式在1992年和1996年分别被开发出来。近年来,视频压缩的进步导致了网页开发的两种新的主要图像格式: webpavif.被称为下一代(或下一代)图像格式,这些格式可以免费使用,导致显著较小的图像(在20%和50%之间减少),并且正在得到网页浏览器的广泛支持。由于

然而,使用下一代格式存在一些挑战. 首先,如果您希望在较旧的浏览器上为用户提供最大的兼容性,您可能希望根据需要使用pngjpg

这是一个 _image proxy 可以帮助的地方. 图像 proxy 是一个应用程序,将基于网页请求生成或获取自定义图像的飞机上。 它们可以用于剪辑或调整图像,添加水标或图像效果,并更改格式。

一个可用的代理程序被称为imgproxy。它由邪恶的火星人(https://evilmartians.com/)支持,并且既可以作为一个自托的免费版本使用商业Pro扩展,如果您需要它们,imgproxy是用Go(https://go.dev)写的,并使用libvips(https://www.libvips.org)来驱动其图像转换。

在本教程中,您将设置imgproxy并生成代理 URL 来修改图像,您还将配置imgproxy以使用签名的 URL 安全地服务图像,并在支持的情况下自动切换到下一代图像格式。

前提条件

要遵循本教程,您将需要:

对于Ubuntu 20.04,你可以遵循指南, 如何在Ubuntu 20.04上安装和使用Docker(或选择其他版本或发行版)。对于macOS或Windows,请参阅产品文件 Docker Desktop。 *一个脚本语言来运行示例脚本. 在本教程中,我们将使用Ruby,您可以通过以下指南安装在Ubuntu上, 如何在Ubuntu 20.04上安装Ruby on Rails with rbenv)。在macOS,你可以使用内置版本 *一些熟悉浏览器开发工具将是有用的。对于Chrome,检查 官方文档或教程,

步骤 1 — 使用 Docker 安装imgproxy

在此步骤中,您将安装imgproxy并检查它是否正确运行. 安装imgproxy有几种不同的方法,但在本教程中,您将使用Docker(https://www.docker.com),因为它是最便携式的方法,并且在迁移到生产风格的环境时将意味着最小的变化。

在已安裝 Docker 的伺服器或開發機上,執行下列命令來檢查 Docker 是否正在執行:

1docker info

输出的开始将类似于以下情况(如果您的容器数量或图像略有不同,不要担心):

 1[secondary_label Output]
 2Client:
 3 Context:    default
 4 Debug Mode: false
 5 Plugins:
 6  buildx: Docker Buildx (Docker Inc., v0.7.1)
 7  compose: Docker Compose (Docker Inc., v2.2.1)
 8  scan: Docker Scan (Docker Inc., v0.14.0)
 9
10Server:
11 Containers: 15
12  Running: 0
13  Paused: 0
14  Stopped: 15
15 Images: 47
16 Server Version: 20.10.11
17 ...

一旦您确认 Docker 正在运行,您可以使用子命令从 Dockerhub下载imgproxy图像的最新版本:

1docker pull darthsim/imgproxy:latest

您将看到一组进度栏,而这下载图像。

接下来,您将使用运行子命令启动一个容器实例:

1docker run -p 8080:8080 -it darthsim/imgproxy

p选项告诉Docker将容器的端口8080地图到您的机器的端口8080--it选项告诉Docker您想要一个交互式终端(在这种情况下,您将希望看到imgproxy的日志输出)。

结果将看起来像这样:

1WARNING [2021-12-24T03:21:18Z] No keys defined, so signature checking is disabled
2WARNING [2021-12-24T03:21:18Z] No salts defined, so signature checking is disabled
3INFO    [2021-12-24T03:21:18Z] Starting server at :8080

不要担心警告;你会修复后一步。

在此步骤中,您安装了impgproxy,并确认它正在运行. 在下一步,您将使用imgproxy URL 请求修改的图像。

步骤 2 — 创建imgproxy URL 来修改图像

在此步骤中,您将创建imgproxyURL,您可以使用它来请求修改的图像。

在使用imgproxy时,网站的最终用户会向imgproxy发出HTTP请求,然后,imgproxy会发出请求,以获取 source 图像。源图像可以在互联网上的任何地方被我们的代理人访问(您将在以后的步骤中保护)。

您通过在 URL 参数中指定所需的修改类型来告诉imgproxy

1http://your-imgproxy-host/%signature/%processing_options/%encoded_source_url.%extension

这个URL中的%signature是可选的,你会在以后的步骤中配置它。%processing_options是你告诉imgproxy去做一些事情,比如收成或水印图像,或者如果你不希望图像被修改,你可以完全放弃它。%coded_source_url指向source_image,你要求imgproxy进行修改。你需要编码它,以便在嵌入另一个 URL 时保持有效性。

一旦您生成了代理 URL,您可以用新的代理 URL 替换一个img标签的src属性,例如,这里有一个典型的图像 URL:

1<img src="https://yourserver.com/assets/image.png" />

有了imgproxy,你可以用这样的东西来替代那个URL:

1<img src="https://imgproxy.yourserver.com/your imgproxy url here />

然而,当你学会使用imgproxy时,查看结果的最快方法是将URL键入你最喜欢的网页浏览器的地址栏中,这将立即显示结果。

由于您在 Docker 中启动了imgproxy,因此您的服务器正在运行localhost,并在端口8080上收听。

1http://localhost:8080

<$>[注] 注: 如果您正在使用远程服务器而不是本地机器来运行本教程,请在以下示例中用您的服务器的IP地址代替localhost

对于本教程,你可以使用下面的链接中发现的小狗的图片: https://i.imgur.com/KSLD4VV.jpeg. (本图像最初来自 Unsplash)。

创建代理 URL 的第一步是编码源 URL. 这意味着您将 URL 中的所有具有含义的特殊字符(例如, ://, /, .)用没有含义的安全字符代替。

「imgproxy」使用 URL-safe Base64编码. 您可能有一个最喜欢的编程语言来使用,或者一个在线的 Base64编码工具会做这个技巧(请确保检查标记为执行URL-safe编码(使用Base64URL格式)的框)。

<$>[注] **注:**您可以使用简单的 URL 代替 Base64 编码的 /plain 选项,但这意味着您需要编码任何查询参数。

使用URL-Safe Base64的样本小狗图片编码为aHR0cHM6Ly9pLmltZ3VyLmNvbS9LU0xENFZWLmpwZWc

1http://localhost:8080/sig/aHR0cHM6Ly9pLmltZ3VyLmNvbS9LU0xENFZWLmpwZWc

<$>[注] 注: 如果您正在使用不同的图像测试,请用 Base64 编码的 URL 代替本 URL 的最后一部分。

一旦您加载,您将看到未修改的狗狗的图像。

<$>[注] 注: 如果您看不到图像,则会显示错误消息,或者您可以从步骤 1 检查docker run命令的输出,它会显示imgproxy日志,包括导致错误的任何请求。

接下来,您将使用URL的.extension部分更改图像格式,并在浏览器中打开以下内容:

1http://localhost:8080/sig/aHR0cHM6Ly9pLmltZ3VyLmNvbS9LU0xENFZWLmpwZWc.png

这将需要更长的时间来加载,如果你在浏览器的开发工具中查看网络标签,你会发现这个图像比原始图像大得多 - 在样品小狗图像的情况下,png版本为15.84MB,而原始jpg仅为1.3MB。

Screenshot showing browser developer tools highlighting an image transfer size of 15.4MB

您还可以将此图像转换为更高效的下一代格式,即webpavif,将其中一个格式添加为规格,如下:

1http://localhost:8080/sig/aHR0cHM6Ly9pLmltZ3VyLmNvbS9LU0xENFZWLmpwZWc.webp

测试图像的webp版本大约为600KB - 与原始的.jpg相比,这是大约53%的减少。

您也可以更改图像大小或添加不同的效果. 您可以这样做,通过指定不同的修改作为 %processing_options 参数。 在这种情况下,您将要求 'imgproxy' 将图像的大小调整为 200 个宽度和 500 个像素的高度,使用 resizing_type' 的 fill' (保持图像 外观比和外部的图像部分),然后使用 5 个面具大小添加 gaussian blur

尝试通过访问您的浏览器中的以下URL:

1http://localhost:8080/sig/size:200:500/resizing_type:fill/blur:5/aHR0cHM6Ly9pLmltZ3VyLmNvbS9LU0xENFZWLmpwZWc

如果您将该 URL 加载到您的浏览器中,您将看到测试图像的模糊和调整版本。

Screenshot of resized puppy image with blur effect

除了更改和模糊之外,您还可以使用许多不同的转换方法. 有关更多选项,请参阅imgproxy文档的 生成 URL 部分

在此步骤中,您生成了imgproxy URL 以服务并修改源图像,接下来,您将保护imgproxy,以便它只提供您使用%signature URL 参数特别允许的 URL 源图像。

步骤 3 – 通过签名确保imgproxy

到目前为止,您一直在使用imgproxy URL 的签名部分中的位置保持者,但是,重要的是要 签名您正在使用的 URL。这意味着imgproxy将处理的唯一 URL 是您使用秘密密密钥/盐对创建的 URL。

「imgproxy」是一個 12因子的應用程式,這意味著您可以使用環境變量設定它,而不需要修改任何檔案。

要创建签名,您首先需要一个键/盐对,这可以是任何随机六十字符串. 您可以使用您的计算机上的随机数据或使用 在线随机生成工具来生成它们。

生成两个64位的六十字符串,类似于下面所示。

1[secondary_label Example Random Hex]
249d5e2cd30d80fccc2e30877e4e58b2f0854a8dca6fb2e980b129171910080ed7ffa5dfbfde006e0c1a8ff52e7b5c614f0d3e9ec6e6ed754399fb0e2eb473c59

(请注意,你的字符串将与上面的字符串不同) 记录在下一个命令中使用的生成的字符串。

接下来,使用您在步骤 1 中使用的相同命令重新启动 Docker,但这一次添加两个 --env 选项,以将环境变量 IMGPROXY_KEYIMGPROXY_SALT 设置为运行容器中的随机生成的值。

1docker run --env IMGPROXY_KEY=first-hex-result --env IMGPROXY_SALT=second-hex-result -p 8080:8080 -it darthsim/imgproxy

现在,如果你在你的网页浏览器中打开http://localhost:8080/sig/aHR0cHM6Ly9pLmltZ3VyLmNvbS9LU0xENFZWmpwZWc,你会收到一个403 禁止的回复。你还会看到Docker日志中的条目,看起来像这样:

1[secondary_label Example Docker Log]
2WARNING [2021-12-28T03:12:34Z] Completed in 134.6µs /sig/aHR0cHM6Ly9pLmltZ3VyLmNvbS9LU0xENFZWLmpwZWc request_id=WQGTfRgeBXPvaQYHkNjab method=GET status=403 client_ip=172.17.0.1 error="Invalid signature"

正如你在日志线的末尾所看到的,imgproxy返回了一个403错误,因为你没有指定一个与imgproxy预期相匹配的签名。这意味着你正确配置了imgproxy以要求签名。这个签名匹配是 共享秘密身份验证的一个例子。imgproxy正在内部计算一个签名,使用所请求的URL的SHA256(https://en.wikipedia.org/wiki/SHA-2)哈希,加上密钥和盐。为了生成相同的签名,必须提供相同的秘密密密钥和盐。这意味着只有具有您的IMGPROXY_KEYIMGPROXY_SALT值的个人或程序才能生成您的imgproxy实例

<$>[注] **注:您不会直接在URL中指定密钥或盐值,因为这将被公开,无论是在网页的源头上,还是在其他浏览器或代理程序缓存时。

最后,为了进行有效的请求,您需要以同样的方式生成有效的签名,如imgproxy。在imgproxy Github 复制中,有很多 示例实现签名算法可用,但对于本教程,您将使用 Ruby 脚本。

使用nano或您最喜欢的文本编辑器,创建一个名为signature.rb的文件:

1nano signature.rb

将下面的内容复制到您的文件中。 用您先前生成的IMGPROXY_KEYIMGPROXY_SALT值代替键盐对。

 1[label signature.rb]
 2# adapted from https://github.com/imgproxy/imgproxy/blob/master/examples/signature.rb
 3require "openssl"
 4require "base64"
 5
 6key = ["your IMGPROXY_KEY value"].pack("H*")
 7salt = ["your IMGPROXY_SALT value"].pack("H*")
 8
 9url = "https://i.imgur.com/KSLD4VV.jpeg"
10
11encoded_url = Base64.urlsafe_encode64(url).tr("=", "").scan(/.{1,16}/).join("/")
12
13path = "/#{encoded_url}"
14
15digest = OpenSSL::Digest.new("sha256")
16hmac = Base64.urlsafe_encode64(OpenSSL::HMAC.digest(digest, key, "#{salt}#{path}")).tr("=", "")
17
18signed_path = "/#{hmac}#{path}"
19
20puts "Open http://localhost:8080#{signed_path} in a web browser"

首先,这个代码块需要生成您的签名所需的库,然后它将密钥和盐串转换为六字节,使用 .pack(H*),因为这就是OpenSSL库所期望的(您可以阅读更多关于包和解包的信息)。

然后,脚本 URL-safe Base64编码源 URL,类似于您在步骤 1 中所做的,尽管在这种情况下,它还删除任何在 Base64 中使用的任何 = 字符,并将每 16 个字符分成 /

一旦脚本具有编码的源 URL,它会使用 SHA256 算法、秘密密密钥和盐来生成签名,然后签名本身就会被 Base64 编码,以便它可以安全地纳入您的结果 URL。

最后,脚本有助于打印您可以在浏览器中打开的签名URL。

您可以打开终端中的另一个卡,或按Ctrl+C停止imgproxy,运行脚本,然后使用docker命令重新启动它。

1ruby signature.rb

结果将看起来像这样:

1[secondary_label Output]
2Open http://localhost:8080/-CAkkjs5IioquivOi5LYyDnVxEULmPK-xIwIwXTleUA/aHR0cHM6Ly9pLmlt/Z3VyLmNvbS9LU0xE/NFZWLmpwZWc in a web browser

突出的部分将在您的 URL 中有所不同. 这是您的签名的 URL,只有您可以生成,因为只有您知道的密钥/盐对. 如果您在浏览器中打开您的签名的 URL,您将看到预期的图像而不是403。

您现在已经配置了imgproxy以要求签名URL,并且您生成了一个有效的签名URL,现在只有有访问您的密钥/盐对的人或程序才能与您的imgproxy交谈。

接下来,您将配置imgproxy,以自动提供最现代化的图像格式。

步骤 4 — 配置imgproxy自动服务下一代图像

到目前为止,您一直明确地告诉imgproxy在返回图像时使用哪种格式。另一种选择是告诉imgproxy使用最有效的图像格式。这意味着您只能在用户浏览器支持Next-Generation格式(webpavif)的情况下提供服务。否则,imgproxy会自动返回pngjpg

imgproxy通过检查 ‘Accept’ 标题,该标题在网页浏览器发送请求时自动发送,以检查支持的图像格式。

1image/avif,image/webp,image/apng,image/*,*/*;q=0.8

由于存在image/avifimage/webp(相应的图像格式的MIME类型(https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types),我们知道Chrome 支持两种图像格式。

您可以使用 AVIF/WebP 支持检测命令imgproxy使用最现代的支持图像格式。 要启用此功能,请将环境变量IMGPROXY_ENABLE_WEBP_DETECTION设置为true,您可以在调用docker run时指定它。

首先,使用Ctrl+C停止运行您的Docker图像,然后使用以下命令重新启动它,确保用您的关键和盐值替换突出部分:

1docker run --env IMGPROXY_ENABLE_WEBP_DETECTION=true --env IMGPROXY_KEY=your-key-from-Step-3 --env IMGPROXY_SALT=your-Salt-from-Step 3 -p 8080:8080 -it darthsim/imgproxy

这是您在步骤 3 中使用的相同的docker命令,附加一个--env标志来启用webp检测。

要检查配置,您将在浏览器中打开图像. 访问您在步骤 3 中生成的签名URL,它看起来像这样:

1[secondary_label Example Image URL]
2http://localhost:8080/-CAkkjs5IioquivOi5LYyDnVxEULmPK-xIwIwXTleUA/aHR0cHM6Ly9pLmlt/Z3VyLmNvbS9LU0xE/NFZWLmpwZWc

您可以通过检查您的浏览器开发工具中的请求大小和类型来验证此情况,或者使用curl来验证使用curl,在您的终端打开一个新的卡,以便imgproxy继续运行,并使用以下命令,以您自己的代替突出的 URL:

1curl -s -v -H "Accept: image/avif,image/webp,image/apng,image/*,*/*;q=0.8" http://localhost:8080/M-RTYvp5xktEK9gG93hPwAB6on9aX7H5XciGsI3XSac/aHR0cHM6Ly9pLmlt/Z3VyLmNvbS9LU0xE/NFZWLmpwZWc

-s 标志意味着对输出保持沉默,因为在简单文本中输出时,图像没有太大的意义。 -v 意味着语音,这样你就可以看到请求和响应标题。

结果将看起来像这样:

 1[secondary_label Output]
 2*   Trying ::1:8080...
 3* Connected to localhost (::1) port 8080 (#0)
 4> GET /M-RTYvp5xktEK9gG93hPwAB6on9aX7H5XciGsI3XSac/aHR0cHM6Ly9pLmlt/Z3VyLmNvbS9LU0xE/NFZWLmpwZWc HTTP/1.1
 5> Host: localhost:8080
 6> User-Agent: curl/7.77.0
 7> Accept: image/avif,image/webp,image/apng,image/*,*/*;q=0.8
 8>
 9* Mark bundle as not supporting multiuse
10< HTTP/1.1 200 OK
11< Cache-Control: max-age=3600, public
12< Content-Disposition: inline; filename="KSLD4VV.webp"
13< Content-Length: 601246
14< Content-Type: image/webp
15< Expires: Tue, 28 Dec 2021 09:08:32 GMT
16< Server: imgproxy
17< Vary: Accept
18< X-Request-Id: I3sp-dXATs2AClfpHcSg-
19< Date: Tue, 28 Dec 2021 08:08:32 GMT
20<
21* Failure writing output to destination
22* Closing connection 0

您可以在内容类型标题中看到imgproxy已返回 webp 图像。

如果您想要,您可以对IMGPROXY_ENABLE_AVIF_DETECTION环境变量做同样的事情,但对于avif格式而不是webp

在此步骤中,您将imgproxy配置为自动使用下一代图像格式,如果并且只有用户浏览器支持这些格式。

结论

在本教程中,您已经了解了新的图像格式以及如何通过Docker运行、配置和保护imgproxy。您还配置了imgproxy,以便自动向任何网站访问者提供webp图像,使用可以处理它们的浏览器。

作为下一步,您可以探索使用imgproxy处理图像的额外选项。您可以在产品文档中看到完整的 处理选项列表。您还可以探索额外的 配置选项

Published At
Categories with 技术
comments powered by Disqus