目录
本片文章搭建的环境是 nginx1.19 + php7.4 + php8.2 + mysql5.7 + mysql8.0 + redis
,多版本 php 和多版本 mysql。
这里就直接使用 docker-compose 搭建环境,也可以找到镜像创建容器再关联映射端口部署。
资源包下载地址。
参考文章:docker-compose使用nginx+php+mysql+redis部署fastadmin
。
1、dnmp目录结构
..env# 配置参数├── docker-compose.yml# docker-compose文件├── mysql57│ ├── conf│ │ └── my.cnf│ └── log│ ├── mysqld.log│ ├── tallylog│ └── yum.log├── mysql80│ ├── conf│ │ └── my.cnf│ ├── data# mysql8.0数据目录(我这里没有挂载)│ └── log├── nginx│ ├── conf│ │ ├── default.conf│ │ ├── php.conf│ └── logs│ ├── access.log│ └── error.log├── php74│ ├── Dockerfile# php7.4 Dockerfile文件│ └── conf│ ├── ini│ │ ├── conf.d│ │ │ ├── docker-php-ext-mysqli.ini│ │ │ ├── docker-php-ext-pdo_mysql.ini│ │ │ └── docker-php-ext-sodium.ini│ │ ├── php.ini-development│ │ └── php.ini-production│ └── php-fpm.d│ ├── docker.conf│ ├── www.conf│ ├── www.conf.default│ └── zz-docker.conf├── php824│ ├── Dockerfile# php8.2.4 Dockerfile文件│ ├── conf│ │ ├── php-fpm.conf│ │ └── php.ini│ ├── data│ │ └── composer│ └── logs│ ├── fpm.slow.log│ └── php.error.log└── redis ├── redis.cnf └── redis.conf
2、.env 配置文件
我只简单配置了 工作目录
和 docker环境目录
,可以根据需要把 docker-compose.yml
中容器参数放到这边。
## 项目目录/工作目录#PROJECT_DIR=/Users/yunsanmu/work/project## 当前docker开发环境目录#DEV_ENV_DIR=/Users/yunsanmu/dev-env
3、docker-compose.yml
为了方便操作,一般都会把容器的配置文件、日志文件等挂载映射。端口映射根据自己需要
version: "2.1"services: nginx: image: nginx:1.19.1-alpine container_name: nginx ports: - "80:80" volumes: - ${PROJECT_DIR}:/usr/share/nginx/html - ${DEV_ENV_DIR}/nginx/conf:/etc/nginx/conf.d - ${DEV_ENV_DIR}/nginx/logs:/var/log/nginx networks: - lnmp-network php74: container_name: php74 build: ./php74 # 这个目录放上我们刚才做好的定制化php的Dockerfile ports: - "9001:9000" volumes: - ${PROJECT_DIR}:/www:rw - ${DEV_ENV_DIR}/php74/conf/ini:/usr/local/etc/php - ${DEV_ENV_DIR}/php74/conf/php-fpm.d:/usr/local/etc/php-fpm.d restart: always links: - mysql57 networks: - lnmp-network php824: container_name: php824 build: ./php824 ports: - "9002:9000" volumes: - ${PROJECT_DIR}:/www/:rw - ${DEV_ENV_DIR}/php824/conf/php.ini:/usr/local/etc/php/php.ini:ro - ${DEV_ENV_DIR}/php824/conf/php-fpm.conf:/usr/local/etc/php-fpm.d/www.conf:rw - ${DEV_ENV_DIR}/php824/logs:/var/log/php - ${DEV_ENV_DIR}/php824/data/composer:/tmp/composer restart: always networks: - lnmp-network mysql57: image: mysql/mysql-server:5.7.28 container_name: mysql57 ports: - "3307:3306" volumes: - ${DEV_ENV_DIR}/mysql57/conf/my.cnf:/etc/my.cnf:ro # - ${DEV_ENV_DIR}/mysql57/data:/var/lib/mysql/:rw # 这里我就不挂载了,有需要到容器里看 - ${DEV_ENV_DIR}/mysql57/log:/var/log/:rw environment: - MYSQL_ROOT_PASSWORD=root restart: always networks: - lnmp-network mysql80: image: mysql:8.0 container_name: mysql80 ports: - "3308:3306" volumes: - ${DEV_ENV_DIR}/mysql80/conf/my.cnf:/etc/my.cnf:ro # - ${DEV_ENV_DIR}/mysql80/data:/var/lib/mysql/:rw - ${DEV_ENV_DIR}/mysql80/log:/var/log/:rw environment: - MYSQL_ROOT_PASSWORD=root networks: - lnmp-network redis: image: redis:5.0.3-alpine container_name: redis ports: - "6379:6379" volumes: - ${DEV_ENV_DIR}/redis/redis.cnf:/etc/redis.conf:ro restart: always entrypoint: [ "redis-server", "/etc/redis.conf" ] networks: - lnmp-networknetworks: lnmp-network: driver: bridge ipam: driver: default
由于我的电脑是 mac 的 m1 芯片
所以我这里使用的都是支持linux/arm64/v8
的镜像。
MySQL5.7的最新镜像就是不支持 linux/arm64/v8 平台,创建容器会报如下警告:
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
我这里使用 mysql/mysql-server:5.7.28
替代。
4、dockerfile
dockerfile
是自定义镜像的一套规则,由多条指令构成,在docker-compose.yml
中通过 build
参数引入。 上面的 docker-compose.yml
比较简单,我只对两个版本的PHP写了 dockerfile
,其他的都只在 compose
中使用image
,没有过多配置。
php7.4 的 dockerfile:
# 该装的都装上 # 版本7.4FROM php:7.4-fpm # composerRUN curl -sS https://getcomposer.org/installer | php \ && mv composer.phar /usr/bin/composer && chmod +x /usr/bin/composer # 各种依赖库和扩展RUN apt-get update \ && apt-get install -y \ vim \ git \ wget \ build-essential \ libmagickcore-dev \ libmagickwand-dev \ imagemagick \ libfreetype6-dev \ libmcrypt-dev \ libpng-dev \ libzip-dev \ libwebp-dev \ autoconf \ pkg-config \ gcc \ make \ zlib1g \ zlib1g-dev \ && docker-php-ext-configure gd --with-webp=/usr/include/webp --with-jpeg=/usr/include --with-freetype=/usr/include/freetype2/ \ && docker-php-ext-install -j$(nproc) gd iconv pdo pdo_mysql pdo_odbc mysqli bcmath calendar exif gettext sockets dba pcntl shmop sysvmsg sysvsem sysvshm zip \ && pecl install redis-5.3.7 \ && pecl install imagick \ && pecl install mcrypt \ && docker-php-ext-enable redis imagick mcrypt \# 这句很重要,如果和你的nginx用户不同会导致你的服务起不来RUN groupadd www && useradd -g www www # 如果你需要别的扩展,还可以再加
php8.2.4 的 dockerfile:
# 该装的都装上# 版本8.2.4FROM php:8.2.4-fpm# composerRUN curl -sS https://getcomposer.org/installer | php \ && mv composer.phar /usr/bin/composer && chmod +x /usr/bin/composer# 各种依赖库和扩展RUN apt-get update \ && apt-get install -y \ vim \ git \ wget \ build-essential \ libmagickcore-dev \ libmagickwand-dev \ imagemagick \ libfreetype6-dev \ libmcrypt-dev \ libpng-dev \ libzip-dev \ libwebp-dev \ autoconf \ pkg-config \ gcc \ make \ zlib1g \ zlib1g-dev \ && docker-php-ext-configure gd --with-webp=/usr/include/webp --with-jpeg=/usr/include --with-freetype=/usr/include/freetype2/ \ && docker-php-ext-install -j$(nproc) gd iconv pdo pdo_mysql mysqli bcmath calendar exif gettext sockets dba pcntl shmop sysvmsg sysvsem sysvshm zip \ && pecl install redis-5.3.7 \ && pecl install imagick \ && pecl install mcrypt \ && docker-php-ext-enable redis \ && docker-php-ext-enable imagick \ && docker-php-ext-enable mcrypt# 这句很重要,如果和你的nginx用户不同会导致你的服务起不来RUN groupadd www && useradd -g www www# 如果你需要别的扩展,还可以再加
5、启动
进入 docker-compose.yml
所在的目录,创建镜像那一步就直接跳过了,执行 docker-compose up -d
启动如下:
yunsanmu@yunsanmudeMacBook-Pro ~ % cd dev-env yunsanmu@yunsanmudeMacBook-Pro dev-env % docker-compose up -dStarting nginx ... doneStarting redis ... doneStarting php824 ... doneStarting mysql80 ... doneStarting mysql57 ... doneStarting php74 ... doneyunsanmu@yunsanmudeMacBook-Pro dev-env %
打开docker 客户端如下图:
启动相关命令:
docker-compose up -d # 创建并启动某个容器docker-compose down # 停止并删除所有容器、网络、镜像等docker-compose stop # 停止所有容器docker-compose start # 启动所有容器docker-compose restart# 重启所有容器docker-compose rm# 删除容器(删除前必须关闭容器,执行stop)
启动完成后需要做一些操作,mysql默认root账号是没有远程连接权限,先通过命令行在mysql5.7和mysql8.0赋予root用户远程权限,生产环境添加专门的远程账号。
通过docker 客户端进入mysql57和mysql80容器内,都执行一遍下面的命令:
sh-4.2# mysql -uroot -pEnter password: mysql> use mysql;Database changedmysql> update user set host = '%' where user = 'root';Query OK, 1 row affected (0.03 sec)Rows matched: 1 Changed: 1 Warnings: 0mysql> flush privileges;Query OK, 0 rows affected (0.01 sec)mysql> exit
6、测试
下面的测试显示的都是成功的流程,如果遇到相同问题参考下面的解决方法,其他问题自行百度。
进入nginx配置文件目录添加两个配置文件:php74.conf
、php82.conf
,并且在项目目录下创建两个文件夹:php74
、php82
,分别测试不同版本PHP。
├── nginx│ ├── conf│ │ ├── default.conf│ │ ├── php74.conf│ │ ├── php82.conf
├── project│ ├── php74│ │ ├── index.php│ ├── php82│ │ ├── index.php
php74.conf :
server { listen 80; server_name www.php74.com; location / { root /usr/share/nginx/html/php74; index index.html index.htm index.php; if (!-e $request_filename) { # rewrite ^.*$ /index.php last; rewrite ^/(.*)$ /index.php/$1 last; } } location ~ \.php$ { fastcgi_pass php74:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /www/php74/$fastcgi_script_name; include fastcgi_params; }}
php82.conf :
server { listen 80; server_name www.php82.com; location / { root /usr/share/nginx/html/php82; index index.html index.htm index.php; if (!-e $request_filename) { rewrite ^/(.*)$ /index.php/$1 break; # rewrite . /index.php last; } } location ~ \.php$ { fastcgi_pass php824:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /www/php82/$fastcgi_script_name; include fastcgi_params; }}
修改 hosts,添加以下内容:
127.0.0.1 www.php74.com127.0.0.1 www.php82.com
虚拟域名访问:
mysql5.7、mysql8.0和redis连接测试,编辑两个域名下的index.php文件,添加相同测试代码,测试连接:
php74/index.php:
// redis 测试$redis = new \Redis();$redis->connect('redis',6379);echo "redis is running: ".$redis->ping();echo '
';// mysql5.7 测试try { # 连接的host要注意,与./nginx/default.conf中的php连接一样,不是ip,是docker-compose中配置的容器名,container_name $dsn = "mysql:host=mysql57;dbname=mysql;"; $username = "root"; $password = "root"; $db = new PDO($dsn, $username, $password); $sql = "SELECT * FROM user"; $stmt = $db->prepare($sql); $stmt->execute(); $result = $stmt->fetchAll(PDO::FETCH_ASSOC); var_dump($result);} catch (PDOException $e) { echo $e->getMessage() . "
"; exit;}echo '
';// mysql8.0 测试try { # 连接的host要注意,与./nginx/default.conf中的php连接一样,不是ip,是docker-compose中配置的容器名,container_name $dsn = "mysql:host=mysql80;dbname=mysql;"; $username = "root"; $password = "root"; $db = new PDO($dsn, $username, $password); $sql = "SELECT * FROM user"; $stmt = $db->prepare($sql); $stmt->execute(); $result = $stmt->fetchAll(PDO::FETCH_ASSOC); var_dump($result);} catch (PDOException $e) { echo $e->getMessage() . "
"; exit;}
再次访问虚拟域名:
1、PHP8 打不开
报错:
[error] 26#26: *1 rewrite or internal redirection cycle while processing "/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/", client: 172.28.0.1, server: www.php82.com, request: "GET / HTTP/1.1", host: "www.php82.com"2
修改nginx配置文件的反向代理:
错误配置if (!-e $request_filename) { rewrite ^/(.*)$ /index.php/$1 last;}正确配置,替换{}内容:rewrite ^/(.*)$ /index.php/$1 break;或rewrite . /index.php last;
2、MySQL 不允许主机连接到此MySQL服务器
报错:
Host '172.28.0.6' is not allowed to connect to this MySQL server
解决方法: 进入容器执行以下命令。
mysql> use mysql;mysql> update user set host = '%' where user = 'root';mysql> flush privileges;mysql> exit
执行第二个命令时可能会出现 Duplicate entry ‘%-root‘ for key ‘PRIMARY‘
错误,参考:MySql出现ERROR 1062 (23000): Duplicate entry ‘%-root‘ for key ‘PRIMARY‘。
3、Mysql 无法连接
错误:
Error!: could not find driver
原因:
当我们使用 navicat
连接 mysql
时是在容器外进行操作,是用 ip+映射端口
连接;当在 php
代码中使用 pdo
连接 mysql
是在 php
容器内部连接mysql
容器,所以是 容器名+3306端口
连接。
解决办法:
$conn = new PDO('mysql:host=容器名;dbname=数据库;port=端口','用户','密码');
来源地址:https://blog.csdn.net/weixin_43844718/article/details/129883644