MENU

稽于docker奔跑LNMP运行环境

2018 年 05 月 04 日 • 应用服务器

emmmm,最近在考虑要不要用docker来跑这个小博客,大概想了一下,现在所使用的环境就是一个LNMP,只要用docker能跑起一个LNMP平台就可以实现,但是细想了一下本站启用了https+http2,看来得找一个支持http2的nginx镜像才可以,因为nginx要跑h2的前提条件是得装有openssl,版本大于 1.0.2e,看到这里,其实这个小博客已经在容器上正常运行一段时间了,搭建途中也踩过一些坑,今天来分享一下搭建过程。

不废话了,先准备一下需要用的镜像吧。

获取镜像

获取nginx镜像

我本是打算以CentOS的镜像去自动构建一个支持http2的nginx镜像,先试了一下把已经编译好的nginx直接扔上去能不能行,结果是能正常跑起来,我是直接把博客正式服务器上的nginx打了一个tar包,通过Dockerfile的ADD参数直接传到了镜像里,可以启动,也支持h2,经过测试没啥子问题,省去了编译安装的步骤,所以我的Dockerfile内容如下

FROM centos:latest
ENV LANG en_US.utf8
ENV PATH /usr/local/nginx/sbin:$PATH
ADD nginx.tar.gz /usr/local/
RUN useradd -u 33 -s /sbin/nologin -M www-data && \
    ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo Asia/Shanghai > /etc/timezone
CMD ["nginx", "-g", "daemon off;"]

我nginx是以www-data用户去启动的,所以得添加一个www-data用户,然后吧nginx的sbin目录加到了全局变量,还有就是修改了编码和时区,最后是默认执行命令,我不用传配置文件和证书了,因为都包里全有的,如果你没有使用Dockerfile去的COPY参数传进去吧,查看构建后的镜像。

[root@rj-bai /data/docker/centos7-nginxh2]# docker build -t centos7-nginxh2 .
[root@rj-bai /data/docker/centos7-nginxh2]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos7-nginxh2     latest              806dc5facdf7        16 seconds ago      318MB

暂时先不启动。

获取MySQL镜像

还是使用MySQL5.7,先搜一下。

[root@rj-bai ~]# docker search mysql
NAME                                                   DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mysql                                                  MySQL is a widely used, open-source relation…   6073                [OK]                

用第一个官方的就好,pull下来,指定一下版本号,否则是最新版,现在最新版貌似是8.0的了。

[root@rj-bai ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
Status: Downloaded newer image for mysql:5.7
[root@rj-bai ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mysql               5.7                 db763dfc448b        3 days ago          372MB

先不启动,继续下载PHP

获取PHP镜像

PHP还是继续用PHP7.2的吧,直接pull就好,所使用的镜像信息如下。

[root@rj-bai ~]# docker pull php:7.2-fpm
7.2-fpm: Pulling from library/php
Status: Downloaded newer image for php:7.2-fpm
[root@rj-bai ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos7-nginxh2     latest              f41c7f881f86        5 minutes ago       318MB
php                 7.2-fpm             aec878ff21b3        2 days ago          367MB
mysql               5.7                 db763dfc448b        3 days ago          372MB
centos              latest              e934aafc2206        3 weeks ago         199MB

镜像已经全部下载完了,下面开始启动容器。

启动容器

启动MySQL容器

直接启动不行哦,也得改一下时区和语言编码,所以还得写Dockerfile,内容如下。

FROM mysql:5.7
ENV LANG C.UTF-8
RUN ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo Asia/Shanghai > /etc/timezone
[root@rj-bai /data/docker/debian9-mysql5.7]# docker build -t debian9-mysql5.7 .
[root@rj-bai /data/docker/debian9-mysql5.7]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
debian9-mysql5.7    latest              6e63430b212c        7 seconds ago       372MB

启动mysql容器,需要设置一下root的密码,必填项-e MYSQL_ROOT_PASSWORD=参数,我是把我本机的数据库文件直接挂到了容器的/var/lib/mysql目录,所以不用添加这个,还有就是我也没做端口映射,我不想把数据库暴露到公网,想远程连接的时候可以手动去写NAT即可。

[root@rj-bai ~]# docker run -d --hostname mysql --name mysql5.7 \
> -v /data/mysql:/var/lib/mysql:rw \
> debian9-mysql5.7
7c2732ea049a5cca70ab33b9886566b6559c8b7f16cbd8f073d123a0195308f2
[root@rj-bai ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
7c2732ea049a        debian9-mysql5.7    "docker-entrypoint.s…"   47 seconds ago      Up 46 seconds       3306/tcp            mysql5.7

我自己看了一下没问题,和现有的数据库数据一致,因为我直接用的是我本机的数据库文件,这只是一个最基础的启动方式,对于我的博客够用了,如果你需要使用自定义参数,像是添加用户设置密码,使用自己的my.cnf配置文件,请参考官方文档,MySQL到此,下面是PHP。

启动PHP容器

启动php容器需要做的事情,添加PHP扩展,包括pdo_mysqlzip,先把镜像带有的PHP扩展贴出来吧。

root@02fc86b55bae:/var/www/html# php -m
[PHP Modules]
Core
ctype
curl
date
dom
fileinfo
filter
ftp
hash
iconv
json
libxml
mbstring
mysqlnd
openssl
pcre
PDO
pdo_sqlite
Phar
posix
readline
Reflection
session
SimpleXML
sodium
SPL
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
zlib

[Zend Modules]

看你们需要哪些扩展,缺的话需要自行添加,我除了上面列出的那些还需要pdo_mysql&mysqli&zip&gd扩展,更详细的添加扩展方法请看官方文档,开始编写Dockerfile文件

FROM php:7.3.4-fpm
ENV LANG C.UTF-8
RUN ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo Asia/Shanghai > /etc/timezone && \
    mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" && \
    apt-get update && apt-get -y install zlib1g-dev libzip-dev libpng-dev && \
    docker-php-ext-install zip pdo_mysql mysqli gd \

开始构建

[root@rj-bai /data/docker/debian9-php7.2]# docker build -t debian9-php7.2 .

构建完成

然后开始启动PHP容器,需要做的是挂载网站根目录,端口映射,9000-9000,这个就没有必要了,要和上面启动的MySQL链接一下,就是容器之间互通,需要使用--link参数。

[root@rj-bai ~]# docker run -d --hostname php --name php7.2 \
> -v /usr/local/nginx/html:/var/www/html:rw \
> --link mysql5.7:mysql \
> debian9-php7.2
d6e95a2b79993e44a8940e3d2819196310aca557e64efaff60333b53bfa7230f
[root@rj-bai ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
d6e95a2b7999        debian9-php7.2      "docker-php-entrypoi…"   3 seconds ago       Up 3 seconds        9000/tcp            php7.2
7c2732ea049a        debian9-mysql5.7    "docker-entrypoint.s…"   18 minutes ago      Up 18 minutes       3306/tcp            mysql5.7

最后,启动nginx

启动nginx容器

emmmm,启动nginx需要做的事情,端口映射,80-80,443-443,挂载网站的根目录,需要能访问到PHP容器,建议把nginx的网站根目录和PHP统一,我的都是放到/var/www/html下面的,否则nginx还要改配置,就这样,开撸。

[root@rj-bai ~]# docker run -d --hostname nginx --name nginx \
> -p 80:80 \
> -p 443:443 \
> -v /usr/local/nginx/html:/var/www/html:rw \
> --link php7.2:phpfpm \
> centos7-nginxh2
3f29d256cba9d244fc28b7409db22e9484bdbe2a1bccbcfb3824f6740dfb9c91

最后,看一下正在运行的容器

[root@rj-bai ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                      NAMES
3f29d256cba9        centos7-nginxh2     "nginx -g 'daemon of…"   19 seconds ago      Up 18 seconds       0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   nginx
d6e95a2b7999        debian9-php7.2      "docker-php-entrypoi…"   2 minutes ago       Up 2 minutes        9000/tcp                                   php7.2
7c2732ea049a        debian9-mysql5.7    "docker-entrypoint.s…"   21 minutes ago      Up 21 minutes       3306/tcp                                   mysql5.7

下面需要做的事情就是登录到nginx容器,改一下连接PHP的地址,否则访问是502

[root@rj-bai ~]# docker exec -it nginx /bin/bash
            fastcgi_pass  172.17.0.3:9000;
[root@nginx /]# nginx -s reload

然后改一下程序连接数据库的地址,如果你都没做错,就可以看效果了,还有可能遇到没有写入权限的问题。

没有写入权限

一个低级错误,还是犯了,我发现这个问题不是在传文件的时候,而是邮件提醒评论的插件,收到评论不会给你发邮件了,而手动测试发送就能收到,我当时就在好奇,一样的代码,宿主机上跑就没问题,扔到容器上就不行了。
然后找狗头,狗头表示异步调用失败,需要改代码,叫我把他的代码拿下来直接用,他的改过了,我用了他的发现问题更严重了,评论直接500,哈哈哈哈,感觉已经不是代码的问题了,我当时是以为PHP那里出什么问题了,结果查了半天PHP,最后的最后,我想到了,是不是目录的权限有问题,试了一下,还真是,大概是酱紫。

20180503183215.png

然后,宿主机终极解决方案

[root@rj-bai ~]# chmod 777 -R /usr/local/nginx/html/blog.rj-bai.com/

一切恢复正常,就是没权限,777只是临时解决办法,下面开始排除,先看一下我根目录的属主属组和权限。

[root@rj-bai ~]# ll /usr/local/nginx/html/
total 4
drwxr-xr-x 6 www www 4096 Apr 28 11:39 blog.rj-bai.com

属主属组www,权限755,这是在我宿主机上看的,再去nginx容器看看

[root@nginx /]# ll /var/www/html/
total 4
drwxr-xr-x 6 1001 1001 4096 Apr 28 11:39 blog.rj-bai.com

再是PHP容器

root@php:/var/www/html# ls -l
total 4
drwxr-xr-x 6 1001 1001 4096 Apr 28 11:39 blog.rj-bai.com

这特么的分明不对么,然后看了一下PHP的运行属主组。

root@php:/var/www/html# apt-get update && apt-get -y install procps
root@php:/var/www/html# ps -ef | grep php-fpm
root         1     0  0 17:39 ?        00:00:00 php-fpm: master process (/usr/local/etc/php-fpm.conf)
www-data     5     1  0 17:39 ?        00:00:00 php-fpm: pool www
www-data     6     1  0 17:39 ?        00:00:00 php-fpm: pool www

上面两种进程分别是什么嘤该不用解释了,是以PHP是以www-data去运行的,而nginx是www用户去运行的,解决办法就是要么是在nginx容器添加www-data用户,uid要和PHP容器内的uid一致,然后改一下目录的属主属组就可以了,建议在nginx容器上添加www-data用户就好,要改PHP容器的也可以,需要安装vi或是直接sed去替换配置文件内容,www.conf位置。

root@php:/var/www/html# find / -type f -name "www.conf"
/usr/local/etc/php-fpm.d/www.conf

我是在nginx容器上操作的,先确定一下PHP容器的www-data用户的UID是什么。

[root@rj-bai ~]# docker exec -it php7.2 /bin/bash
root@php:/var/www/html# cat /etc/passwd | grep www-data
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

是33,然后nginx容器添加一下,然后改一下权限

[root@rj-bai ~]# docker exec -it nginx /bin/bash
[root@nginx /]# cat /etc/passwd | grep 33
[root@nginx /]# useradd www-data -u 33 -s /sbin/nologin 
[root@nginx /]# cat /etc/passwd | grep www-data
www-data:x:33:1001::/home/www-data:/sbin/nologin
[root@nginx /]# chown www-data.www-data -R /var/www/html/blog.rj-bai.com/
[root@nginx /]# chmod 755 -R /var/www/html/blog.rj-bai.com/
[root@nginx /]# ll /var/www/html/
total 4
drwxr-xr-x 6 www-data www-data 4096 May  3 18:31 blog.rj-bai.com

PHP容器看一下就行了。

[root@rj-bai ~]# docker exec php7.2 /bin/bash -c "ls -l /var/www/html"
total 4
drwxr-xr-x 6 www-data 1001 4096 May  3 18:31 blog.rj-bai.com

这个问题就算是解决了,那个1001是属组,无所谓了,强迫症的话自己改吧,哈哈。

数据库

远程连接数据库

刚刚也提了一下,我MySQL容器在启动的时候没有做端口映射,现在想远程连接数据库就需要自己写NAT咯,具体步骤如下。
首先要获取到MySQL容器的IP地址。

[root@rj-bai ~]# docker container inspect mysql5.7 | grep -i ipaddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",

地址获取到了,之前也提过再启动容器时候使用的-p参数其实就是给你的iptables加了点东西,也就是NAT,可以iptables -t nat -L -n看一下,现在MySQL容器没有在启动时候添加-p参数,所以得手动加咯,内容如下,建议在需要远程连接数据库时候添加,不需要远程连接的时候把他删掉。

[root@rj-bai ~]# iptables -t nat -A DOCKER ! -i docker0 -p tcp -m tcp --dport 3306 -j DNAT --to-destination 172.17.0.2:3306
[root@rj-bai ~]# iptables -t nat -A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 3306 -j  MASQUERADE
[root@rj-bai ~]# iptables -t filter -A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 3306 -j ACCEPT

自行测试吧,不演示咯。

数据库备份

既然是用容器了,备份也不能断,但是数据库不在我本机,在容器,直接备份数据库目录,以后在别的数据上恢复会很麻烦,所以还得备份成sql文件,只给一条导出容器数据库为sql文件的命令,脚本自己写去吧。

[root@rj-bai ~]# docker exec mysql5.7 sh -c 'exec mysqldump 数据库名 -uuser -p"pass"'> 宿主机位置

到这里嘤该就木什么问题了,大概就是酱紫的东西,搭建起来就是几分钟的事,可能还会有坑,暂时还没发现,发现了再说吧。

最后编辑于: 2019 年 04 月 26 日
返回文章列表 文章二维码 打赏
本页链接的二维码
打赏二维码