【问题标题】:Self-contained Docker image with Laravel app (no shared volume)带有 Laravel 应用程序的自包含 Docker 映像(无共享卷)
【发布时间】:2020-07-14 05:24:44
【问题描述】:

网络上至少有十几个关于如何使用 Docker 设置 Laravel 应用程序的教程。他们都使用的基本设置是 3 个 Docker 容器:

  • nginx 容器
  • php-fpm 容器
  • mysql 容器

Nginx 和 PHP-fpm 容器依赖于共享卷。 HTTP 请求进入 Nginx 以获取共享卷上的文件。 Nginx 将请求交给 PHP-fpm。 Php-fpm 还可以访问共享卷中的文件,因此它可以运行脚本。

对于开发来说,这太棒了。我可以编辑共享卷中的文件并立即测试更改。但我质疑我是否希望将其用于生产。我真的希望我的任何代码都在运行 Docker 的服务器上吗?这似乎首先破坏了 Dockerising 的一些目的。似乎我希望代码在运行 nginx 和 PHP-fpm 的 Docker 容器中自包含(数据库可以是托管环境中的单独容器或服务)。

我的想法在这里正确吗?在 Docker 中部署 Laravel 进行生产的最佳实践是什么?

【问题讨论】:

    标签: php laravel docker nginx


    【解决方案1】:

    您在这里遗漏了一个非常重要的事实:在生产服务器上,卷不应该是bind mounts,它们主要是"normal" volumes,它们的目的之一确实是能够在容器之间共享数据。

    卷是保存 Docker 容器生成和使用的数据的首选机制。虽然bind mounts 依赖于主机的目录结构和操作系统,但卷完全由 Docker 管理。与绑定挂载相比,卷有几个优点:

    • 卷比绑定挂载更容易备份或迁移。
    • 您可以使用 Docker CLI 命令或 Docker API 管理卷。
    • 卷可在 Linux 和 Windows 容器上运行。
    • 可以在多个容器之间更安全地共享卷。
    • 卷驱动程序可让您将卷存储在远程主机或云提供商上、加密卷的内容或添加其他 功能。
    • 新卷的内容可以由容器预先填充。
    • Docker Desktop 上的卷比来自 Mac 和 Windows 主机的绑定挂载具有更高的性能。

    此外,卷通常是比在容器的可写层中持久化数据更好的选择,因为卷不会增加使用它的容器的大小,并且卷的内容存在于给定容器的生命周期之外.

    如果您的容器生成非持久状态数据,请考虑使用 tmpfs 挂载以避免将数据永久存储在任何地方,并通过避免写入容器的可写层来提高容器的性能。

    卷使用 rprivate 绑定传播,并且绑定传播不可为卷配置。

    来源:https://docs.docker.com/storage/volumes/,重点,我的

    因此,正如您在此处所看到的,即使 Docker 的文献也建议卷不要将一些特定的持久数据案例捆绑在容器本身中。

    拥有一个捆绑 NGINX 和 PHP 的容器也会破坏容器化的想法:

    通常建议您通过每个容器使用一项服务来区分关注区域。该服务可能会分叉成多个进程(例如,Apache Web 服务器启动多个工作进程)。拥有多个进程是可以的,但要从 Docker 中获得最大收益,请避免一个容器负责整个应用程序的多个方面。您可以使用用户定义的网络和共享卷连接多个容器。

    来源:https://docs.docker.com/config/containers/multi-service_container/

    每个容器应该只有一个关注点。将应用程序解耦到多个容器中,可以更轻松地水平扩展和重用容器。例如,一个 Web 应用程序堆栈可能由三个独立的容器组成,每个容器都有自己独特的图像,以解耦的方式管理 Web 应用程序、数据库和内存缓存。

    将每个容器限制在一个进程中是一个很好的经验法则,但这并不是一个硬性规定。例如,不仅容器可以是spawned with an init process,一些程序可能会自行产生额外的进程。例如,Celery 可以生成多个工作进程,Apache 可以为每个请求创建一个进程。

    利用您的最佳判断力,尽可能保持容器清洁和模块化。如果容器相互依赖,可以使用Docker container networks保证这些容器可以通信。

    来源:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#decouple-applications


    在您的特定用例中,捆绑 NGINX + PHP-FPM 容器会破坏您可能希望独立于 PHP-FPM 扩展 NGINX 的事实,例如,如果您在 NGNIX 级别上进行反向代理缓存,你很快就会需要比 PHP 容器更多的 NGINX 容器副本。

    因此,将它们分开将有利于您的水平扩展需求,并且更接近应用程序容器化的原则。

    在这种情况下我会问自己的一个问题是:

    如果我要将这些进程捆绑在一个容器中,那么我是否需要在此容器中启动任何类型的进程控制系统,例如 supervisor

    如果这个问题的答案是,那么我肯定会问自己,我是否没有违背我的应用程序容器化的目的。


    相关问题:

    【讨论】:

      猜你喜欢
      • 2018-05-31
      • 2021-06-12
      • 2019-05-25
      • 1970-01-01
      • 1970-01-01
      • 2020-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多