Docker多容器部署LNMP环境

作者: dodos | 来源:发表于2016-11-08 20:55 被阅读12881次
    Docker

    使用单一进程容器,即一个容器只运行一种服务,而不是把所有服务放在一个容器的设计,让PHP项目需要的Nginx、PHP、MySQL组件,分别运行在各自镜像创建出来的独立容器中。

    文章提到的完整脚本请移步docker-lnmp,内辅详细的注释(欢迎大家关注!)。

    整个流程:
    • 客户端http请求服务器80端口,该端口被映射到Nginx容器80端口,进入Nginx处理。
    • Nginx分析请求,如果是静态资源,直接服务器读取内容;如果是PHP脚本,通过PHP容器调用服务器获取脚本,然后FastCGI处理。
    • FastCGI解析PHP脚本,必要时访问MySQL容器读写数据。
    具体步骤
    Dockerfile:
    • MySQL镜像
      继承自官方的MySQL5.7镜像,相对独立解耦的模块,无其它额外处理,见mysql/Dockerfile
    • PHP镜像
      继承自官方的centos7镜像,PHP源码按需编译安装,方便后续扩展管理或者配置。通过sed修改php.in监听所有9000端口(此处为关键!!因为提供Nignx容器访问支持PHP脚本,PHP容器对于Nginx容器不是localhost),完整见php7/Dockerfile
    • Nginx镜像
      继承自官方的centos7镜像,Nginx源码按需编译安装,方便后续更改或者配置。通过sed修改nginx.conf增加对PHP脚本的支持,完整见nginx/Dockerfile
    构建镜像:
    docker build --tag addcn/mysql -f mysql/Dockerfile .
    docker build --tag addcn/php7 -f php7/Dockerfile .
    docker build --tag addcn/nginx -f nginx/Dockerfile .
    
    启动容器:

    整个流程可以看到,Nginx、PHP、MySQL三者的关系:
    Nginx容器---->PHP容器,PHP容器---->MySQL容器。即容器之间是有关联的,两两容器的数据通信通过容器启动命令docker run加参数--link解决。

    docker run --name mysql -p 3306:3306 -v /root/bo/data/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -it addcn/mysql
    docker run --name php7 -p 9000:9000 -v /var/www/html:/usr/local/nginx/html --link mysql:mysql -it addcn/php7
    docker run --name nginx -p 80:80 -v /var/www/html:/usr/local/nginx/html --link php7:php7 -it addcn/nginx
    
    测试 PHP & MySQL:

    vi /var/www/html/test.php

    <?php
    //date
    echo date("Y-m-d H:i:s")."<br />\\n";
    
    //mysql
    try {
        $conn = new PDO('mysql:host=mysql;port=3306;dbname=mysql;charset=utf8', 'root', '123456');
    } catch (PDOException $e) {
        echo 'Connection failed: ' . $e->getMessage();
    }
    //$conn->exec('set names utf8');
    $sql = "SELECT * FROM `user` WHERE 1";
    $result = $conn->query($sql);
    while($rows = $result->fetch(PDO::FETCH_ASSOC)) {
        echo $rows['Host'] . ' ' . $rows['User']."<br />\\n";
    }
    
    //phpinfo
    phpinfo();
    ?>
    

    客户端浏览:
    http://192.168.8.36/test.php
    ![Docker运行PHP及输出MySQL表][1]
    [1]: https://raw.githubusercontent.com/addcn/docker-lnmp/master/docs/docker-lnmp.png

    Q&A
    • Nginx如何支持PHP脚本?
      Nginx容器启动时候,通过--link php7:php7参数共享PHP容器的网络,配置nginx.conf文件(见nginx/Dockerfile),当处理PHP脚本时,转给PHP容器解析:
    location ~ \\.php$ {
        root           html;
        fastcgi_pass   php7:9000;  #此处为关键!!其中php7为PHP容器的名称,见启动PHP容器docker run --name指定的值
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /usr/local/nginx/html$fastcgi_script_name; #关键!!/usr/local/nginx/html为web目录
        include        fastcgi_params;
    }
    
    • PHP如何读取MySQL数据?
      PHP容器启动时候,通过--link mysql:mysql参数,与MySQL容器共享网络,类似两者处于同一台机器,因此PHP代码连接的时候使用$conn = new PDO('mysql:host=mysql;port=3306;dbname=mysql;charset=utf8', 'root', '123456');就可以连接上MySQL(其中host=mysqlmysql为MySQL容器的名称,见启动MySQL容器docker run --name指定的值)。
    下一步?
    • 单一容器部署LNMP
    • Docker Compose使用
    • PHP/MySQL/Nginx日志及配置文件挂载出容器外面
    • 容器集群的自动化部署扩容及运维开源平台kubernetes了解

    相关文章

      网友评论

      • 淡o_O悠悠:分享一下遇到的问题:构建PHP镜像的时候遇到了cc: internal compiler error: Killed (program cc1) 这个错误,原因是内存不足,具体解决办法大家可以百度
      • 3e16a17db040:项目源码就放在宿主机是吧
        如果是在阿里云的容器服务上部署,项目源码放哪呢?每个项目都在独立的容器里跑?
        dodos:@蝎子x2 服务集群,源码只要一份在宿主机供各节点读写就好
        3e16a17db040:@dodos 集群模式怎么搞,每个节点都放一份源码?好像怪怪的
        dodos:@蝎子x2 源码放宿主机,即阿里云的机器上
      • yeszao:一键部署的话,用《Docker搭建可一键部署的多域名LNMP环境》https://www.awaimai.com/2120.html
        细节解释得也很清楚
      • 茶艺瑶:为什么 404
        yeszao:没文件
      • 茶艺瑶:怎么在 php 中安装扩展
        dodos:PHP镜像继承自官方的centos7,进入系统普通linux正常安装就好
      • RainingMan:很不错。问一个问题,mysql的镜像没有继承centos7的语句,是因为这个镜像打包的时候已经继承了吗?(我是认为这些服务一定要继承于一个linux发行版才能运行)
      • 星与梦:不错 讲得非常好
      • d9a7ec101c63:非常棒,
      • 咬咬鱼:docker run --name php7 -p 9000:9000 -v /var/www/html:/usr/local/nginx/html --link mysql:mysql -it addcn/php7
        中的 -p 9000:9000 好像不是必须的。
      • 旭积博发:按照文中操作,虽然遇到了不少问题,但是最终还是成功的搭建并运行起来了。感谢。
        dodos:@Azon 您的反馈(评论)是我最大的鼓励!
      • fec06fab892e:很有用
        dodos:@豆逗磊 希望可以帮助到大家
      • Kaiyulee:线上部署的的时候建议单一服务单一容器, 开发环境随便折腾, 为了方便分发给队友使用,我是弄到了一个容器里面。
        Kaiyulee:@dodos :grin:
        dodos:@小强点中国 github里面centos目录就是准备做一个容器,//TODO :smile:

      本文标题:Docker多容器部署LNMP环境

      本文链接:https://www.haomeiwen.com/subject/xlczuttx.html