LNMP是继LAMP之后的又一个非常流行的web框架,即Linux+Nginx+Mysql+PHP的网站架构方案。nginx相较于apache更轻量级,尤其是对静态页面的处理更有优势。做运维的朋友应该都知道一个流行的词汇——动静态分离,其中一个比较普遍的是使用nginx处理静态页面,而动态页面交由后端的apache或者tomcat处理。本文要讲的是通过Dockerfile构建LNMP环境镜像,分别把nginx、mysql和PHP部署在docker容器里,实现LNMP网站架构。
一、项目环境介绍
1、系统环境
操作系统版本:Centos 7.5 64位
Docker版本:18.06.1-ce(社区版)
Nginx版本:1.15.5
PHP版本:7.2.11
Mysql版本:8.0.12
ip地址:192.168.2.236
lnmp网络ip地址:172.18.0.1
2、源码包下载地址
nginx下载地址:http://nginx.org/download/nginx-1.15.5.tar.gz
php下载地址:http://cn2.php.net/get/php-7.2.11.tar.gz/from/this/mirror
mysql使用官方8.0.12镜像
3、目录结构
二、安装部署docker环境
docker环境的安装部署可以参考我的另一篇博文《Centos 7部署docker环境、基本命令使用及简单实战》,https://blog.51cto.com/andyxu/2174652 本文的所有操作都是基于这个环境执行的。
三、构建php镜像
(1)Dockerfile文件内容
FROM centos:latest MAINTAINER https://blog.51cto.com/andyxu ENV TIME_ZOME Asia/Shanghai ARG PV="php-7.2.11" ADD $PV.tar.gz /tmp RUN yum -y install gcc gcc-c++ make gd-devel libxml2-devel libcurl-devel libjpeg-devel libpng-devel openssl-devel bison && mkdir /data && cd /tmp/$PV && ./configure --prefix=/data/php --with-config-file-path=/data/php/etc --with-gd --with-mysqli --with-openssl --with-zlib --with-curl --with-jpeg-dir --with-png-dir --with-iconv --enable-fpm --enable-zip --enable-mbstring && make -j 4 && make install && cp /data/php/etc/php-fpm.conf.default /data/php/etc/php-fpm.conf && cp /data/php/etc/php-fpm.d/www.conf.default /data/php/etc/php-fpm.d/www.conf && sed -i '/;daemonize/adaemonize = no' /data/php/etc/php-fpm.conf && sed -i 's/127.0.0.1/0.0.0.0/g' /data/php/etc/php-fpm.d/www.conf && echo "${TIME_ZOME}" > /etc/timezone && ln -sf /usr/share/zoneinfo/${TIME_ZOME} /etc/localtime && rm -rf /tmp/php* && yum clean all && yum -y remove gcc gcc-c++ make WORKDIR /data/php/ EXPOSE 9000 CMD ["sbin/php-fpm","-c","etc/php-fpm.conf"]
注:daemonize = no表示fpm在前台运行
(2)构建php镜像
[root@andyxu ~]# cd dockerfile/php/ [root@andyxu php]# docker build -t php:7.2.11 .
此时会先下载centos镜像,然后再构建新镜像,时间会比较久,可喝杯茶耐心等待
(3)报错问题解决方法
如果yum语句无法执行的话,并且报以下警告:
[Warning] IPv4 forwarding is disabled. Networking will not work.
这个问题是由于IPv4转发被禁用了,导致无法上网,需要将IPv4转发开启
解决方法:vim /usr/lib/sysctl.d/00-system.conf
添加如下内容net.ipv4.ip_forward=1
重启network服务systemctl restart network
四、构建nginx镜像
(1)Dockerfile文件内容
FROM centos:latest MAINTAINER https://blog.51cto.com/andyxu ENV TIME_ZOME Asia/Shanghai ARG NV="nginx-1.15.5" COPY nginx.conf /data/nginx/conf/ ADD $NV.tar.gz /tmp RUN yum -y install gcc gcc-c++ make openssl-devel pcre-devel && mkdir -p /data && cd /tmp/$NV && ./configure --prefix=/data/nginx && make -j 2 && make install && echo "${TIME_ZOME}" > /etc/timezone && ln -sf /usr/share/zoneinfo/${TIME_ZOME} /etc/localtime && rm -rf /tmp/nginx* && yum clean all && yum -y remove gcc gcc-c++ make WORKDIR /data/nginx/ EXPOSE 80 CMD ["./sbin/nginx","-g","daemon off;"]
(2)准备好nginx配置文件
将nginx.conf文件的server段按如下内容修改,我这里去掉了#号注释行
server { listen 80; server_name localhost; location / { root html; index index.html index.htm index.php; #添加index.php } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } location ~ .php$ { root html; fastcgi_pass php:9000; #php容器名称和端口号 fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; #使用root指定的路径 include fastcgi_params; } }
(3)构建nginx镜像
[root@andyxu php]# cd ../nginx/ [root@andyxu nginx]# docker build -t nginx:1.15.5 .
五、下载mysql镜像
建议直接使用mysql官方镜像,我测试过源码编译安装,最后生成的镜像大小3G多,而官方镜像只有400多M,而且源码安装操作步骤比较复杂,所以这里我弃用了源码安装,而选择直接使用官方镜像。
[root@andyxu nginx]# docker pull mysql:8.0.12 8.0.12: Pulling from library/mysql 802b00ed6f79: Pull complete 30f19a05b898: Pull complete 3e43303be5e9: Pull complete 94b281824ae2: Pull complete 51eb397095b1: Pull complete 54567da6fdf0: Pull complete bc57ddb85cce: Pull complete d6cd3c7302aa: Pull complete d8263dad8dbb: Pull complete 780f2f86056d: Pull complete 8e0761cb58cd: Pull complete 7588cfc269e5: Pull complete Digest: sha256:038f5f6ea8c8f63cfce1bce9c057ab3691cad867e18da8ad4ba6c90874d0537a Status: Downloaded newer image for mysql:8.0.12
查看已经构建完成的镜像情况
[root@andyxu nginx]# docker pull mysql:8.0.12 8.0.12: Pulling from library/mysql 802b00ed6f79: Pull complete 30f19a05b898: Pull complete 3e43303be5e9: Pull complete 94b281824ae2: Pull complete 51eb397095b1: Pull complete 54567da6fdf0: Pull complete bc57ddb85cce: Pull complete d6cd3c7302aa: Pull complete d8263dad8dbb: Pull complete 780f2f86056d: Pull complete 8e0761cb58cd: Pull complete 7588cfc269e5: Pull complete Digest: sha256:038f5f6ea8c8f63cfce1bce9c057ab3691cad867e18da8ad4ba6c90874d0537a Status: Downloaded newer image for mysql:8.0.12
查看已经构建完成的镜像情况
[root@andyxu nginx]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx 1.15.5 2ecb7008e436 6 minutes ago 266MB php 7.2.11 5be80a8d0f1f 35 minutes ago 580MB centos latest 75835a67d134 2 days ago 200MB mysql 8.0.12 6a834f03bd02 5 weeks ago 484MB
六、创建并启动容器
(1)创建自定义网络lnmp
[root@andyxu nginx]# docker network create lnmp d56d132338f8e63537dac55d481053d56a5c5faf3ab3bd3a04ac2bc460b54b3f [root@andyxu nginx]# docker network ls NETWORK ID NAME DRIVER SCOPE b0fa374c72f1 bridge bridge local e6930ef7e774 host host local d56d132338f8 lnmp bridge local d7beee548faa none null local
(2)创建生成mysql、php、nginx容器的脚本
docker_lnmp.sh脚本内容如下
#!/bin/bash function mysql() { docker run --name mysql --restart=always --net lnmp -p 3306:3306 -v /data/mysql/data:/var/lib/mysql -v /data/mysql/conf:/etc/mysql/conf.d -v /data/mysql/logs:/logs -e MYSQL_ROOT_PASSWORD=test123456 -d mysql:8.0.12 --character-set-server=utf8 } function php() { docker run --name php --restart=always --net lnmp -v /data/nginx/html:/data/nginx/html -v /data/php/log:/data/php/var/log -d php:7.2.11 } function nginx() { docker run --name nginx --restart=always --net lnmp -p 80:80 -v /data/nginx/html:/data/nginx/html -v /data/nginx/logs:/data/nginx/logs -d nginx:1.15.5 } $1
注:php和nginx必须都要挂载网站目录
(3)启动mysql、php、nginx容器
[root@andyxu ~]# sh docker_lnmp.sh mysql [root@andyxu ~]# sh docker_lnmp.sh php [root@andyxu ~]# sh docker_lnmp.sh nginx
(4)查看容器是否都成功启动
[root@andyxu ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a1f9c0dea6df nginx:1.15.5 "./sbin/nginx -g 'da…" About a minute ago Up About a minute 0.0.0.0:80->80/tcp nginx 8dfe39adbc60 php:7.2.11 "sbin/php-fpm -c etc…" 5 minutes ago Up 5 minutes 9000/tcp php 475b41187391 mysql:8.0.12 "docker-entrypoint.s…" 6 minutes ago Up 6 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp mysql
(5)修改mysql的密码加密方式为mysql_native_password[root@andyxu ~]# vim /data/mysql/conf/docker_mysql.cnf
[mysqld] default-authentication-plugin=mysql_native_password
如果不修改加密方式的话,低版本的mysql客户端登陆时会报错
重启mysql容器
七、创建并启动redis容器
(1)下载redis镜像
[root@iZ2zefwlhq937bc2wfpp1oZ ~]# docker pull redis
(2)启动redis镜像
[root@iZ2zefwlhq937bc2wfpp1oZ ~]# docker run --name redis --restart=always --net lnmp -p 6379:6379 -d redis
(3)查看效果
八、创建连接php连接redis扩展
(1) 下载对应的安装依赖命令
[root@iZ2zefwlhq937bc2wfpp1oZ ~]# yum install php-devel php-pear httpd-devel
因为使用pecl下载扩展的需要安装否则出现如下报错
-bash: pecl: command not found
(2)检查是否安装成功json扩展如果没有安装则安装
1.进入容器内部
[root@iZ2zefwlhq937bc2wfpp1oZ ~]# docker exec -it php bash
2.使用命令查看
[root@9f4c8b7e15c0 php]# php -m | grep json
3.如果不存在使用
[root@9f4c8b7e15c0 php]# yum install php-json
(3)使用pecl下载redis扩展
[root@9f4c8b7e15c0 php]# pecl install redis
(4)php有2个配置的php.ini一个编译的时候,一个在启动加载模块的php.ini如图
所以需要手动设置进入对应php容器
[root@9f4c8b7e15c0 php]# pear config-set php_ini /data/php/etc/php.ini
就会如上图所示
(5) 在容器里面执行pecl install redis 命令后悔自动在对应目录下面的ph.ini 里面添加扩展如图
(6)出来容器自动重启php容器
[root@iZ2zefwlhq937bc2wfpp1oZ html]# docker restart php
备注:安装swoole 和memcached 都是一样的套路