Docker 最佳实践:容器的单一进程
Docker best practices: single process for a container
Docker best practices 指南指出:
"...您应该只运行 单个容器中的单个进程..."
Nginx 和 PHP-FPM 运行 应该放在不同的容器中吗?或者这是否意味着微服务架构仅 运行 一项服务或 "app" 在一个容器中?
将这些服务放在一个容器中似乎更易于部署和维护。
这意味着 Linux/Unix 这个词意义上的过程。也就是说,没有什么可以阻止您 运行 在一个容器中使用多个进程,只是不推荐这种范例。
我们发现我们可以使用 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"]
作为最佳实践,我们仅在服务受益于运行而所有其他服务受益的情况下才这样做容器是独立的微服务。
根据使用情况,您 可以 运行 在一个容器中使用多个进程,但我不建议这样做。
从某种意义上说,将它们 运行 放在不同的容器中甚至更简单。使容器保持小型、无状态并围绕单个作业进行,可以更轻松地维护它们。让我告诉你我的容器工作流程是如何处于类似情况的。
所以:
- 我有一个带有 nginx 的容器,它暴露在外面的世界 (:443, :80)。在此级别,管理配置、tls 证书、负载平衡器选项等很简单。
- 一个(或多个)应用程序容器。在那种情况下,一个 php-fpm 容器与应用程序。 Docker 图像是无状态的,容器装载和共享静态文件的卷等等。此时,您可以随时销毁并重新创建应用程序容器,保持负载均衡器正常运行 运行ning。此外,您可以在同一个代理 (nginx) 后拥有多个应用程序,管理其中一个不会影响其他应用程序。
- 数据库的一个或多个容器...同样适用。
- Redis、Memcache 等
具有这种结构,部署是模块化的,因此每个 "service" 都是分离的,并且在逻辑上独立于系统的其余部分。
作为副作用,在这种特殊情况下,您可以对应用程序进行零停机部署(更新)。这背后的想法很简单。当您必须进行更新时,您可以使用更新后的应用程序、运行 容器、运行 所有测试和维护脚本创建一个 docker 映像,如果一切顺利,您可以添加新创建的容器到链(负载均衡器),并轻轻杀死旧容器。就是这样,您拥有更新的应用程序,而用户根本没有注意到它。
Docker best practices 指南指出:
"...您应该只运行 单个容器中的单个进程..."
Nginx 和 PHP-FPM 运行 应该放在不同的容器中吗?或者这是否意味着微服务架构仅 运行 一项服务或 "app" 在一个容器中?
将这些服务放在一个容器中似乎更易于部署和维护。
这意味着 Linux/Unix 这个词意义上的过程。也就是说,没有什么可以阻止您 运行 在一个容器中使用多个进程,只是不推荐这种范例。
我们发现我们可以使用 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"]
作为最佳实践,我们仅在服务受益于运行而所有其他服务受益的情况下才这样做容器是独立的微服务。
根据使用情况,您 可以 运行 在一个容器中使用多个进程,但我不建议这样做。
从某种意义上说,将它们 运行 放在不同的容器中甚至更简单。使容器保持小型、无状态并围绕单个作业进行,可以更轻松地维护它们。让我告诉你我的容器工作流程是如何处于类似情况的。
所以:
- 我有一个带有 nginx 的容器,它暴露在外面的世界 (:443, :80)。在此级别,管理配置、tls 证书、负载平衡器选项等很简单。
- 一个(或多个)应用程序容器。在那种情况下,一个 php-fpm 容器与应用程序。 Docker 图像是无状态的,容器装载和共享静态文件的卷等等。此时,您可以随时销毁并重新创建应用程序容器,保持负载均衡器正常运行 运行ning。此外,您可以在同一个代理 (nginx) 后拥有多个应用程序,管理其中一个不会影响其他应用程序。
- 数据库的一个或多个容器...同样适用。
- Redis、Memcache 等
具有这种结构,部署是模块化的,因此每个 "service" 都是分离的,并且在逻辑上独立于系统的其余部分。
作为副作用,在这种特殊情况下,您可以对应用程序进行零停机部署(更新)。这背后的想法很简单。当您必须进行更新时,您可以使用更新后的应用程序、运行 容器、运行 所有测试和维护脚本创建一个 docker 映像,如果一切顺利,您可以添加新创建的容器到链(负载均衡器),并轻轻杀死旧容器。就是这样,您拥有更新的应用程序,而用户根本没有注意到它。