使用Docker部署PHP应用的设计方案

1. Docker

Docker的官方定义是:

Docker allows you to package an application with all of its dependencies into a standardized unit for software development.

-- https://www.docker.com/whatisdocker

毫无疑问的是,Docker解决了应用部署上一个巨大的问题:

客户: 安装好了,用不了。

发布者:我的机器上没问题。

如何解决每个应用的依赖在Docker出现之前是个头疼的问题,现在仅仅通过一次配置,Dockerfile或者image作为最终交付,就能在任何Linux上完美运行了。说起来很简单的样子,但在Docker配置过程中,又存在很多值得思考的问题:应用各个组件如何安排?一个Container解决问题还是细化Container?Container之间何如通信?等等。。下面用一个最普遍的WEB应用配置部署来说明这些问题。

NOTE:本文假定读者对Docker中的一些概念有基本的认识,如果不甚了解,我推荐这篇文章:

https://linux.cn/article-6074-weibo.html

2. LNMP

典型的PHP应用配置方案是LAMP或者LNMP,本文以LNMP为例。

设计方案如下图(我已经实现并运行成功的案例):

应用由4个组件组成,分别是Nginx,PHP-FPM(PHP),MySQL以及WWW,4个组件运行在由各自镜像创建出来的独立的容器中。其中WWW Container只是一个存储业务代码和静态资源的容器,可以认为是"死"的。

事实上LNMP架构采用上面的设计方式应该是最容易想到的,也是最清晰的,每个组件有相对的独立性。其中除了WWW容器,其他3个容器都可以直接通过官方镜像构建出来。

然而网上很多同学并不是这样做的,不会分的这么细,通常是把Nginx和WWW放到一个容器内,或者干脆全部放到一个容器中。可以学习一下大家的Dockerfile:

https://github.com/search?utf8=?&q=docker-lnmp

细化Container这种设计的优缺点:

  1. 容器间的耦合性增大。可以看到PHP-FPM容器和另外三个容器间有耦合关系,MySQL容器最独立。
  2. 虽然耦合性比较大,但这种端口耦合,文件系统耦合关系可以通过增加几个运行选项解决掉,后面有介绍。
  3. 由于容器对整个架构的划分,使得容器中的内容变得十分独立和安全。例如,我希望在线上更新WWW中的代码,只需要进入WWW容器做修改,不会影响到Nginx,PHP-FPM或者是MySQL。
  4. 各容器可灵活拆卸更换,比如我想把MySQL换成Mongodb,或者干脆把业务代码搬个家,不会影响到其他容器(仅仅更改相关配置文件)
  5. 由于各容器经由官方的镜像创建,因此可以随时花最少的代价使用最新的官方镜像尝鲜。
  6. 占用空间会比较大,一个简单的应用要这么做的话,四个镜像会占用大量的存储空间。

2.1 容器间通信问题

细化Container面临着另一个问题,就是如何进行容器间通信。下面简要描述一下上图中的数据流程:

  1. 客户端的http请求达到server的80端口,该端口被映射到Nginx Container的80端口,因此进入Nginx处理。Nginx会分析请求资源,判定是静态资源还是php脚本,如果是静态资源,则直接从WWW中取出发回客户端;如果是脚本程序,则要告诉PHP-FPM到WWW获取相应脚本,然后通过php-cgi处理。
  2. fast-cgi通过php执行脚本,必要时访问MySQL存取数据。

这样耦合关系就出来了:

  1. Nginx需要连接PHP-FPM开放的9000端口,需要访问WWW中的文件系统。
  2. PHP-FPM也需要访问WWW中的文件系统,还要访问MySQL的3306端口。

2.2 解决问题

可以看出有两类耦合关系:端口和文件系统。

对于端口耦合,docker是通过--link选项解决的;对于文件系统耦合,docker是通过--volumes-from选项解决的。

解决第一个耦合关系:

$ sudo docker run -p 80:80 -p 443:443  # 主机端口映射到容器
--volume-from WWW_CONTAINER_NAME  # 把WWW容器VOLUME过的文件夹挂载到将启动的容器上
--link PHP_FPM_CONTAINER_NAME:fpmservice  # 冒号前是正在运行的FPM容器名称,后面是别名,别名会作为hostname在将启动的容器内可见
-d  # detach
NGINX_IMAGE  # 镜像名

解决第二个耦合关系:

$ sudo docker run --volume-from WWW_CONTAINER_NAME
--link MYSQL_CONTAINER_NAME:mysql
-d
PHP_FPM_IMAGE

参考文档:https://docs.docker.com/reference/run/

因此容器启动的先后顺序就出来了:

  1. MySQL Container
  2. WWW Container (由于没有任何服务运行,容器run后会立即exit,可以使用 tail -f 等block命令使容器保持运行不退出)
  3. PHP-FPM Container
  4. Nginx Container

其中1和2可以对换。

3. 总结

利用Docker部署Web应用可以带来很多便利,在宏观上实现应用组件化,为实现分布式系统奠定了基础。

可以看到实际上在Docker容器间共享数据是很方便的,搞清楚各容器的依赖关系就不难解决。

P.s. 本文是我学习docker两天后的心得体会,纰漏在所难免,如有错误还请斧正。

时间: 2024-11-05 04:52:14

使用Docker部署PHP应用的设计方案的相关文章

【Docker江湖】之docker部署与理解

转载请注明出处:http://blog.csdn.net/gamer_gyt 博主微博:http://weibo.com/234654758 Github:https://github.com/thinkgamer Docker江湖 [Docker江湖]之Docker部署与理解 [Docker江湖]之hub上镜像的使用,Dockerfile语法解读和数据管理 [Docker江湖]之创建带有SSH服务的镜像 写在前边的话 在之前便想学习Docker技术了,可是一直没有机会,近期在做elk的一个项目

Centos7 下面安装docker 部署Nginx

实验 环境 Centos 7 操作系统 安装docker yum install docker -y 查看docker 是否安装成功 docker -v Docker version 1.12.6, build 3a094bd/1.12.6 启动docker systemctl start docker 部署Nginx 获取基础镜像 docker pull nginx:1.10.3 查看 镜像 1.直接启动容器 docker run -d -p 8080:80 nginx:1.10.3 解释:

docker'部署

环境:ubuntu-14.04.4-server-amd64 1.更换阿里云源 备份源配置文件: $ sudo cp /etc/apt/sources.list /etc/apt/sources.list_backup $ sudo vim /etc/apt/sources.list 删除文件内容,更新为: deb http://mirrors.aliyun.com/ubuntu trusty main restricted deb-src http://mirrors.aliyun.com/u

docker部署tomcat乱码和系统时间不对处理

docker部署好程序后访问中文是乱码,(针对centos 6镜像) docker默认为POSIX 在Dockerfile 里添加 ENV         LANG         en_US.UTF-8 系统时间为UTC时间差8小时 在Dockerfile里添加 RUN     /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime RUN     /bin/echo -e "ZONE="Asia/Shanghai"

docker部署gitlab

由于docker部署gitlab比较方便,于是用docker部署gitlab,安装步骤如下: 我拿的虚拟机做的测试,系统是centos 7.1,我ip是192.168.12.234. docker安装以及基础知识这里就不说了 1. 下载gitlab镜像 docker pull gitlab/gitlab-ce 2. 运行gitlab实例 mkdir -pv /data/gitlab/{config,logs,data} GITLAB_HOME="/data/gitlab" docker

Docker学习笔记三:Docker部署Java web系统

Docker部署Java Web系统 1.在root目录下创建一个路径test/app mkdir test && cd test&& mkdir app &&cd app 2.将apache-tomcat-7.0.29.tar.gz及jdk-7u25-linux-x64.tar.gz拷贝 到app目录下 3.解压两个tar.gz文件 tar -zxvf apache-tomcat-7.0.29.tar.gz tar -zxvf jdk-7u25-linux

手把手教你用Docker部署一个MongoDB集群

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中最像关系数据库的.支持类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引.本文介绍了如何使用Docker搭建MongoDB集群. 本文我会向大家介绍如何使用Docker部署一个MongoDB集群,具体如下: 2.6.5版本的MongoDB 有3个节点的副本集(Replica set) 身份验证 持久化数据到本地文件系统 首先要准备三个运行的Docker服务器,这意味着你

基于VS2017的Docker Support体检ASP.NET Core站点的Docker部署

最近在学习如何用 Docker 部署生产环境中的 ASP.NET Core 站点,作为一个 Docer 新手,从何处下手更容易入门呢?一开始就手写 Docker 配置文件(Docfile, docker-compose.yml)容易让人产生挫败感,想到 Visual Studio 2017 对 Docker 的支持(Docker Support),也许借助它自动生成Docker配置文件.初步体验一下 Docker 部署是一个入门捷径,遂据此想法尝试了一下,感觉不错. 1. 启用 VS2017 的

转 docker 部署 kafka

原文链接 http://blog.csdn.net/snowcity1231/article/details/54946857 1.下载镜像 这里使用了wurstmeister/kafka和wurstmeister/zookeeper这两个版本的镜像 [html] view plain copy print? docker pull wurstmeister/zookeeper [html] view plain copy print? docker pull wurstmeister/kafk