docker 构建 php,mariadb,nginx环境

docker多版本php的搭建_cangqiong_xiamen的博客-CSDN博客_docker 多版本php

CentOS 7中Docker搭建LNMP环境的方法_CentOS_资源库

sudo docker pull mariadb:10.3
sudo docker pull php:7.2-fpm
sudo docker pull nginx:1.14
sudo docker pull php:8.0-fpm

运行 mariadb10.3 容器的 shell 脚本  (特别要注意的是,docker command line is order sensitive! docker 命令的选项不能随意交换次序,参考 Docker ERROR: mysqld failed while attempting to check config_虚心前行-CSDN博客),docker 容器运行出错,可以 sudo  docker logs  <container name> 查看日志

#!/bin/bash

echo docker 准备运行 mariadb10.3 容器
echo -e "目录映射 host \e[1;34m/home/sjg/docker_data/mariadb10.3\e[0m -> container \e[1;35m/data\e[0m"
echo -e "端口映射 host \e[1;34m3306\e[0m -> container \e[1;35m3306\e[0m"
echo -e "内部 root 密码 \e[1;31mjsjxjf\e[0m"

already_started=`sudo docker ps | grep 'mariadb10.3'`
if [ ! -z "$already_started" ]; then
    echo mariadb10.3 already started
else
    has_container=`sudo docker ps -a | grep 'mariadb10.3'`
    if [ ! -z "$has_container" ]; then
        echo find image mariadb10.3, try to start it
        sudo docker start mariadb10.3
    else
        echo no image mariadb10.3, try to create and run
        sudo docker run -d -v /home/sjg/docker_data/mariadb10.3:/data  -p 3306:3306 -e MYSQL_ROOT_PASSWORD=jsjxjf --name mariadb10.3 mariadb:10.3 
    fi

    started=`sudo docker ps | grep 'mariadb10.3'`
    if [ -z "$started" ]; then
        echo FAILED to start mariadb10.3
        exit
    fi 
fi    

if [ $# -eq 1 -a "$1" = "bash" ]; then 
   echo 运行容器内部伪终端
   sudo docker exec -ti mariadb10.3 /bin/bash
fi   

运行效果如下 (可以在里面运行 mysql 和 mysqldump 命令) (已经改了,默认不进入虚拟终端,要进入虚拟终端,加参数 bash,如 ./start_mariadb.sh  bash

停止该容器的脚本

#!/bin/bash

started=`sudo docker ps | grep 'mariadb10.3'`
if [ ! -z "$started" ]; then
    sudo docker stop mariadb10.3
fi

check=`sudo docker ps | grep 'mariadb10.3'`
if [ -z "$check" ]; then
    echo mariadb10.3 stopped!
else
    echo FAILED to stop mariadb10.3
fi    

注意:和 CentOS一样,docker 方式的 mariadb 没有将服务器默认字符集设置为 utf8mb4 或 utf8!这让用惯了 Ubuntu 的我有点不太适应,需要记住,创建数据库时指定字符集(否则要去修改配置文件) CREATE DATABASE IF NOT EXISTS  mydb DEFAULT CHARACTER SET utf8mb4  COLLATE  utf8mb4_general_ci  或者修改 docker 容器内配置文件 /etc/mysql/mariadb.cnf (文件内有提示,去掉有关注释即可)

类似处理 php-7.2fpm,启动和关闭脚本 (容器联系   外部容器名:内部容器名,内部容器名mariadb是php-7.2fpm容器引用mariadb10.3时使用的名字,当然,也可以直接用IP来引用)

#!/bin/bash

mariadb_started=`sudo docker ps | grep 'mariadb10.3'`
if [ -z "$mariadb_started" ]; then
    echo container mariadb10.3 must be started first! exit
    exit
fi

cname='php7.2fpm'

echo docker 准备运行 $cname 容器
echo -e "目录映射 host \e[1;34m/home/sjg/docker_data/gxlq_pig\e[0m -> container \e[1;35m/gxlq_pig\e[0m"
echo -e "端口映射 host \e[1;34m9000\e[0m -> container \e[1;35m9000\e[0m"
echo -e "容器联系 \e[1;31mmariadb10.3:mariadb\e[0m"

already_started=`sudo docker ps | grep $cname`
if [ ! -z "$already_started" ]; then
    echo $cname already started
else
    has_container=`sudo docker ps -a | grep $cname`
    if [ ! -z "$has_container" ]; then
        echo find container $cname, try to start it
        sudo docker start $cname
    else
        echo no container $cname, try to create and run
        sudo docker run -d -v /home/sjg/docker_data/gxlq_pig:/gxlq_pig  -p 9000:9000 --link mariadb10.3:mariadb --name $cname php:7.2-fpm 
    fi

    started=`sudo docker ps | grep $cname`
    if [ -z "$started" ]; then
        echo FAILED to start $cname
        exit
    fi 
fi    

if [ $# -eq 1 -a "$1" = "bash" ]; then 
   echo 运行容器内部伪终端
   sudo docker exec -ti $cname /bin/bash
fi
#!/bin/bash

cname='php7.2fpm'

started=`sudo docker ps | grep $cname`
if [ ! -z "$started" ]; then
    sudo docker stop $cname
fi

check=`sudo docker ps | grep $cname`
if [ -z "$check" ]; then
    echo $cname stopped!
else
    echo FAILED to stop $cname
fi    

处理里面项目,参考 简介 | Composer 中文文档 | Composer 中文网  来安装 composer

然后 composer update 安装项目 vendor 目录下的依赖包

出现少png.hapt install  libpng-dev 

对于缺少PHP扩展,类似 docker-php-ext-install  gd  zip 安装  (gd扩展少特性,参考后面处理,下载有关源码包重新配置编译,docker容器里面安装php扩展其实是编译安装的)

类似处理 nginx1.14,我们希望不同的项目不同的组合,所以,这里建立 start_gxlq_pig.sh 为例(启动该脚本会先启动mariadb10.3 和 php7.2fpm。容器联系里 phpfpm7.2容器在本容器内名称为phpfpm,所以,nginx配置网站时,fastcgi_pass phpfpm:9000;,用127.0.0.1 会连不上报502错误,事实上各容器是连接在同一个网桥bridge上的,可以 docker network list 查看,各容器有一个“内部局域网”地址)

注意:nginx容器内应该始终给它配置80端口,使用其他端口配置 XDEBUG和PHPSTORM调试时似乎不能很好映射路径

#!/bin/bash

./start_mariadb.sh
./start_php7.2fpm.sh

sleep 2s   # delay to ensure the processes started

mariadb_started=`sudo docker ps | grep 'mariadb10.3'`
php72fpm_started=`sudo docker ps | grep 'php7.2fpm'`

if [ -z "$mariadb_started" -o -z "$php72fpm_started" ]; then
    echo container mariadb10.3 and php7.2fpm must be started first! exit
    exit
fi

cname='gxlq_pig'

echo docker 准备运行 $cname 容器
echo -e "目录映射 host \e[1;34m/home/sjg/docker_data/gxlq_pig\e[0m -> container \e[1;35m/gxlq_pig\e[0m"
echo -e "端口映射 host \e[1;34m8066\e[0m -> container \e[1;35m80\e[0m"
echo -e "容器联系 \e[1;31mphp7.2fpm:phpfpm\e[0m"

already_started=`sudo docker ps | grep $cname`
if [ ! -z "$already_started" ]; then
    echo $cname already started
else
    has_container=`sudo docker ps -a | grep $cname`
    if [ ! -z "$has_container" ]; then
        echo find container $cname, try to start it
        sudo docker start $cname
    else
        echo no container $cname, try to create and run
        sudo docker run -d -v /home/sjg/docker_data/gxlq_pig:/gxlq_pig  -p 8066:80 --link php7.2fpm:phpfpm --name $cname nginx:1.14 
    fi

    started=`sudo docker ps | grep $cname`
    if [ -z "$started" ]; then
        echo FAILED to start $cname
        exit
    fi 
fi    

if [ $# -eq 1 -a "$1" = "bash" ]; then
   echo 运行容器内部伪终端
   sudo docker exec -ti $cname /bin/bash
fi
#!/bin/bash

cname='gxlq_pig'

started=`sudo docker ps | grep $cname`
if [ ! -z "$started" ]; then
    sudo docker stop $cname
fi

check=`sudo docker ps | grep $cname`
if [ -z "$check" ]; then
    echo $cname stopped!
else
    echo FAILED to stop $cname
fi    

apt update,  apt  install  vim procps, 用 vim 修改 /etc/nginx/conf.d/default.conf,和生产环境相比,开发环境去掉 SSL,phpfpm 改成 端口方式 (如果原来是 unix socket 方式), ps -aux 查看nginx容器工作进程的用户为nginx,phpfpm容器工作进程用户为www-data (需要可写权限的应该是phpfpm),对于开发环境,我们简单让www-data用户对项目目录都是可写的(或者 chmod 0777 -R

对于php7.2fpm容器添加 xdebug 以便可以调试,可以部分  参考 docker 配置xdebug成功案例【极其简单】_Lzq_1010的专栏-CSDN博客_docker xdebug

Xdebug: Documentation » Step Debugging

xdebug版本与支持的PHP版本情况可以参考  http://xdebug.org/docs/compat#supported-versions

apt update, apt install wget, cd /usr/src/php/ext/ (这个目录可能没有,可以自己手工先建立,是解压里面已经存在的php源码产生,也可以手工解压php.tar.xz文件,不过后面docker-php-ext-install也会自动先解压,docker-php-ext-configure 相当于 configure 操作,用来配置编译参数,docker-php-ext-install 相当于 make, make install 编译安装,要用该命令安装扩展,都要在这个基础目录下进行)
wget http://xdebug.org/files/xdebug-3.0.3.tgz && tar zxvf xdebug-3.0.3.tgz && mv xdebug-3.0.3 xdebug && rm -f xdebug-3.0.3.tgz  (这里确保 xdebug源码目录已经在php/ext下)

docker-php-ext-install xdebug,  docker-php-ext-enable xdebug (已经加载这句可能不需要,php  -m 可以查看已经加载的扩展
apt update && apt install vim,  vim /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
修改配置 (容器内重启 php-fpm服务可以 kill  -USR2  1  ,因为 php-fpm 主进程 id 为 1)

zend_extension=xdebug.so
xdebug.mode=debug
xdebug.remote_port=9003       ---->  version 3.0+, replaced by  .client_port
xdebug.idekey=PHPSTORM
xdebug.remote_log=/tmp/xdebug_remote.log   ----> version 3.0+, replaced by  .log
xdebug.discover_client_host=1

PHPSTORM配置:可以在 settings-PHP-Debug 中按 Pre-configuration 提示操作,因为谷歌商店被墙,我们就用GET参数 XDEBUG_SESSION_START=PHPSTORM来激发调试,Xdebug port 9000,9003,settings-PHP-servers设置好服务器的路径映射(Host localhost, Port 8066, Debugger Xdebug,勾选 Use path mapping),本地源码目录和容器内绝对路径映射(项目根/home/sjg/phpsrc/gxlq_pig和web根/gxlq_pig)

(上图中 xdebug:9001 应为 xdebug:9003,PHPSTORM默认监听9000,9003这两个端口来接收xdebug的调试信号,但9000端口php-fpm占用了,所以,我们使用9003 。当然,也可以xdebug的配置和PHPSTORM的配置一起改成9001,同时重启php-fpm和PHPSTORM生效。配置后可以用Run菜单下Validate Debugger Configuration验证,确保都是绿色√,php.ini没找到但额外的.ini文件能解析到就行。PHPSTORM的设置中,Servers中可能需要新建一个服务器,Name和Host都使用nginx容器中配置的主机名,同时,配置好路径映射,见前图之前的说明。可以Run - Break at first line in PHP scripts 强制在首行中断查验是否起作用。)

php-fpm 开启日志可以参考  开启php-fpm日志记录 – 行星带

注意:在 nginx中配置网站时,对应的 php-fpm 不能使用 127.0.0.1,要使用 php7.2fpm 或 php8.0fpm 这样的容器ID (虽然内部IP应该也可以,但不好记)

容器内配置改坏了导致容器启动不了恢复办法可以参考 Docker容器无法启动,里面的配置文件如何修改 - 知乎

因为我基本上就是配置改坏了,所以,用 docker cp [容器id]:docker容器中配置文件路径  主机路径  拷贝到宿主机修改,改好再拷贝回去(cp后面源和目标互换)

docker 的 php7.2fpm 的扩展和linux的不太一样,gd扩展少 free-type jpeg 等支持 (在前述扩展基础目录下用 php  --ri  gd 可以了解 gd 扩展安装情况)

apt  install  libjpeg-dev (针对 error: jpeglib.h not found.)

apt install libfreetype-dev (针对 fatal error: ft2build.h: No such file or directory )

docker-php-ext-configure gd --with-freetype-dir=/usr --with-jpeg-dir=/usr --with-png-dir=/usr   && docker-php-ext-install -j "$(nproc)" gd

(配置php-fpm8.0或php-fpm8.1时,docker-php-ext-confiugre  gd  --help可以发现,配置选项  --with-freetype-dir=/usr   --with-jpeg-dir=/usr  --with-png-dir=/usr 前面两个 -dir 应去掉,第三个选项不需要了,即 docker-php-ext-configure gd --with-freetype=/usr --with-jpeg=/usr    \
  && docker-php-ext-install -j "$(nproc)" gd

php -r "print_r(gd_info());"  查看是否已经支持
docker-php-ext-install pdo pdo_mysql  (针对访问 mariadb)
apt update && apt install openssh-client  (针对没有 scp,如果容器内需要 ssh 和 scp 命令的话 )
(更多扩展安装可以参考  docker安装php-fpm以及扩展_猛犸象-CSDN博客_docker php-fpm  )

从 php-fpm 容器编写测试连接数据库:(注意,对容器来说 localhost 都是自己,所以,连接时 host 需要使用容器名或者宿主的IP地址,找不到连不上会报错 Error!: SQLSTATE[HY000] [2002] No such file or directory) 

<?php
$dbms="mysql";   
$host="mariadb10.3";    // 注意:必须用 容器名 或者 宿主IP
$dbport = "3306";
$dbName="gxlq_pig";  
$user="gxlq_pig";    
$pass="××××××"; 
$dsn="$dbms:host=$host;port=$dbport;dbname=$dbName";

try {
    $dbh = new PDO($dsn, $user, $pass);
    echo "successful<br/>";
    
    $dbh = null;
} catch (PDOException $e) {
    die ("Error!: " . $e->getMessage() . "<br/>");
}

容器内的时区默认是0时区UTC,修改时区要么在生成容器时用参数指定,要么给容器添加配置文件,可以参考 (我使用了拷贝/etc/localtime文件的方式,对 yii2 应用来说,在配置文件中设定 timeZone 比较好,可以不理睬服务器的时区设置) Docker-设置容器时区_wxuzero的博客-CSDN博客_设置容器时区

 我们访问容器提供的网站时,其实是先把请求提交给了代理(访问数据库和php-fpm也类似),然后这个代理对应docker内部的IP,我的使用中, 网站外部端口8066 ,内部端口80,内部IP地址172.17.0.1, 在使用 yii2 gii 模块时,我就设定 allowedIPs 包含 172.17.0.*  (对于数据库连接,网站程序可以使用 172.17.0.* 这样的 IP 连接,也可以用容器名 mariadb10.3 连接,因为网站程序的执行身份是 nginx 容器,它能识别同为容器的 mariadb10.3,而 PhpStorm/IDEA 中配置 Database - Data Source 时,只能使用 IP 地址 172.17.0.*,因为 PhpStorm 中使用 JDBC 连接,相当于一个独立图形客户端,不能识别容器名 mariadb10.3。可以在 mariadb10.3 容器内用命令 ip  a 查看具体 IP 地址(通常,运行容器后,容器内/etc/hosts文件登记了它自己的IP地址,一般是最后一行,从最后一行往上,如果有,就是相联系的容器的IP地址)。同样的道理,要使用 yii2 的 migration 功能迭代创建数据库,尽管有了docker容器 php8.0fpm,还是需要在当前宿主机安装支持访问 mariadb的扩展的,(sudo apt install php8.0-mysql),并且,数据连接配置中,$host = '172.17.0.*',可以使用类似 $host = YII_ENV ? '172.17.0.2' : 'localhost'; 的配置。更好的做法是创建容器php8.1-fpm的时候,容器联系定义好

sudo docker run -d -v /home/sjg/docker_data/wxinfo:/wxinfo  -p 9000:9000 --link mariadb10.3:mariadb --link redis:redis --name $cname php:8.1-fpm

然后,代码中都使用容器名称

$mariadbHost = IS_DOCKER ? 'mariadb' : 'localhost';  // php8.1fpm:phpfpm 容器联系到 mariadb10.3:mariadb
$redisHost = IS_DOCKER ? 'redis' : 'localhost';    // php8.1fpm:phpfpm 容器联系到 redis:redis

因为使用 IP 地址,IP地址是动态的,一旦前面有其他容器运行了,会冲突。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值