Rails 宿主机中的 nginx 怎么访问 docker 容器中的 public assets 文件?

qichunren · 2022年04月14日 · 最后由 huacnlee 回复于 2022年04月18日 · 905 次阅读

我目前正在切换到 docker 部署方案。nginx 是原来就已经安装在服务器的主机环境中,通过将 docker 容器中的 puma 的端口暴露在主机中,可以实现 Rails 程序跑起来。但是静态文件这部分,public/目录怎么让 nginx 能访问到呢?

我看到 homeland 是由于就一个 Rails 应用,它是直接在 Rails 应用的容器中安装了 nginx,这样就可以直接访问到同一个容器中的文件。但是我这个服务器,由于有多个网站在运行,我后续打算将每一个 Rails 应用都采用 docker 容器来运行,它们共用一个 nginx 服务(后面有可能采主机的 nginx 或者是 docker 容器的 nginx 服务)。

所以 nginx 怎么样可以访问每个容器中 Rails 应用的 public 目录呢,以便配置/assets等静态资源 url?

-v 把宿主机文件夹与容器的文件夹做个映射?

spike76 回复

我在 docker-compose.yml 中配置了:

volumes:
  - ./data/public:/home/app/ntwebsite/public

docker-compose run app 后,然后发现主机中这个 data/public 目录是空的了。然后我在主机的 data/public 创建一个文件,通过 docker exec 进入到 container 中的 public 目录查看,发现有刚才创建的文件,public 目录中本来存在的文件都没有了。

qichunren 回复

是有这个问题,挂载时的内容会以宿主机为准,若挂载时宿主机的/data/public 是空的,那么/home/app/ntwebsite/public 也是空的。之后在容器中从新编译静态文件到 public 目录,就能在宿主机看到文件了

spike76 回复

之后在容器中从新编译静态文件到 public 目录,就能在宿主机看到文件了

这样太麻烦了啊。有其它办法吗?

怎么样让这个关系反过来呢?我挂载时宿主机故意不存在/data/public 这个目录都解决不了问题。

Rei 回复

你的意思是在 Rails 应用开启服务静态文件的功能,

# Disable serving static files from the `/public` folder by default since
 # Apache or NGINX already handles this.
  config.public_file_server.enabled = true

然后通过配置你提示的这个Reverse Proxy with Caching 来曲线解决问题?

qichunren 回复

是的。生产环境均衡负载用云服务的,静态文件用 CDN。nginx 也可以这么用。基于文件共享的方案不适合容器。

qichunren 回复

据我所知,不能把这个关系反过来。

Rei 回复

@Rei 好办法,👍 我先这样试试。以后再研究一下其它的。

考虑到在一个容器版本里, public 内容不会变的情况下,比较 tricky 的实现思路我想到两种:

  1. 在启动容器的时候调用 docker cp 指令将 public 复制到宿主机中。

  2. docker-compose.yml 使用 volumes: ,利用 docker 创建空的 named volume 时会自动复制对应 path 文件到宿主机 volume 的特性,通过 /var/lib/docker/volumes/{volume名称}/_data 访问 volume 数据。但是这要求更新镜像版本时删除这个 volume。

总的来说,比如 docker-compose 就没有原生对 pre script 的支持,坑多不好用就是了。

你说的第 2 个方法有文档或者关键字吗?没有看明白是怎么配置的。谢谢~ @xinyifly

发布的时候上传外部 CDN

需要 登录 后方可回复, 如果你还没有账号请 注册新账号