Docker - 搭建LNMP环境 - 学习/实践

1.应用场景

主要用于学习使用docker搭建开发环境. 学习容器化技术.

以及快速搭建开发环境, 同时保持团队之间开发/测试环境相同~~~~

2.学习/操作

1.文档阅读

Docker - 学习/实践_穿素白衫的少年的博客-CSDN博客 // 所需文档

Docker 入门教程 - 阮一峰的网络日志 //  再放一次, 推荐阅读~~~

Docker 微服务教程 - 阮一峰的网络日志 // Docker - 微服务教程

避坑!用Docker搞定PHP开发环境搭建 // 避坑!用Docker搞定PHP开发环境搭建  -- 20210424 周六 公寓

docker搭建环境(php+nginx+mysql)_-client的博客-CSDN博客 // docker搭建环境(php+nginx+mysql)

插入:其他人发布的搭建lnmp的镜像与GitHub项目

Docker Hub

Docker Hub

GitHub - thinksvip/lnmp: LNMP docker production environment

单独安装Nginx,PHP, MySQL

MySQL 8.0 - 安装[含Docker安装] - Win10/Mac_穿素白衫的少年的博客-CSDN博客

MySQL 8.0 - Docker安装 - Win10 - 学习/实践_穿素白衫的少年的博客-CSDN博客

Docker - Windows下安装Nginx - 学习/实践_穿素白衫的少年的博客-CSDN博客

Docker - PHP - 如何使用php image - 学习/实践_穿素白衫的少年的博客-CSDN博客

待做:

将下面也打包成docker image发布到docker hub

2.整理输出

这里主要整合上面几个文档可取之处, 整理出个人认为比较好【比较适合自己】的方式~~

2.1 LNMP拆分为多个容器, 单独运行.

如拆分为:  Nginx, PHP, MySQL三个容器

这里根据各个容器的链接方式,分为两种方式: link 与 network

环境:

MacOS

方式一: link方式

项目地址:https://gitee.com/william_ning/docker-lnmp-development-env // 可对照参考

1. 先拉取镜像

nginx

php-pfm

mysql

redis

任意目录下 // 但建议选择一个目录作为工作目录, 这里选择,并新建Workspace, /Users/williamning/Workspace作为工作目录

cd /Users/williamning/Workspace // 进入工作目录下

docker pull nginx:latest

docker pull php:7.4-fpm

docker pull mysql:8.0

docker pull redis:latest

Note:

williamning是本人的用户名,换成自己的即可

而且工作目录可任选,不论是mac还是Windows

版本信息如上或者如下,可选择自己想要的

nginx:latest ---> 1.19.10

redis:latest ---> 6.2.3

2. 配置准备工作【是为了后面便于修改配置, 而不用反反复复进入容器中】

nginx

mkdir etc

docker run --name tmp-nginx -d nginx // 临时容器
docker cp tmp-nginx:/etc/nginx $PWD/etc/nginx // 拷贝容器文件到本机制定目录下
docker rm -f tmp-nginx // 拷贝完成,删除容器

插入:

如果只要nginx容器,执行如下命令即可, 将相关资源放到/Users/williamning/Workspace/www下即可,浏览器输入:localhost就已经可以访问资源了

docker run --name run-nginx -d -p 80:80 -v $PWD/www:/usr/share/nginx/html:ro nginx

docker rm -f run-nginx

php-fpm

docker run --name tmp-php-fpm -d php:7.4-fpm
docker cp tmp-php-fpm:/usr/local/etc $PWD/etc/php
docker rm -f tmp-php-fpm

配置php-fpm与nginx配合工作

编辑文件 etc/nginx/conf.d/default.conf

加入如下部分:

location ~ \.php$ {
    fastcgi_pass   run-php-74-fpm:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  /var/www/html$fastcgi_script_name;
    include        fastcgi_params;
}

3. 实例化容器

顺序:[因为前后有依赖【link】关系]

mysql-->redis-->php-fpm-->nginx

mysql

mkdir mysql && cd mysql
mkdir conf && mkdir logs && mkdir data

docker run \
    --name run-mysql-80 \
    -p 33060:3306 \
    -e MYSQL_ROOT_PASSWORD=root \
    -v $PWD/conf:/etc/mysql/conf.d \
    -v $PWD/logs:/logs \
    -v $PWD/data:/var/lib/mysql \
    -d mysql:8.0

cd ..  // 回到工作目录

Note:

这里使用33060端口,因3306端口已为其他容器使用~~

redis

docker run \
    --name run-redis-latest \
    -p 6379:6379 \
    -d redis:latest

php-fpm

docker run \
    --name run-php-74-fpm \
    -v $PWD/www:/var/www/html \
    -v $PWD/etc/php:/usr/local/etc \
    -v $PWD/log/php:/var/log/php \
    -d php:7.4-fpm

nginx

docker run \
    --name run-nginx-latest \
    -p 8080:80 \
    -v $PWD/www:/usr/share/nginx/html \
    -v $PWD/etc/nginx:/etc/nginx \
    -v $PWD/log/nginx:/var/log/nginx \
    --link run-php-74-fpm:php-fpm-container \
    --link run-redis-latest:redis \
    --link run-mysql-80:mysql \
    -d nginx:latest

Note:

A. 这里使用8080端口,因80端口已为其他容器使用~~

B. 容器已经全部实例化,如下

C. 此时,各个容器均能单独工作, 尚不能完全协作

D. mysql/redis均能通过可视化工具正常连接

E. windows下, 简要截图如下, 注意,如果从上面直接拷贝命令执行, 换行的地方可能会出现编码异常的问题, 需要手动处理下空格,换行

4. 安装php扩展

因这里要使用pdo-mysql,redis扩展去连接mysql, redis server, 但php-fpm官方镜像并没有默认安装, 需要自行安装

进入php-fpm容器

docker exec -it e3c79200f9ef76d231e5df2d55533969bfe4b0ffd02aa4813e69a1043e8e30fa /bin/sh

安装 pdo-mysql

在/Users/williamning/Workspace/etc/php/php/conf.d【即容器中的/usr/local/etc/php/conf.d】下新建docker-php-ext-pdo_mysql.ini文件,

文件内容:

extension=pdo_mysql.so

执行安装命令:

docker-php-ext-install pdo_mysql

通过命令确认

php -m 或者 php -r 'phpinfo();' | grep pdo_mysql

安装redis

pecl install redis-5.3.4 && docker-php-ext-enable redis

如果出现

enable igbinary serializer support? [no] :   

输入:yes, 后面又出现两个提示, 同样输入yes,结果出现报错,原因:TBD

详情参考:

enable igbinary serializer support? · Issue #1196 · phpredis/phpredis · GitHub

这里先统一设置为no,重新安装

pecl install -n redis-5.3.4 && docker-php-ext-enable redis

同理新建

/Users/williamning/Workspace/etc/php/php/conf.d/docker-php-ext-redis.ini

内容:

extension=redis.so

通过命令确认

php -m 或者 php -r 'phpinfo();' | grep redis

然后,重启php-fpm容器

否则,在后面测试mysql/redis会分别提示,没有driver,没有Redis class

5. 开始测试lnmp服务

web根目录下新建文件列表如下:

测试html资源访问

测试php脚本

测试phpinfo

测试PDO连接mysql

测试连接redis

目前看来,一切正常~~

优化:

建议使用shell脚本去尽量自动化处理~~

方式二: network方式

项目代码:

https://gitee.com/william_ning/docker-lnmp-pickup

运行后的目录结构: https://gitee.com/william_ning/docker-lnmp-dev-env-sh

同时结合docker-compose进行优化,同时开启/关闭/移除容器

步骤:

1. 克隆项目到工作目录【任一目录即可】

2. 执行shell脚本

./lnmp-preprare.sh

3. 一键式启动容器

docker-compose up -d

4. 继续执行启动容器后的安装php扩展

执行命令, ./lnmp-after-up-containers.sh

5. 浏览器中分别开窗口访问如下地址:

localhost:8080

localhost:8080/index.php

localhost:8080/phpinfo.php

localhost:8080/pdo.php

localhost:8080/redis.php

不出意外,一切正常~~ 到此Over~

6. 不使用时,移除即可

docker-compose dowm

推荐使用命令 // 因为 Docker Compose is now in the Docker CLI, try `docker compose up

docker compose up -d

docker compose down

----------------------------------------------------------------分割线----------------------------------------------------------------

踩坑与过程简要记录:

添加执行权限

2.jenkins构建过程中添加docker容器判断是否启动的功能 - 简书 // jenkins构建过程中添加docker容器判断是否启动的功能

Shell 教程 | 菜鸟教程 // Shell 教程

【Linux】grep 匹配多个关键字_媛测的博客-CSDN博客_grep或的多个匹配项 // 【Linux】grep 匹配多个关键字

用sed、awk、grep同时匹配多个条件(与模式、或模式) - 陌上归人的博客 - 博客园 // 用sed、awk、grep同时匹配多个条件(与模式、或模式)

grep无法查找shell传过来的变量?先注意一下文本格式吧! - 云+社区 - 腾讯云 // grep无法查找shell传过来的变量?先注意一下文本格式吧!

踩坑截图

解决完:正常

执行docker-compose up -d

一直报错,如下 // 简单说,就是Version的使用姿势不对

ERROR: Version in "./docker-compose.yml" is invalid. You might be seeing this error because you're using the wrong Compose file version. Either specify a supported version (e.g "2.2" or "3.3") and place your service definitions under the `services` key, or omit the `version` key and place your service definitions at the root of the file to use version 1.
For more on the Compose file format versions, see https://docs.docker.com/compose/compose-file/

----------------------------------------------------------------分割线----------------------------------------------------------------

2.2 同一个容器中, 搭建LNMP环境

TBD

优化:TBD

http://www.dockerinfo.net/docker-compose-项目 // 一个项目一个容器,这种方式个人认为更好~

3. 思考

TBD

后续补充

...

3.问题/补充

1. 如何在php7.2/php7.3中安装mcrypt扩展?

如何在php7.2/php7.3中安装mcrypt扩展?-php教程-PHP中文网

2. 如何安装pdo_mysql扩展?

docker-php-ext-install pdo pdo_mysql
出现报错,导致一直安装不成功

解决方案:
在/usr/local/etc/php目录下面新建 conf.d
也可以把 docker-php-ext-pdo_mysql.ini 文件也创建了,文件内容:

extension=pdo_mysql.so

修改完重复执行安装命令

3. 使用PDO去测试连接mysql容器服务,一直报错

SQLSTATE[HY000] [2002] No such file or directory

搜索了一些问答, 结果全是关于apache相关的问题, 而且多是使用laravel数据库出现的错误

php - PDOException SQLSTATE[HY000] [2002] No such file or directory - Stack Overflow // PDOException SQLSTATE[HY000] [2002] No such file or directory

结论就是设置, mysql的socket,php.ini中的pdo_mysql.default_socket=/tpm/mysql.sock 或者 pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock

以上操作,

但均没有效果, 而且冷静下来,想了下连接mysql server的方式, 目前为止, 个人没有用过socket方式, 至于怎么用TBD

都是使用IP+port方式进行连接, 才想明白, 可能是IP不对, 不能使用lcoalhost或者127.0.0.1本机IP,而应该使用容器分配的私有IP

查看容器IP方式

docker inspect 容器ID 

找到IPAddress即可

-- 补充

旧截图

修改IP,如上

浏览器中访问测试地址

终于访问成功~~

思考

网上资料质量参差不齐,加上个人相关知识【基础知识】薄弱, 如果找不到权威的资料去查看,学习,实践,就会花费比较多的时间去弄这件事, 而且花的时间太多却一直得不到想要的结果, 本身就是一个负反馈的过程, 不利于继续学习, 深入。

个人思考后,建议应该多学习基础知识,而且在遇到问题时, 尽量去查找相关权威资料, 不要上来就百度,而应该先花费至少五分钟思考下,最好写下来, 哪里会有这方面的权威资料, 或者请求比较权威的帮助,比如自己的技术Leader,或者有可通讯的技术大佬【不过可能回复不及时】, 

然后再去实践,同时在这个过程中,要不断思考, 尽量结合以往的知识,经验去推敲,思考验证,从步步逼近真实情况。如果能将这个过程循环往复,技能, 知识技能必会有所进益,这才是一个做技术人应该有的态度和习惯

当然更重要的是,可以节省更多时间去做更多有意义感兴趣的事情~

至于redis,使用localhost时出现报错,已经想到了,是相同的原因

解决办法,使用容器的IP即可

Fatal error: Uncaught RedisException: Connection refused in /var/www/html/redis.php:4 Stack trace: #0 /var/www/html/redis.php(4): Redis->connect('127.0.0.1', 6379) #1 {main} thrown in /var/www/html/redis.php on line 4

4. 查看容器所有的IP

docker inspect --format='{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)

可以看到容器的IP是后先后顺序的,都是172.17.0.x ....

Note

容器的IP是会变化的,要确认清楚,否则会连接失败!

解决办法

固定容器IP,具体参考:

https://sleele.com/2020/04/26/docker-compose固定容器ip写法/ // docker-compose固定容器IP写法

Docker 容器固定 IP - Yogile - 博客园. // Docker 容器固定 IP

5. 容器环境下,在物理机中执行数据库迁移命令,报如下错,分析报错信息,可初步判断是连接被拒绝,

应该是连接配置信息不正确导致的。

➜  laravel7.test git:(master) ✗ php72 artisan migrate

   Illuminate\Database\QueryException 

  SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = laravel7.test and table_name = migrations and table_type = 'BASE TABLE')

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:671
    667|         // If an exception occurs when attempting to run a query, we'll format the error
    668|         // message to include the bindings with SQL, which will make this exception a
    669|         // lot more helpful to the developer instead of just the database's errors.
    670|         catch (Exception $e) {
  > 671|             throw new QueryException(
    672|                 $query, $this->prepareBindings($bindings), $e
    673|             );
    674|         }
    675| 

      +36 vendor frames 
  37  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

这里是因为项目代码中使用的DB_HOST使用的是容器IP「仅仅是用于容器之间的通信」,但是在物理机环境下,是识别不到该地址的。

所以,解决办法:

进入到php-fpm容器中,执行迁移命令

到容器中执行命令,依然失败,说明配置还是有问题

最后发现你是容器的IP发生变化,修改为争取的IP即可 -- 上面的方式,存在一个问题:IP在重启容器的时候,可能会发生变化,这就导致,需要重新配置DB,Redis 的IP  --- 解决办法:TBD

优化:

更好的解决办法TBD

6. Nginx 和 PHP-FPM容器中执行PS命令提示命令不存在

原因:该nginx等镜像没有打包ps命令

使用如下命令安装

apt-get update && apt-get install procps

再执行PS命令如下:

PHP-FPM

Nginx

7. docker修改redis配置文件

推荐还是像mysql,nginx,php-fpm那样将redis的配置文件挂载到外部文件系统

单独实例化 redis容器:

sudo docker run -p 6379:6379 \

--name redis -v /data/redis/redis.conf:/etc/redis/redis.conf \

-v /data/redis/data:/data \

-d redis redis-server /etc/redis/redis.conf \

--appendonly yes

docker修改redis配置文件_城北码农的博客-CSDN博客_docker修改redis配置文件

目前先基于当前的环境,进入容器进行下修改:

找到redis的安装路径,以及配置

root@9e80a893b099:/usr/local/bin# ls

docker-entrypoint.sh  gosu  redis-benchmark  redis-check-aof  redis-check-rdb  redis-cli  redis-sentinel  redis-server

root@9e80a893b099:/usr/local/bin# pwd

/usr/local/bin

root@9e80a893b099:/usr/local/bin#

但是没有找到redis的配置文件

Docker Hub

根据docker官方redis镜像文档说明,可以知道,如果实例化redis容器时,没有指定redis.conf

则容器并没有redis.conf文件,那么现在的解决方案有两种:

1. 手动下载一个redis.conf文件,并且重启redis容器并加载redis.conf配置文件

2. 重新实例化一个redis容器。

redis.conf文件下载地址

Redis configuration | Redis

这里是6.2.4

https://raw.githubusercontent.com/redis/redis/6.2/redis.conf

终端curl下载

或者

浏览器打开,然后全选复制

这里先采用方式一:「不推荐,这里只是作为临时方案」
ssh到远程服务器,进入redis容器中,

进入指定目录下,创建redis.conf

复制之前redis.conf内容到该文件中「走网络传输」

记得配置

requirepass your-password

/usr/local/etc/redis/redis.conf

Note:

docker容器中「当然要根据自己操作系统来定,不过可以多试试」

安装vim:

apt-get update && apt-get install vim

安装ps命令:apt-get update && apt-get install procps

在容器中启动redis服务

 可以看到启动./redis-server出现警告和报错,因为:

1. 「警告」没有指定配置文件

2. 「报错」端口已经占用「因为redis服务已经有一个启动,使用的正是6379端口」

解决办法:

关掉已经启动的redis服务,同时指定我们刚添加/修改的redis配置文件

查看redis进程

root@9e80a893b099:/usr/local/bin# ps aux |grep redis

redis          1  0.1  0.3  52968 12632 ?        Ssl  03:18   0:06 redis-server *:6379

root        1066  0.0  0.0   3084   892 pts/3    S+   05:03   0:00 grep redis

root@9e80a893b099:/usr/local/bin#

「上面的数字并不是PID,导致kill失败」

root@9e80a893b099:/usr/local/bin# ps -ef           

UID          PID    PPID  C STIME TTY          TIME CMD

redis          1       0  0 03:18 ?        00:00:07 redis-server *:6379

root          19       0  0 03:20 pts/0    00:00:00 bash

root          41       0  0 03:43 pts/1    00:00:00 bash

root          89       0  0 04:29 pts/2    00:00:00 bash

root         480       0  0 04:48 pts/3    00:00:00 bash

root        1081     480  0 05:07 pts/3    00:00:00 ps -ef

root@9e80a893b099:/usr/local/bin# ps -ef | grep redis

redis          1       0  0 03:18 ?        00:00:07 redis-server *:6379

root        1083     480  0 05:07 pts/3    00:00:00 grep redis

root@9e80a893b099:/usr/local/bin# kill 1

root@9e80a893b099:/usr/local/bin# [root@MrNing ~]#

虽然成功了,但是不好意思,直接退出docker容器「容器应该是被关闭了,毕竟PID=1的进程是祖宗进程」

然后重新进入redis容器,回到了上面的问题「应是redis容器配置自动重启服务」。

如果换个端口,则没问题

重新开个终端,进入redis容器,连接6380端口的redis实例

断开ssh连接后,重新连接后,发现依然有两个redis服务,

「不过,在重启redis 容器后,应该就只会剩下一个,就是6379端口的redis服务」

kill 6380端口的redis server,并没有退出redis容器。

重启redis容器,然后进入redis容器中,如下

说明与学习:

1. 因为服务器并没有暴露6380端口,以及映射端口到容器‘

2. 说明redis docker容器也可以同时实例化多个redis服务「容器本质上也是提供了一个环境,即容器,内部还是通过软件的形式发挥作用」。

方式一目前失败了「或者说暂时不再深入下去」

只能采用方式二进行解决了

修改docker-compose.yml文件中redis的配置

TBD

8. 升级了docker版本之后,通过docker desktop点击启动docker compose出现报错

这里通过命令可以正常启动:docker-compose up -d

原因TBd

4.参考

Docker - 学习/实践_穿素白衫的少年的博客-CSDN博客 // 所需文档

Docker 入门教程 - 阮一峰的网络日志 //  再放一次, 推荐阅读~~~

避坑!用Docker搞定PHP开发环境搭建 // 避坑!用Docker搞定PHP开发环境搭建  -- 20210424 周六 公寓

https://sleele.com/2020/04/26/docker-compose固定容器ip写法/ // docker-compose固定容器IP写法

Docker 容器固定 IP - Yogile - 博客园. // Docker 容器固定 IP

后续补充

...

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值