用 docker 代替宝塔托管 php

最近要维护一个 php 站点,需要运行 wp 和其他一些插件、服务。为了精简运维和减少负载,尝试使用 docker 代替宝塔。

官方的 php 镜像无法安装一些模块,这里用编译安装。编译后的二进制文件映射到基础容器中运行,二进制文件放 git 库里做版本控制;这是为了避免自建 docker 源或导出、传输不受版本控制的 docker 镜像,有自己源的朋友建议用源。

下面是操作流程:

1、运行编译容器

编译可能遇到各种问题,这样更容易调试。在容器中编译避免“弄脏”本地环境。

1
docker run -it --rm -v `pwd`/php74:/usr/local/php74 debian:bullseye  bash

2、安装依赖

1
2
3
4
apt update && apt install -y libxml2-dev libssl-dev \
libsqlite3-dev zlib1g-dev libcurl4-openssl-dev \
libpng-dev libwebp-dev libjpeg-dev libfreetype-dev \
libonig-dev libxml2-dev wget gcc g++ pkg-config

3、下载和编译 php

1
wget https://www.php.net/distributions/php-7.4.28.tar.gz && tar zxf php-7.4.28.tar.gz && cd php-7.4.28
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
./configure --prefix=/usr/local/php74 \
--with-config-file-path=/usr/local/php74/etc \
--enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data \
--enable-mysqlnd --with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd --with-iconv-dir --with-freetype \
--with-jpeg --with-zlib --enable-xml \
--disable-rpath --enable-bcmath --enable-shmop --enable-sysvsem \
--enable-inline-optimization --with-curl --enable-mbregex \
--enable-mbstring --enable-intl --enable-pcntl --enable-ftp \
--enable-gd --with-openssl --with-mhash --enable-pcntl \
--enable-sockets --with-xmlrpc --enable-soap --with-gettext \
--disable-fileinfo --enable-opcache --with-webp

make -j 4 && make install

exit # 退出容器

执行完成后可见 php74 目录下有二进制文件。

1
2
~ ❯ ls php74/bin
phar phar.phar php php-cgi php-config phpdbg phpize

4、项目配置

二进制文件用 volumes 链接到 wp 容器中运行,用 wp 容器不需要关心链接库,减少一个 Dockerfile build 环节。

配合 nginx 和数据库,docker-compose.yaml 如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
version: "3"
services:
nginx:
image: nginx:1.22
restart: always
volumes:
# nginx 相关配置
- ./servers/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./servers/nginx/conf.d:/etc/nginx/conf.d:ro
- ./var/log/nginx:/var/log/nginx
# 项目文件映射
- ./volumes/wp:/var/www/html
ports:
- 80:80
- 443:443
depends_on:
- wp
wp:
image: wordpress:php7.4-fpm
restart: always
environment:
# 时区
- TZ=Asia/Shanghai
volumes:
# wp 相关
- ./volumes/wp:/var/www/html
- ./var/cache:/var/www/html/wp-content/cache
- ./servers/wp/wp-config.php:/var/www/html/wp-config.php:ro # 这里存了数据库账密
# 自定义 php 映射
- ./servers/php74:/usr/local/php74
- ./servers/php74/link/php:/usr/local/bin/php:ro
- ./servers/php74/link/php-fpm:/usr/local/sbin/php-fpm:ro
- ./var/log/php:/usr/local/php74/var/log

command: /usr/local/php74/sbin/php-fpm -c /usr/local/php74/etc/ -F # -F 让 php-fpm 前台运行
depends_on:
- wp-db
wp-db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: <dbname>
MYSQL_USER: <user>
MYSQL_PASSWORD: <pwd>
MYSQL_RANDOM_ROOT_PASSWORD: <pwd>
volumes:
- ./volumes/db:/var/lib/mysql
- ./volumes/dbbak:/var/backups

nginx 配置

1
2
3
4
5
6
7
location ~ \.php(.*)$ {
fastcgi_pass wp:9000;
fastcgi_index index.php;
fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
fastcgi_param SCRIPT_FILENAME $web_root$fastcgi_script_name;
include fastcgi_params;
}

后记

特别注意,不要在线上初始化 wp,我在 10 分钟内被植入了木马。

应该在本地初始化完成数据库后,将数据库传到服务器上,并禁用掉 xmlrpc.php 之类的不需要的文件。

本作品采用 知识共享许可协议 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。