【问题标题】:Docker best practices: single process for a containerDocker 最佳实践:容器的单个进程
【发布时间】:2015-12-11 15:41:36
【问题描述】:

Docker best practices 指南指出:

"...您应该只在单个容器中运行单个进程..."

Nginx 和 PHP-FPM 应该在不同的容器中运行吗?或者这是否意味着微服务架构只在容器中运行一个服务或“应用程序”?

将这些服务放在一个容器中似乎更易于部署和维护。

【问题讨论】:

  • 我最近开始使用 Docker 并遇到了相同的查询。我最终为每个容器提供了单独的容器。不过,我很想在这里了解为什么这是“最佳实践”。
  • @DavidT 因为它允许您在 docker 组合/配置级别扩展服务,而无需修改服务本身的配置。

标签: php nginx docker virtual-machine dockerfile


【解决方案1】:

根据用例,您可以在单个容器中运行多个进程,但我不建议这样做。

从某种意义上说,在不同的容器中运行它们甚至更简单。保持容器小、无状态且围绕单个作业可以更容易地维护它们。让我告诉你我的容器工作流程是如何处于类似情况的。

所以:

  1. 我有一个带有 nginx 的容器,该容器暴露于外部世界 (:443, :80)。在此级别,可以直接管理配置、tls 证书、负载平衡器选项等。
  2. 一个(或多个)装有应用程序的容器。在这种情况下,带有应用程序的 php-fpm 容器。 Docker 镜像是无状态的,容器挂载和共享静态文件的卷等等。此时,您可以随时销毁并重新创建应用程序容器,保持负载均衡器正常运行。此外,您可以在同一个代理 (nginx) 后面拥有多个应用程序,管理其中一个不会影响其他应用。
  3. 一个或多个数据库容器...同样的好处也适用。
  4. Redis、Memcache 等

具有这种结构,部署是模块化的,因此每个“服务”都是分离的,并且在逻辑上独立于系统的其余部分。

作为副作用,在这种特殊情况下,您可以对应用程序进行零停机时间部署(更新)。这背后的想法很简单。当您必须进行更新时,您使用更新的应用程序创建一个 docker 映像,运行容器,运行所有测试和维护脚本,如果一切顺利,您将新创建的容器添加到链中(负载均衡器),然后轻轻地杀了老一。就是这样,您拥有更新的应用程序,而用户根本没有注意到它。

【讨论】:

  • 回答得很好。我喜欢 nginx 转发代理背后的多个应用程序实例的想法。虽然如果我运行说两个应用程序(4x 实例)我如何交叉配置 nginx.conf 文件?是否可以将配置从 PHP-APP-1 和 PHP-APP-2 传递到 nginx 容器中?
  • 就个人而言,我明确定义了 nginx 的配置(这是明确执行此操作的内部策略)。首先,我不会为每个应用程序更改 nginx.conf,但我在 /etc/nginx/sites-enabled 目录中为每个应用程序都有单独的配置文件,该目录包含在 nginx.conf 中。您可以即兴创作并从容器中获取配置文件。 ;)
【解决方案2】:

这意味着 Linux/Unix 意义上的进程。也就是说,没有什么能阻止你在一个容器中运行多个进程,这不是推荐的范例。

【讨论】:

    【解决方案3】:

    我们发现我们可以使用Supervisord 运行多个服务。它使架构变得非常简单,只需要你有一个额外的 supervisor.conf 文件。例如:

    supervisord.conf

    [supervisord]
    nodaemon=true
    
    [program:apache2]
    command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2 -DFOREGROUND"
    
    [program:udpparser]
    command=bin/bash -c "exec /usr/bin/php -f /home/www-server/services/udp_parser.php"
    

    来自 Dockerfile:

    FROM ubuntu:14.04
    
    RUN apt-get update
    RUN apt-get install -y apache2 supervisor php5 php5-mysql php5-cli
    
    RUN mkdir -p /var/lock/apache2 /var/run/apache2 /var/log/supervisor
    
    RUN a2enmod rewrite
    RUN a2enmod ssl
    
    COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
    
    ADD 000-default.conf /etc/apache2/sites-enabled/
    ADD default-ssl.conf /etc/apache2/sites-enabled/
    ADD apache2.conf /etc/apache2/
    ADD www-server/ /home/www-server/
    
    EXPOSE 80 443 30089
    
    CMD ["/usr/bin/supervisord"]
    

    作为最佳实践,我们仅在服务从一起运行中受益而所有其他容器都是独立微服务的情况下才这样做。

    【讨论】:

    • 虽然这意味着您可以只使用一个CMD 运行多个进程,但实际上您仍然有多个进程在同一个容器中运行。那么这不违背最佳实践,还是我误解了?甚至Docker 也建议这样做。声明“在这个例子中,我们将使用进程管理工具Supervisor来管理 多个进程 在我们的容器。” - 令人困惑!
    • 在某一点上的“最佳实践”是一个选择问题。我不会在 any 容器中管理三个以上的进程,我会研究为什么我们需要密切关注。这很令人困惑(很多 Docker 都可能是这样),但在与 Docker 人员的讨论中,我发现他们支持使用 Supervisor 在有意义的情况下将多个进程放在一个容器中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-07
    • 1970-01-01
    • 2023-02-05
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 2019-02-18
    相关资源
    最近更新 更多