Alibaba Cloud Linux 3 +Docker 部署 ThinkPHP6 (宝塔环境)
在使用 Docker 部署 ThinkPHP6 并适配宝塔环境时,遇到很多问题。本文整理了实战中具体的操作步骤,至于遇到的错误及解决方案后边再补充。(结合实际这种部署有点繁琐,后期维护管理比较复杂,所以这里只用于Docker学习,不建议这样搭建生产环境。)
一、环境说明
- 宿主机:安装宝塔面板的 Linux 服务器
- 容器环境:PHP 8.1-FPM
- 框架:ThinkPHP6
- 部署方式:Docker + Docker Compose
宿主机已通过宝塔面板安装 Nginx、PHP、MySQL ,我这里并没有重复容器化整套 LNMP 环境(避免端口冲突和资源浪费),采用的是 “部分容器化”方案:仅将 ThinkPHP6 应用与 PHP-FPM 容器化,同时复用宿主机宝塔管理的 Nginx(处理反向代理)和 MySQL(数据库)。
容器化需遵循 “不占用宿主机已用端口、通过挂载目录同步代码、配置网络互通” 原则,核心架构如下:
宿主机(安装宝塔面板)
├─ 1. Nginx(占用 80/443 端口,作为前端Web服务器)
├─ 2. MySQL(占用 3306 端口,独立运行在宿主机)
└─ 3. Docker 容器(运行 ThinkPHP6 + PHP-FPM)
├─ 目录挂载:将宿主机项目目录 /www/wwwroot/tp6 挂载到容器内目录(如 /var/www/html),实现代码实时同步
├─ 端口配置:暴露容器内 PHP-FPM 监听端口(如 9003),与宿主机 PHP-FPM 端口(默认 9000)错开,避免冲突
└─ 数据库连接:通过“宿主机内网IP”(如 172.18.0.1,Docker 默认网桥网关)或“宿主机真实内网IP”(如 192.168.1.100)连接宿主机 MySQL
二 、前置准备:宿主机环境检查与配置
1. 确认宝塔服务状态
通过宝塔面板或命令行确认 Nginx、MySQL 正常运行:
# 宝塔命令行工具查看服务状态
# 确保 Nginx、MySQL 显示“运行中”
bt status# 查看宿主机 PHP-FPM 端口(避免容器端口冲突)
# 如显示 9000、9001,容器需用其他端口(如 9002)
netstat -tulnp | grep php-fpm
2. 准备 ThinkPHP6 项目目录
在宝塔默认网站目录创建项目(便于宝塔管理):
# 1. 创建目录并克隆 ThinkPHP6 源码(Gitee 镜像)
mkdir -p /www/wwwroot/tp6 && cd /www/wwwroot/tp6
git clone https://gitee.com/top-think/think.git .# 确认 Composer 路径
# 输出可能为 /usr/local/bin/composer
which composer
#获取composer版本
#输出结果:Composer version 2.8.11 PHP version 8.1.32
/usr/bin/composer --version# 进入项目目录,用 PHP 8.1 执行
cd /www/wwwroot/tp6#安装ThinkPHP6项目依赖
/www/server/php/81/bin/php $(which composer) install --no-dev
调整目录权限(宝塔默认www用户,避免容器读写权限问题)
chown -R www:www /www/wwwroot/tp6
chmod -R 755 /www/wwwroot/tp6
chmod -R 777 /www/wwwroot/tp6/runtime /www/wwwroot/tp6/public/uploads
3. 授权 MySQL 允许容器访问
容器内应用需连接宿主机 MySQL,需通过宝塔授权 “容器所在内网 IP” 访问:
- 登录宝塔面板 → 数据库 → 对应数据库(如
tp6_db
)→ 权限管理; - 新增授权:
- 用户名:
tp6_user
(自定义); - 密码:
Tp6@123456
(自定义); - 授权主机:填写 宿主机内网 IP(如
172.18.0.1
,Docker 默认网桥网关,可通过ip addr show docker0
查看);
- 用户名:
ip addr show docker0
#运行结果
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:3e:7e:6a:ac brd ff:ff:ff:ff:ff:ffinet 172.18.0.1/16 brd 172.18.255.255 scope global docker0valid_lft forever preferred_lft foreverinet6 fe80::42:3eff:fe7e:6aac/64 scope link valid_lft forever preferred_lft forever
使用 172.18.0.1
这个网关地址设置数据库访问权限:
三、容器化配置:仅容器化 ThinkPHP6 + PHP-FPM
在项目目录 /www/wwwroot/tp6
下创建 Docker 相关文件,仅定义 PHP-FPM 容器(复用宿主机 Nginx/MySQL)。
1. 创建 Dockerfile(仅构建 PHP-FPM 环境)
无需包含 Nginx 和 MySQL,仅需适配 ThinkPHP6 所需的 PHP 扩展:
# 基础镜像:PHP 8.1-FPM(与宿主机宝塔 PHP 版本一致,避免语法兼容问题)
FROM php:8.1-fpm# 使用阿里云镜像源加速
RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list && \sed -i 's/security.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list# 修改 www-data 用户的 UID/GID 为 1000(匹配宿主机 www 用户)
RUN usermod -u 1000 www-data && groupmod -g 1000 www-data# 安装 ThinkPHP6 必需扩展(gd、pdo_mysql 等)
RUN apt-get update && apt-get install -y \curl \wget \iproute2 \net-tools \procps \libfreetype6-dev \libjpeg62-turbo-dev \libpng-dev \libzip-dev \&& rm -rf /var/lib/apt/lists/* # 安装 PHP 扩展(分开步骤避免失败)
RUN docker-php-ext-configure gd --with-freetype --with-jpeg
RUN docker-php-ext-install -j$(nproc) gd pdo_mysql mysqli zip opcache# 安装 Composer(使用国内镜像)
RUN curl -sS https://install.phpcomposer.com/installer | php -- --install-dir=/usr/local/bin --filename=composer && \composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/# 配置 PHP-FPM 监听端口(使用自定义配置文件)
RUN echo '[global]' > /usr/local/etc/php-fpm.conf && \echo 'error_log = /proc/self/fd/2' >> /usr/local/etc/php-fpm.conf && \echo 'daemonize = no' >> /usr/local/etc/php-fpm.conf && \echo 'include=/usr/local/etc/php-fpm.d/*.conf' >> /usr/local/etc/php-fpm.conf# 关键修复:先备份并清空默认配置,然后创建自定义配置
RUN cp /usr/local/etc/php-fpm.d/www.conf /usr/local/etc/php-fpm.d/www.conf.backup && \echo '[www]' > /usr/local/etc/php-fpm.d/www.conf && \echo 'listen = 9003' >> /usr/local/etc/php-fpm.d/www.conf && \echo 'user = www-data' >> /usr/local/etc/php-fpm.d/www.conf && \echo 'group = www-data' >> /usr/local/etc/php-fpm.d/www.conf && \echo 'pm = dynamic' >> /usr/local/etc/php-fpm.d/www.conf && \echo 'pm.max_children = 50' >> /usr/local/etc/php-fpm.d/www.conf && \echo 'pm.start_servers = 5' >> /usr/local/etc/php-fpm.d/www.conf && \echo 'pm.min_spare_servers = 5' >> /usr/local/etc/php-fpm.d/www.conf && \echo 'pm.max_spare_servers = 10' >> /usr/local/etc/php-fpm.d/www.conf# 删除可能冲突的自定义配置文件
RUN rm -f /usr/local/etc/php-fpm.d/zz-docker.conf# 配置 PHP 时区
RUN echo 'date.timezone = Asia/Shanghai' > /usr/local/etc/php/conf.d/timezone.ini# 设置工作目录(与宿主机项目目录对应,后续通过挂载同步代码)
WORKDIR /var/www/html# 先复制所有项目文件
COPY . .# 安装 PHP 依赖
RUN composer install --no-dev --optimize-autoloader --no-scripts# 设置文件权限
RUN chown -R 1000:1000 /var/www/html \&& chmod -R 755 /var/www/html \&& chmod 644 /var/www/html/public/index.php \&& chmod -R 777 /var/www/html/runtime /var/www/html/public/uploads# 暴露自定义 PHP-FPM 端口(9003)
EXPOSE 9003CMD ["php-fpm"]
2. 创建 docker-compose.yml(简化版,仅管理 PHP-FPM 容器)
无需定义 Nginx 和 MySQL 服务,仅启动 PHP-FPM 容器,并挂载宿主机项目目录:
services:tp6-php-fpm:build: . # 基于当前目录 Dockerfile 构建restart: novolumes:# 挂载宿主机项目目录到容器(实时同步代码,宿主机修改后容器立即生效)- /www/wwwroot/tp6_study_web:/var/www/htmlports:# 宿主机端口 9003 → 容器端口 9003(避免冲突)- "9003:9003"# 关键:指定容器运行用户(UID 1000 对应宿主机 www 用户)user: "1000:1000"
四、配置宿主机宝塔 Nginx:反向代理到容器
通过宝塔面板配置 Nginx,将请求转发到容器内的 PHP-FPM(无需在容器内启动 Nginx)。
1. 宝塔创建站点
- 登录宝塔面板 → 网站 → 添加站点;
- 填写基本信息:
- 域名:如
tp6.example.com
(或直接用服务器 IP);- 根目录:选择
/www/wwwroot/tp6/public
(ThinkPHP 入口目录);- PHP 版本:选择 “纯静态”(因为 PHP 解析交给容器,避免宿主机 PHP 干扰);
- 点击 “提交”,创建站点。
2. 修改 Nginx 配置:反向代理 PHP 请求到容器
- 进入站点 → 配置文件 → 修改 “Nginx 配置”;
- 找到
location ~ \.php$
块,替换为以下内容(转发到容器 PHP-FPM):
# 处理 PHP 请求:转发到容器 PHP-FPM(宿主机 9003 端口)
location ~ \.php$ {# 容器 PHP-FPM 地址(替换为你的容器 IP)fastcgi_pass 127.0.0.1:9003;fastcgi_index index.php;# 容器内的项目路径(与 Docker 挂载路径对应)fastcgi_param SCRIPT_FILENAME /var/www/html/public$fastcgi_script_name; include fastcgi_params;
}# 处理静态资源:直接返回(复用宿主机 Nginx 静态资源处理能力)
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg)$ {root /www/wwwroot/tp6/public; # 宿主机静态资源目录expires 30d;access_log off;
}# ThinkPHP URL 重写(美化路由)
location / {root /www/wwwroot/tp6/public;if (!-e $request_filename) { # 只有文件/目录不存在时,才重写rewrite ^(.*)$ /index.php?s=$1 last;break;}
}
3、点击 “保存”,并重启 Nginx(宝塔面板 → 服务 → Nginx → 重启)。
五、启动容器并测试
1. 启动 PHP-FPM 容器
在项目目录 /www/wwwroot/tp6
执行命令:
# 构建镜像并启动容器(-d 后台运行)
docker-compose up -d --build
# 查看容器状态(确保 tp6-php-fpm 为 Up 状态)
docker-compose ps
# 查看容器日志(排查 PHP 扩展缺失、MySQL 连接失败等问题)
docker logs tp6-tp6-php-fpm-1
2. 测试访问与数据库连接
(1)访问 ThinkPHP6 首页
在浏览器输入站点域名 / IP(如 http://tp6.xiaocaizhang.fun),若看到 ThinkPHP 欢迎页面,说明 Nginx 反向代理和容器 PHP-FPM 正常。
(2)测试数据库连接
修改 ThinkPHP6 配置文件 .env
,连接宿主机 MySQL:
APP_DEBUG = trueDB_TYPE = mysql
DB_HOST = 172.18.0.1
DB_NAME = tp6_user
DB_USER = tp6_user
DB_PASS = mW3ekrY3MDmTzGzS
DB_PORT = 3306
DB_CHARSET = utf8DEFAULT_LANG = zh-cn
创建测试控制器 app/controller/Test.php
,验证数据库连接:
<?php
namespace app\controller;use think\Db;
use app\BaseController;class Test extends BaseController
{public function index(){// 测试创建表并插入数据Db::execute("CREATE TABLE IF NOT EXISTS test (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(50) NOT NULL,create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP)");Db::name('test')->insert(['name' => '宝塔+容器混合部署测试']);$data = Db::name('test')->select();return json($data);}
}
访问 tp6.xiaocaizhang.fun/index/test,若返回 JSON 数据,说明数据库连接成功。
部署中遇到了很多问题,后边我再编写笔记。