# Docker 镜像更新：Redis 6 及镜像大小缩小 25%

**URL:** https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437
**Category:** Announcements
**Tags:** docker
**Created:** [2020年十一月26日 22:02 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437 "2020-11-26T22:02:27Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [2020年十一月26日 22:02 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/1 "2020-11-26T22:02:27Z")

</div>

我们刚刚发布了一个全新的容器镜像，将在您下次运行 `./launcher rebuild app` 时使用。一如既往，只要您遵循我们的 [Discourse 官方标准安装指南](https://meta.discourse.org/t/discourse-official-standard-installation/142537)，则无需更改任何配置。不过，此次更新引入了一些新功能，将有助于某些部署环境。

### Redis 6

我们在 Discourse 的多个地方 **大量** 使用 Redis，包括缓存、Sidekiq、MessageBus、分布式锁和速率限制等。总体而言，它一直是我们可靠的选择。

然而，在某些特定工作负载下，Redis 可能成为性能瓶颈。由于 Redis 的单线程特性，加上我们因使用 LUA 脚本而无法部署多个实例，这使得该瓶颈难以绕过。

幸运的是，Redis 6 增加了对 I/O 操作使用线程池的支持。在我们的测试中，它非常适合那些因 Redis 而受限的 Discourse 集群。

因此，如果您运行的机器拥有 **大量** CPU 核心，且 [监控指标](https://meta.discourse.org/t/prometheus-exporter-plugin-for-discourse/72666) 显示 Redis 难以处理当前负载，您现在可以通过 `app.yml` 的 `params` 部分选择启用写入操作的线程支持：

```yaml
params:
  redis_io_threads: "4" # 1 表示禁用，n>1 表示使用 n-1 个额外线程进行 I/O 写入

```

### 更小的镜像

在项目初期，我们选择发布较大的容器镜像，以便非技术人员更容易运行 Discourse，并处理所有必要的依赖项、版本控制和升级等问题。

不过，最近我们的_压缩后_镜像大小已超过 1GB，这确实有些过大。

为了缓解镜像体积不断增大的问题，我们将 Discourse 源代码从镜像内的完整副本改为仅包含最新代码版本的“浅克隆（shallow clone）”。

这一改动使压缩后的镜像体积减少了 25%，从而降低了所需的服务器存储空间，并在发布新镜像时加快了重建速度。同时，这也有助于控制镜像随时间增长的幅度。

我们在 tests-passed、beta 和 stable 分支上进行了测试，包括重建和 Web 更新，未破坏任何标准路径。不过，在 `app.yml` 钩子中执行更复杂的 git 操作的用户可能需要调整其自定义配置。

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2020年十一月27日 12:09 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/2 "2020-11-27T12:09:25Z")

</div>

此类 Redis 升级后，浏览器体验会发生什么变化？是否会影响缓存的资源？升级后这些资源会被清空吗？

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [2020年十一月27日 14:21 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/3 "2020-11-27T14:21:44Z")

</div>

> [@merefield](#):
>
> 这样的 Redis 升级后，浏览器体验会发生什么变化吗？

没有任何影响。

> [@merefield](#):
>
> 对缓存资源有影响吗？

资源会保存到本地磁盘或对象存储中，并由 CDN 进行缓存。Redis 不会影响这些资源。

> [@merefield](#):
>
> 升级会导致这些数据被清空吗？

Redis 数据在升级期间会被保留。

---

<div class="post-metadata">

### Author: ![codinghorror](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/codinghorror/32/110067_2.png) [@codinghorror](https://meta.discourse.org/u/codinghorror)
#### Post date: [2020年十一月28日 06:27 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/4 "2020-11-28T06:27:18Z")

</div>

> [@Falco](#):
>
> `redis_io_threads`

默认值是多少？是 1 吗？

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [2020年十一月28日 12:45 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/5 "2020-11-28T12:45:17Z")

</div>

是的。它来自 Redis 自身的配置文件，其中 1 表示单线程，如同旧版本一样。

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2020年十二月1日 20:30 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/6 "2020-12-01T20:30:57Z")

</div>

我遇到了一个情况，我添加了以下内容：

```plaintext
after_redis:
  - replace:
      filename: "/etc/redis/redis.conf"
      from: /^databases.*/
      to: "databases 50"

```

但重建失败，原因是：

```plaintext
25:M 01 Dec 2020 20:21:08.830 # FATAL: Data file was created with a Redis server configured to handle
 more than 16 databases. Exiting

```

是否有其他钩子可以在它尝试迁移或执行其他操作之前更新数据库数量？

嗯。现在在看似重建失败后，我在 Docker 日志中看到了以下内容：

```plaintext
chgrp: invalid group: ‘syslog’

```

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [2020年十二月1日 20:34 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/7 "2020-12-01T20:34:15Z")

</div>

为什么需要不止一个数据库？

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2020年十二月1日 20:53 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/8 "2020-12-01T20:53:49Z")

</div>

多站点。多个实例共用一个 Redis。我本应使用更通用的 Redis 容器，但决定还是沿用您的方案。

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [2020年十二月1日 20:56 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/9 "2020-12-01T20:56:27Z")

</div>

🤨

多站点是否使用单个数据库和标准的 Redis 键名空间？据我所知，Redis 数据库只是一个薄层，而且我们有跨越其边界的命令，因此你不应该依赖这一点。

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [2020年十二月1日 20:59 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/10 "2020-12-01T20:59:30Z")

</div>

是的，多站点使用一个数据库。

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2020年十二月1日 21:00 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/11 "2020-12-01T21:00:37Z")

</div>

哦，那并不是多站点部署，而是在一台机器上运行多个实例，每个实例都需要独立的 Redis。我之所以将默认的 16 个数据库增加到 50 个，只是因为懒得严格管控哪些 Redis 数据库正在被使用。

所以，我是不是应该为每个实例运行一个独立的 Redis 容器呢？

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [2020年十二月1日 21:02 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/12 "2020-12-01T21:02:42Z")

</div>

> [@pfaffman](#):
>
> 所以我猜应该为每个实例运行一个独立的 Redis 容器？

是的，否则可能会出现实例间互相干扰的问题。

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2020年十二月1日 21:04 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/13 "2020-12-01T21:04:45Z")

</div>

哦，真糟糕。

好在我是在仅用于测试的服务器上发现的这个问题。

对于其他站点，我是该直接提供一个全新的 Redis 实例并丢弃已排队的任务，还是应该进行备份和恢复操作？

顺便提一下，过去一年多来，我并没有注意到任何交叉干扰的问题。🤷 而且，确实有方法可以设置数据库编号。

编辑：好消息是，我可以进入容器，编辑 `redis.conf` 并重启它，之后它就能正常工作了。

如果您知道如何将一个站点从 `DISCOURSE_REDIS_DB: 12`（位于一个 Redis 容器）迁移到另一个 Redis 容器，我很想听听您的建议。或者，也许根本不必在意那些排队的任务？

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [2020年十二月1日 21:43 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/14 "2020-12-01T21:43:55Z")

</div>

> [@pfaffman](#):
>
> 或者干脆别管计划任务了？

没错。Discourse 应该能够合理地在 Redis 清空后继续运行。虽然会丢失一些数据，但都不是关键内容。

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2020年十二月1日 21:48 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/15 "2020-12-01T21:48:49Z")

</div>

我原本也是这么想的，因为我不知道有任何方法可以让备份尝试恢复它（不过我还有很多不知道的地方）。看起来我可以像这样操作：[https://stackoverflow.com/questions/23222616/copy-all-keys-from-one-db-to-another-in-redis，我刚刚在测试中尝试过，似乎成功了，但调整我的](https://stackoverflow.com/questions/23222616/copy-all-keys-from-one-db-to-another-in-redis%EF%BC%8C%E6%88%91%E5%88%9A%E5%88%9A%E5%9C%A8%E6%B5%8B%E8%AF%95%E4%B8%AD%E5%B0%9D%E8%AF%95%E8%BF%87%EF%BC%8C%E4%BC%BC%E4%B9%8E%E6%88%90%E5%8A%9F%E4%BA%86%EF%BC%8C%E4%BD%86%E8%B0%83%E6%95%B4%E6%88%91%E7%9A%84) playbook 以直接创建一个新的 Redis 容器并使用它会更简单。

谢谢。

现在需要决定是将这些 Redis 实例运行在数据库服务器上还是 Web 服务器上……

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2020年十二月3日 18:30 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/16 "2020-12-03T18:30:16Z")

</div>

[quote=“sam, post:10, topic:171437, full:true”]  
是的，多站点使用 1 个数据库  
[/quote] 那么多站点配置中的 `db_id: 2` 指的是什么？

> [@sam](#):
>
> ```plaintext
> before_bundle_exec:
> - file:
> path: $home/config/multisite.yml
> contents: |
> secondsite:
> adapter: postgresql
> database: b_discourse
> pool: 25
> timeout: 5000
> db_id: 2
> host_names:
> - b.discourse.example.com
> 
> ```

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [2020年十二月3日 18:34 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/17 "2020-12-03T18:34:03Z")

</div>

> [@pfaffman](#):
>
> 那么多站点配置中的 `db_id: 2` 指的是什么？

这是一个已弃用的设置：

> <https://github.com/discourse/rails_multisite/commit/2bb4d5170cbf462708eb32bb85c035fb1700f7b4>
>
> remove db\_id

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2020年十二月3日 18:35 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/18 "2020-12-03T18:35:44Z")

</div>

哈哈，是的，确实很令人困惑！

谢谢。我正在撰写一篇关于“在无外部反向代理的情况下使用 Let’s Encrypt 配置多站点”的主题，届时我也会顺便清理另一篇帖子。

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [2020年十二月3日 19:19 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/19 "2020-12-03T19:19:34Z")

</div>

> [@pfaffman](#):
>
> 丢弃已排定的任务？

只需确保在操作后立即重启 Unicorn，这样它便会重新创建排定任务。  
您会丢失所有已排队的任务，因此需要选择一个合适的时机来执行此操作。

---

<div class="post-metadata">

### Author: ![Ed\_S](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ed_s/32/134015_2.png) [@Ed\_S](https://meta.discourse.org/u/Ed_S)
#### Post date: [2021年七月27日 19:30 UTC](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437/20 "2021-07-27T19:30:51Z")

</div>

> [@Falco](#):
>
> ……我们最近发现 _压缩后_ 的镜像大小超过了 1GB，这有点太大了。
> 
> 因此……我们将 Discourse 的源代码从镜像内部移到了“浅克隆”中，仅包含最新版本的代码。
> 
> 这一改动使压缩后的镜像大小减少了 25%……同时也有助于控制镜像随时间增长的问题。

这是否仍按预期工作？是否有一个简单的单行命令可以查看压缩后镜像的大小？

[下一頁](https://meta.discourse.org/t/docker-image-update-redis-6-and-25-smaller-image-size/171437.md?page=2)
