宿主機nginx使用容器php-fpm處理php請求
宿主機Nginx使用php容器解析php請求
環境說明
首先,我在宿主機上已經運行了一個nginx
[root@localhost html]# nginx -v
nginx version: nginx/1.18.0
宿主機上也安裝運行了docker
[root@localhost html]# docker version
Client: Docker Engine - Community
Version: 20.10.2
...
需求:在docker裡面執行php容器,然後用php容器來解析所有訪問nginx的php請求。
基於alpine定製php-fpm容器
php官方基礎映象缺少很多擴充套件,一般情況下不滿足實際專案的執行,所以需要定製一個符合專案執行環境的php映象。
瞭解php基礎映象
php的官方映象分為三個分支:
cli
:沒有開啟CGI,也就是不能執行fpm,只能執行命令列。fpm
:開啟了CGI,可以用來執行web服務也可以執行cli命令。zts
:開啟了執行緒安全的版本。
一般來說,lnmp環境使用 fpm
即可。
映象選擇
這裡我使用的php官方映象是: php:7.3.23-fpm-alpine
。php版本為7.3.23,是基於Alpine Linux 3.12基礎映象構建的,所以映象體積會比較小。
預設官方的映象有如下擴充套件:
/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]
除了以上擴充套件,我們還需要安裝一些其他擴充套件:
- redis
- gd
- mysqli
- pdo_mysql
- opcache
- zip
- bcmatch等
構建準備
# 建立目錄 $ mkdir -p /root/docker/php $ cd /root/docker/php # 建立配置檔案目錄 $ mkdir conf.d # 設定php時區為東八區 $ echo "date.timezone = Asia/Shanghai" >> conf.d/date.ini # 設定opcode預設的引數 $ cat >> conf.d/opcode.ini << EOF opcache.enable=${OPCODE} enable_clopcache.enable_cli=1 opcache.revalidate_freq=60 opcache.max_accelerated_files=100000 opcache.validate_timestamps=1 EOF # 設定alpine的apk源為國內源 $ cat >> repositories <<EOF http://mirrors.aliyun.com/alpine/v3.12/main http://mirrors.aliyun.com/alpine/v3.12/community EOF # 準備php-fpm配置檔案 $ cat >> www.conf << EOF [www] user = www group = www listen = 0.0.0.0:9000 pm = dynamic pm.max_children = 5 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 3 EOF # 專案目錄結構如下: [root@localhost php]# tree . . ├── conf.d │ ├── date.ini │ └── opcode.ini ├── Dockerfile ├── repositories └── www.conf
最終的Dockerfile檔案如下:
FROM php:7.3.23-fpm-alpine
LABEL maintainer="syushin [email protected]"
# 設定apk源為阿里雲
COPY repositories /etc/apk/repositories
COPY ./conf.d/ $PHP_INI_DIR/conf.d/
ENV TZ "Asia/Shanghai"
ENV TERM xterm
# 預設關閉opcode
ENV OPCODE 0
# 新增使用者
RUN addgroup -g 1000 -S www && adduser -s /sbin/nologin -S -D -u 1000 -G www www
# PHPIZE_DEPS 包含 gcc g++ 等編譯輔助類庫,完成編譯後刪除
RUN apk add --no-cache $PHPIZE_DEPS \
&& apk add --no-cache libstdc++ libzip-dev vim\
&& apk update \
&& pecl install redis-4.3.0 \
&& pecl install zip \
&& pecl install swoole \
&& docker-php-ext-enable redis zip swoole\
&& apk del $PHPIZE_DEPS
# 安裝擴充套件
RUN apk add --no-cache \
freetype \
libpng \
libjpeg-turbo \
freetype-dev \
libpng-dev \
jpeg-dev \
libjpeg \
libjpeg-turbo-dev \
libwebp \
libwebp-dev \
&& docker-php-ext-configure gd --with-gd --with-webp-dir --with-jpeg-dir \
--with-png-dir --with-zlib-dir --with-freetype-dir \
&& NUMPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) \
&& docker-php-ext-install -j${NUMPROC} gd \
&& docker-php-ext-install -j${NUMPROC} pdo_mysql \
&& docker-php-ext-install -j${NUMPROC} opcache \
&& docker-php-ext-install -j${NUMPROC} bcmath \
&& docker-php-ext-install -j${NUMPROC} mysqli
# 拷貝配置檔案
COPY www.conf /usr/local/etc/php-fpm.d/www.conf
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
說明:
PHP_INI_DIR
:這個環境變數是在php的基礎映象Dockerfile中有定義PHPIZE_DEPS
:這個也是定義在基礎映象Dockerfile
中,包含了擴充套件編譯安裝時需要但是php
執行不需要的linux
軟體庫。我們需要把它們挑選出來,在編譯完擴充套件之後刪除。
構建:
# 建立構建命令指令碼檔案
$ cd /root/docker/php
$ cat >> build-comand.sh << EOF
#/bin/bash
docker build -t myphp:7.3.23-alpine .
EOF
# 執行構建
$ sh build-comand.sh
構建完成檢查
構建完成之後,進入容器,檢查定製的容器。
# 進入容器
[root@localhost php]# docker run -it --rm myphp:7.3.23 sh
/var/www/html # php -m
[PHP Modules]
bcmath
Core
ctype
curl
date
dom
fileinfo
filter
ftp
gd # 安裝的擴充套件
hash
iconv
json
libxml
mbstring
mysqli # 安裝的擴充套件
mysqlnd # 安裝的擴充套件
openssl
pcre
PDO
pdo_mysql # 安裝的擴充套件
pdo_sqlite
Phar
posix
readline
redis # 安裝的擴充套件
Reflection
session
SimpleXML
sodium
SPL
sqlite3
standard
swoole
tokenizer
xml
xmlreader
xmlwriter
Zend OPcache
zip # 安裝的擴充套件
zlib
[Zend Modules]
Zend OPcache
/var/www/html # id www # 使用者也建立了
uid=1000(www) gid=1000(www) groups=1000(www),1000(www)
# 配置檔案也拷貝進來了
/var/www/html # cat /usr/local/etc/php-fpm.d/www.conf
[www]
user = www
group = www
listen = 0.0.0.0:9000
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
這樣,一個自定義的php-fpm映象就定製完成。
Nginx使用容器php-fpm進行解析
Nginx是在宿主機上,所以先定義一個Nginx的虛擬主機配置檔案:
server{
listen 80 default_server;
server_name syushin.com;
index index.html index.htm index.php;
root /var/www/html;
location ~ \.php$
{
root /var/www/html;
include fastcgi_params;
fastcgi_pass 0.0.0.0:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
這裡,location php裡面的root很重要,這裡要填php容器中php專案所在目錄 而不是nginx宿主機的web路徑。以往的nginx和php都在同一臺機器上時不存在這個問題,現在nginx和php算是分開的,所以需要注意一下。fastcgi_param 引數配置的是nginx請求php-fpm時需要帶過去的引數,SCRIPT_FILENAME 表示fpm要執行的PHP檔案的路徑,而 $document_root的值 就是前面的 root 引數的值,所以root要配置成php容器中的php路徑。fastcgi_pass 這裡的ip地址可以使用php容器的ip,這裡我打算使用埠對映的方式啟動php容器,用宿主機9000埠對映php容器的9000埠,所以這裡直接寫 0.0.0.0:9000
了。
啟動自定義的php容器
$ docker run --itd -v /home/wwwroot/syushin:/var/www/html -p 9000:9000 --name myphp myphp:7.3.23
建立站點目錄和測試檔案
$ mkdir -p /home/wwwroot/syushin
$ cat index.php
<?php
echo phpinfo();
?>
$ nginx -t
$ nginx -s reload
瀏覽器訪問宿主機IP測試,顯示如下畫面表示此次試驗成功。