marek
(marek)
1
大家好。我在 Docker 中全新部署了 Discourse。
问题是:容器重建后,容器已启动,我可以访问应用页面,但收到 502 错误响应。查看日志或在容器内尝试执行 rails c 时,只看到以下错误:
`permission_error’: bootsnap 没有权限在 ‘tmp/cache/bootsnap/compile-cache’ 中写入缓存条目(或者,可能性较小的是,没有权限读取 ‘/usr/local/lib/ruby/2.7.0/set.rb’)(Bootsnap::CompileCache::PermissionError)
为了解决这个问题,我必须在容器内手动执行 chown -R discourse:discourse /var/www/discourse/tmp(准确说是 /var/www/discourse/tmp/cache/bootsnap 目录),之后应用即可正常运行,甚至无需重启。每次重建后都手动执行这一操作非常烦人。
我考虑过在 app.yml 的 custom commands 部分添加上述 chown -R discourse:discourse /var/www/discourse/tmp 命令,但不幸的是这不起作用。命令似乎确实被执行了(我试过用 mkdir 测试),但文件权限并未受到影响。
问题可能出在哪里?该如何解决?是否有正确修改文件权限的方法?
pfaffman
(Jay Pfaffman)
2
这有点奇怪。您是否按照 Discourse 官方标准安装 进行操作?
sam
(Sam Saffron)
4
你能粘贴一下你的 container.yml 文件吗(请隐去密码)?
marek
(marek)
5
好的,这是您需要的文件:
## 这是 Discourse 的独立 Docker 容器一体化模板
##
## 修改此文件后,您必须重新构建
## /var/discourse/launcher rebuild app
##
## 编辑时请*非常*小心!
## YAML 文件对空白字符或缩进的错误极其敏感!
## 如有需要,请访问 http://www.yamllint.com/ 验证此文件
templates:
- "templates/postgres.template.yml"
- "templates/redis.template.yml"
- "templates/web.template.yml"
- "templates/web.ratelimited.template.yml"
## 如果您想添加 Lets Encrypt (https),请取消注释以下两行
- "templates/web.ssl.template.yml"
#- "templates/web.letsencrypt.ssl.template.yml"
## 此容器应暴露哪些 TCP/IP 端口?
## 如果您希望 Discourse 与另一个 Web 服务器(如 Apache 或 nginx)共享端口,
## 请参阅 https://meta.discourse.org/t/17247 了解详情
expose:
- "80:80" # http
- "443:443" # https
params:
db_default_text_search_config: "pg_catalog.english"
## 将 db_shared_buffers 设置为总内存的最大 25%。
## 将根据检测到的 RAM 由 bootstrap 自动设置,您也可以覆盖
#db_shared_buffers: "256MB"
## 可以提高排序性能,但会增加每个连接的内存使用量
#db_work_mem: "40MB"
## 此容器应使用哪个 Git 修订版?(默认:tests-passed)
#version: tests-passed
env:
LC_ALL: en_US.UTF-8
LANG: en_US.UTF-8
LANGUAGE: en_US.UTF-8
# DISCOURSE_DEFAULT_LOCALE: en
## 支持多少个并发 Web 请求?取决于内存和 CPU 核心数。
## 将根据检测到的 CPU 由 bootstrap 自动设置,您也可以覆盖
#UNICORN_WORKERS: 3
## TODO: 此 Discourse 实例将响应的域名
## 必填项。Discourse 无法在纯 IP 地址上运行。
DISCOURSE_HOSTNAME: 'example.com'
## 如果您希望容器以与上述指定的相同主机名(-h 选项)启动,请取消注释
## (默认值为 "$hostname-$config")
#DOCKER_USE_HOSTNAME: true
## TODO: 初始注册时将被设为管理员和开发者的逗号分隔的电子邮件列表
## 示例 'user1@example.com,user2@example.com'
DISCOURSE_DEVELOPER_EMAILS: 'test@mail.com'
## TODO: 用于验证新账户和发送通知的 SMTP 邮件服务器
# SMTP 地址、用户名和密码是必填项
# 警告:SMTP 密码中的字符 '#' 可能会导致问题!
DISCOURSE_SMTP_ADDRESS: smtp.mail.io
#DISCOURSE_SMTP_PORT: 587
DISCOURSE_SMTP_USER_NAME: 111
DISCOURSE_SMTP_PASSWORD: 111
#DISCOURSE_SMTP_ENABLE_START_TLS: true # (可选,默认为 true)
#DISCOURSE_SMTP_DOMAIN: discourse.example.com # (某些提供商要求)
#DISCOURSE_NOTIFICATION_EMAIL: noreply@discourse.example.com # (发送通知的地址)
## 如果您添加了 Lets Encrypt 模板,请取消注释以下行以获取免费 SSL 证书
#LETSENCRYPT_ACCOUNT_EMAIL: me@example.com
## 此 Discourse 实例的 http 或 https CDN 地址(配置为拉取)
## 请参阅 https://meta.discourse.org/t/14857 了解详情
#DISCOURSE_CDN_URL: https://discourse-cdn.example.com
## Maxmind 地理位置 IP 地址查询的授权密钥
## 请参阅 https://meta.discourse.org/t/-/137387/23 了解详情
#DISCOURSE_MAXMIND_LICENSE_KEY: 1234567890123456
## Docker 容器是无状态的;所有数据都存储在 /shared 中
volumes:
- volume:
host: /var/discourse/shared/standalone
guest: /shared
- volume:
host: /var/discourse/shared/standalone/log/var-log
guest: /var/log
## 插件放在这里
## 请参阅 https://meta.discourse.org/t/19157 了解详情
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://github.com/discourse/docker_manager.git
## 构建后运行的任何自定义命令
run:
- exec: echo "开始自定义命令"
## 如果您想设置首次注册的“发件人”电子邮件地址,请取消注释并修改:
## 收到首次注册邮件后,请重新注释该行。它只需运行一次。
#- exec: rails r "SiteSetting.notification_email='info@unconfigured.discourse.org'"
#- exec: chown -R discourse:discourse /var/www/discourse/tmp/cache/bootsnap # 我尝试修复文件权限的示例命令
- exec: echo "结束自定义命令"
pfaffman
(Jay Pfaffman)
6
你没运行 discourse-setup 吧?它本应定义一些你已注释掉的内容。我刚做了这些修改,想确认一下是否按预期工作。
你不用 Let’s Encrypt 是有什么原因吗?
不过,我还没看到对你问题的解释。
marek
(marek)
7
首先,应用程序是使用 discourse-setup 构建的。在尝试了几次重建但未看到任何积极结果后,我转向了 /samples 目录中的一个预定义的 .yml 配置文件,然后简单地用我的凭据对其进行了编辑。
为什么不使用 Let’s Encrypt?有人建议使用客户端证书。但据我理解,证书与此无关,因为它们有效且不会引发任何问题。
问题似乎出在项目层面,具体与 bootsnap 缓存文件的权限有关(也许问题出在 Bootsnap 本身)。
pfaffman
(Jay Pfaffman)
8
谢谢。我同意这不太可能是问题所在。我昨天做了几次安装,都运行正常。我没看到能解释你遇到问题的原因。
tebanep
(Esteban Echeverry)
9
我们遇到了同样的问题,我确认在 Docker 容器内执行以下命令:
chown -R discourse:discourse /var/www/discourse/tmp
即可解决问题!无需重启。在更改所有者之前,‘tmp’ 目录的权限被分配给了 ‘discourse:www-data’。希望未来能修复此问题,这样每次重建后就不需要手动执行此操作了。
tebanep
(Esteban Echeverry)
11
是的 @pfaffman,我就是。这是问题所在吗?
gerhard
(Gerhard Schlager)
12
我不这么认为。我总是以 root 身份启动自托管实例,从未遇到过类似问题。
如果你不使用 chown,目录的所有者是谁?在一个最近重建的容器中,情况如下:
# ls -l /var/www/discourse/tmp
total 36
lrwxrwxrwx 1 root root 19 Mar 2 14:56 backups -> /shared/tmp/backups
drwxr-xr-x 1 discourse discourse 4096 Mar 2 14:57 cache
drwxr-xr-x 1 discourse discourse 4096 Mar 2 14:57 ember-rails
drwxr-xr-x 1 discourse root 4096 Mar 2 15:04 pids
lrwxrwxrwx 1 root root 20 Mar 2 14:56 restores -> /shared/tmp/restores
drwxr-xr-x 2 discourse root 4096 Mar 2 14:56 sockets
drwxr-xr-x 2 discourse discourse 12288 Mar 2 15:02 stylesheet-cache
除了克隆插件外,你是否在 app.yml 中添加了任何自定义命令或钩子?
tebanep
(Esteban Echeverry)
13
启动容器后,/var/www/discourse/tmp 目录的所有者用户和组为 discourse:www-data。将其重新分配为 discourse:discourse 后,问题得以解决。此前我从未遇到过这种情况,而且我已经使用 Discourse 好几个月了。不过,修复起来很简单,可能是偶然现象,所以我不想再为此打扰大家了。非常感谢 @gerhard!