knowledge/docs/php/docker-phpfpm74.md
2024-01-23 10:44:43 +08:00

371 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 基于docker的phpfpm+nginx环境
## 简介
本文以php7.4为例介绍在具有docker环境的系统上不安装任何php相关服务完全利用docker容器来实现运行环境的搭建最后还会以ThinkPHP6.0为例演示真实项目的运行,本文中的环境可在生产环境使用。
## 准备工作
在本地创建一个工作目录,笔者的宿主机上它的位置就是`/app/dev/phpfpm-demo`。
```sh
mkdir -p /app/dev/phpfpm-demo
cd /app/dev/phpfpm-demo
```
## 制作过程
### 基础镜像
```sh
docker pull nginx:1.24
docker pull php:7.4.33-fpm-bullseye
```
其中nginx镜像不需要做更改可以直接使用而php镜像则要在基础镜像的基础上安装一些必要的依赖和扩展。
### 制作PHP镜像
#### 为PHP安装扩展
```sh
docker run --rm --name php-fpm -it -d php:7.4.33-fpm-bullseye
docker exec -it php-fpm
```
在容器内安装依赖前最好先更换一下软件源,否则可能会很慢。
```sh
cp /etc/apt/sources.list /etc/apt/sources.list.bak && echo "deb http://mirrors.aliyun.com/debian/ bullseye main non-free contrib
deb-src http://mirrors.aliyun.com/debian/ bullseye main non-free contrib
deb http://mirrors.aliyun.com/debian-security/ bullseye-security main
deb-src http://mirrors.aliyun.com/debian-security/ bullseye-security main
deb http://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib
deb-src http://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib
deb http://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib
deb-src http://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib" | tee /etc/apt/sources.list >/dev/null
```
基础php镜像中没有`redis`、`mysql`等扩展,我们要自己安装一下。在容器内可以随时用`php -m`命令查看当前已经生效的扩展
```sh
apt update && apt install -y \
# gd扩展依赖
libzip-dev libpng-dev \
# pgsql扩展依赖
libpq-dev \
# gmp扩展依赖
libgmp-dev \
# composer需要
git
# redis扩展
pecl install redis && docker-php-ext-enable redis
# mysql扩展
docker-php-ext-install pdo_mysql && docker-php-ext-enable pdo_mysql
# opcache扩展
docker-php-ext-install opcache && docker-php-ext-enable opcache
# gd扩展
docker-php-ext-install gd && docker-php-ext-enable gd
# zip扩展
docker-php-ext-install zip && docker-php-ext-enable zip
# xlswriter扩展超高速读写excel文件
pecl install xlswriter && docker-php-ext-enable xlswriter
# pgsql扩展连接postgres数据库
docker-php-ext-install pdo_pgsql && docker-php-ext-enable pdo_pgsql
# gmp扩展
docker-php-ext-install gmp && docker-php-ext-enable gmp
# 安装composer
php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');" && php composer-setup.php && php -r "unlink('composer-setup.php');" && mv composer.phar /usr/local/bin/composer
```
以上是笔者经历过的项目中比较常用的扩展,如果还有其他需要,可以按照类似的方式安装。
最后一切完毕后就可以离开容器了:
```sh
exit
```
另外,我们需要知道几个关键路径:
- php.ini文件所有路径`/usr/local/etc/php/php.ini`
- 应用路径:`/var/www/html`
这两个路径我们未来要采用映射的方式从项目目录映射到容器内,因此不需要在容器内做什么动作了。
如果在自己的宿主机中没有现成的`php.ini`文件,可以从容器内复制出来一份:
```sh
# 开发环境建议
docker cp php-fpm:/usr/local/etc/php/php.ini-development ./php.ini
# 生产环境建议
docker cp php-fpm:/usr/local/etc/php/php.ini-production ./php.ini
```
#### 保存PHP镜像
```sh
docker commit php-fpm php-fpm:7.4
```
以后我们要使用的就是这个新创建的镜像,如果有`hub.docker.com`网站的账号,可以使用`docker push`命令把这个镜像上传到自己的docker hub上方便以后在其他地方使用。
现在我们刚才启动的镜像已经不再需要了,直接删除就行。
```sh
# 启动时已经使用了--rm参数所以容器被关闭就会自动删除
docker stop php-fpm
```
### 准备nginx配置文件
我们直接启动nginx容器然后从容器是把配置文件复制到宿主机上。
```sh
# 当前目录是宿主机上的工作目录
mkdir nginx
docker run --rm --name php-fpm-nginx -it -d nginx:1.24
docker cp php-fpm-nginx:/etc/nginx/nginx.conf ./nginx/
docker cp php-fpm-nginx:/etc/nginx/conf.d ./nginx/
dorker stop php-fpm-nginx
```
现在我们已经准备好了`nginx:1.24`镜像和`php-fpm:7.4`镜像,已经具备工作条件,下面就开始使用。
## 环境与配置
到目前为止,我们已经有两个镜像:`nginx:1.24`和`php-fpm:7.4`,同时工作目录`/app/dev/phpfpm-demo`中的目录结构如下:
|目录或文件|说明|
|---|---|
|php.ini|PHP环境的配置文件|
|nginx|Nginx的配置文件目录|
|nginx/nginx.conf|nginx的主配置文件|
|nginx/conf.d|nginx下的站点配置目录|
现在我们已经把环境准备好了,接下来准备一个可以一键启动的`docker-compose.yml`文件再修改一些nginx的配置就可以了。
`docker-compose.yml`文件:
```yml
version: "3.1"
services:
php:
image: php-fpm:7.4
container_name: php74
restart: always
volumes:
- ./php.ini:/usr/local/etc/php/php.ini
- ./:/var/www/html
stdin_open: true
nginx:
image: nginx:1.24
container_name: phpnginx
restart: always
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf.d:/etc/nginx/conf.d
- ./:/usr/share/nginx/html
stdin_open: true
ports:
- 8008:80
depends_on:
- php
```
简单解读一下:
- 把当前工作目录中的`php.ini`文件映射到php容器对应的路径上。
- 把当前上作目录映射到php容器中的默认站点根目录上。
- 把当前工作目录中的nginx配置文件映射到nginx容器对应的路径上。
- 把当前工作目录映射到nginx容器中的默认站点根目录上。
- 把nginx容器的80端口映射到宿主机上的8008端口上可以自己改
- nginx容器和php容器都不使用host网络而是自己组成一个私有网络。
接下来我们去修改nginx的配置文件只需要修改`nginx/conf.d/default.conf`这一个文件即可,在里面加入下面这一段:
在`location /`段中添加`index.php`
```conf
location / {
root /usr/share/nginx/html;
index index.html index.htm index.php;
}
```
然后再添加下面一段:
```conf
location ~ \.php$ {
fastcgi_pass phpfpm74:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
include fastcgi_params;
}
```
接下来,我们在站点根目录上创建一个`index.html`文件:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>欢迎</title>
</head>
<body>
<h1>Hello, web</h1>
</body>
</html>
```
再创建一个`phpinfo.php`文件:
```php
<?php
phpinfo();
```
接下来,在工作目录上,直接运行下面的命令:
```sh
docker compose up -d
```
看到容器启动成功。
- 用浏览器访问`http://ip:8008`应该可以看到我们刚才创建的`index.html`中的内容。
- 用浏览器访问`http://ip:8008/phpinfo.php`应该可以看到我们刚才创建的`phpinfo.php`中的内容也就是php服务的参数页。
现在一个基于docker的nginx+php-fpm环境已经制作好了任何支持docker的环境都可以直接使用。
## 高级应用
### 在宿主机使用composer命令
目前假设我们的宿主机没有php环境那么如果我们执行`composer create-project topthink/think:6.0.* tp`时,那自然会得到`composer: command not found`的结果这不是我们想要的结果解决办法也很简单——做个直接进入容器执行composer命令的脚本就行了。
> 下面的操作只适用于linux系统如果是windows系统的话可以按照这个思路做`composer.bat`批处理文件。
```sh
touch composer
```
编辑`composer`脚本内容如下:
```shell
#!/bin/bash
docker compose run --rm webman-jsonrpc composer $@
```
给文件添加执行权限:
```sh
chmod +x composer
```
现在就可以使用这个`composer`脚本了:
```sh
./composer create-project topthink/think:6.0.* think
```
网络正常的情况下,我们应该会看到工作目录下已经出现的`tp`文件夹打开就会看到完整的thinkphp项目目录。
### 开发ThinkPHP项目
下面我们整理一下工作目录结构:
```sh
mv tp/* .
mv tp/.* .
rm -rf tp
```
接下来我们再修改一下nginx配置文件来支持thinkphp的伪静态再把nginx站点目录和php站点目录指向到工作路径的pulic目录下。
编辑`nginx/conf.d/default.conf`文件如下:
```conf
location / {
root /usr/share/nginx/html/public/;
index index.html index.htm index.php;
try_files $uri $uri/ /index.html last;
if (!-e $request_filename){
rewrite ^(.*)$ /index.php?s=$1 last; break;
}
}
location ~* (runtime|app)/{
return 403;
}
location ~ \.php$ {
fastcgi_pass phpfpm74:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/html/public/$fastcgi_script_name;
include fastcgi_params;
}
```
现在再次在工作目录中用docker compose启动容器就可以启动这个tp项目了
```sh
docker compose up -d
```
再次在浏览器中打开`http://ip:8008`可以看到tp的欢迎页面了。
最后别忘了给`runtime`目录修改一个所有者,否则项目运行还是会出问题:
```sh
chown www-data:www-data -R runtime
```
### 在宿主机使用php命令
和制作`composer`脚本一样,我们同样可以通过制作名为`php`的脚本来实现在工作目录中使用`./php`命令来代替`php`命令:
```sh
touch php
```
编辑`php`脚本内容:
```shell
#!/bin/bash
docker compose run --rm php php "$@"
```
给脚本执行权限:
```sh
chmod +x php
```
使用脚本:
```sh
./php think make:controller Test
```
看到`Controller:app\controller\Test created successfully.`结果后,就可以看到工作目录下的`app\controller`目录中已经出现`Test.php`文件了。
## 一键完成
以上是搭建这样一套环境的整个过程,按照以上过程,已经做好了现成的一套代码库,可以直接使用:
```sh
git clone https://git.wandoubaba.com/wandoubaba/docker-tp6-php74.git tp-project
cd tp-project
git remote remove origin
./composer install
chown www-data:www-data -R runtime
docker compose up -d
```