From f461fe93f0c289fc068b56755fa2a6eff328a74b Mon Sep 17 00:00:00 2001 From: ZF sun <34314687@qq.com> Date: Thu, 25 Dec 2025 09:34:07 +0800 Subject: [PATCH] =?UTF-8?q?chore(docker):=20=E6=9B=B4=E6=96=B0docker?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=EF=BC=8C=E8=A7=A3=E5=86=B3=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E7=9A=84=E6=89=A7=E8=A1=8C=E6=AD=A5=E9=AA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 8 +- docker/php/entrypoint.sh | 221 ++++-------------------------------- docker/php/supervisord.conf | 9 -- 3 files changed, 27 insertions(+), 211 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index ed5a4b8d2..bfd6b3427 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,9 +25,13 @@ services: # 不然,ThinkPHP 6.x 系列,会只加载 .env 文件,而不会加载 .env.local 文件,导致 .env.local 文件中的配置不会生效 APP_ENV: ${APP_ENV:-development} APP_DEBUG: ${APP_DEBUG:-true} + # PHP应用根目录(可选,默认 /var/www/html) + PHP_APP_ROOT: ${PHP_APP_ROOT:-/var/www/html} + # 用户ID映射(可选,用于解决挂载权限问题) + USER_ID: ${USER_ID:-33} + GROUP_ID: ${GROUP_ID:-33} volumes: - - ./:/var/www/all_source - - ./src:/var/www/html + - ./src:/var/www/html:rw # 更新下载源列表以加速apt-get - ./docker/debian/sources.list:/etc/apt/sources.list:ro - ./docker/php/php.ini:/usr/local/etc/php/php.ini:ro diff --git a/docker/php/entrypoint.sh b/docker/php/entrypoint.sh index a892fde5a..f7673736b 100644 --- a/docker/php/entrypoint.sh +++ b/docker/php/entrypoint.sh @@ -18,219 +18,40 @@ fi echo "当前用户: $(whoami)" echo "UID: $(id -u), GID: $(id -g)" -# 修复目录所有权和权限 -fix_directory_permissions() { - local dir=$1 - echo "修复PHP目录权限: $dir" - - # 确保目录存在 - mkdir -p "$dir" + +# 修复所有目录权限(处理挂载覆盖问题,一次性处理) +if [ -d "$APP_ROOT" ]; then + echo "修复应用目录权限(处理 Docker 挂载覆盖问题)" # 设置所有权 - chown -R www-data:www-data "$dir" + chown -R www-data:www-data "$APP_ROOT" - # 设置权限 - chmod -R 775 "$dir" + # 设置目录权限和setgid + find "$APP_ROOT" -type d -exec chmod 775 {} \; + find "$APP_ROOT" -type f -exec chmod 664 {} \; + find "$APP_ROOT" -type d -exec chmod g+s {} \; - # 设置setgid权限 - chmod g+s "$dir" - - # 尝试设置ACL(如果支持) + # 设置ACL(如果支持) if command -v setfacl >/dev/null 2>&1; then - setfacl -dR -m u:www-data:rwx "$dir" + setfacl -dR -m u:www-data:rwx "$APP_ROOT" 2>/dev/null || echo "ACL 设置失败,继续执行" fi - - find "$dir" -type d -exec chmod 775 {} \; - find "$dir" -type f -exec chmod 775 {} \; - find "$dir" -type d -exec chmod g+s {} \; - find "$dir" -type f -exec chmod g+s {} \; # 设置umask umask 0002 + + echo "✅ 应用目录权限修复完成" - echo "✅ $dir 权限设置完成, 目录权限: $(stat -c '%a %n' "$dir"), setgid权限: $(stat -c '%a %n' "$dir" | grep 's')" -} - - -# 处理所有需要权限的目录 -directories=("addon" "app" "config" "extend" "public" "runtime" "upload" "runtime/log" "runtime/cache" "runtime/temp") -for dir in "${directories[@]}"; do - fix_directory_permissions "$APP_ROOT/$dir" -done - - -# 验证权限 -echo "=== 权限验证 ===" -echo "当前用户: $(whoami)" -echo "当前UID: $(id -u), GID: $(id -g)" -echo "当前umask: $(umask)" - -# 验证www-data用户是否可以在runtime和upload目录下新建子目录 - -# 方法1:使用sudo -if command -v sudo >/dev/null 2>&1; then - echo "使用sudo测试..." - if sudo -u www-data mkdir -p $APP_ROOT/runtime/log/test_dir 2>/dev/null; then - echo "✅ sudo: runtime目录创建子目录成功 [使用www-data用户]" - rm -rf $APP_ROOT/runtime/log/test_dir - else - echo "❌ sudo: runtime目录创建子目录失败 [使用www-data用户]" + # 验证文件权限是否足够 + echo "=== 验证文件权限 ===" + test_file="$APP_ROOT/index.php" + if [ -f "$test_file" ]; then + echo "测试文件: $test_file" + echo "文件权限: $(stat -c '%a %n' "$test_file")" + echo "www-data 用户测试读权限: $(su -s /bin/sh -c "cat '$test_file' >/dev/null && echo '✅ 可读' || echo '❌ 不可读'" www-data 2>/dev/null || '无法测试')" + echo "www-data 用户测试写权限: $(su -s /bin/sh -c "echo 'test' >> '$test_file.test' && rm '$test_file.test' && echo '✅ 可写' || echo '❌ 不可写'" www-data 2>/dev/null || '无法测试')" fi fi -# 方法2:使用su -echo "使用su测试..." -if su -s /bin/sh -c "mkdir -p $APP_ROOT/runtime/log/test_dir" www-data 2>/dev/null; then - echo "✅ su: runtime目录创建子目录成功 [使用www-data用户]" - rm -rf $APP_ROOT/runtime/log/test_dir -else - echo "❌ su: runtime目录创建子目录失败 [使用www-data用户]" -fi - -# 方法3:使用runuser -if command -v runuser >/dev/null 2>&1; then - echo "使用runuser测试..." - if runuser -u www-data -- mkdir -p $APP_ROOT/runtime/log/test_dir 2>/dev/null; then - echo "✅ runuser: runtime目录创建子目录成功 [使用www-data用户]" - rm -rf $APP_ROOT/runtime/log/test_dir - else - echo "❌ runuser: runtime目录创建子目录失败 [使用www-data用户]" - fi -fi - -# 检查www-data用户和组 -echo "检查www-data用户..." -id www-data -groups www-data - -# 检查目录的实际权限 -echo "检查目录权限..." -for dir in "${directories[@]}"; do - echo "检查目录权限: $dir" - ls -ld "$APP_ROOT/$dir" -done - -echo "检查setgid权限..." -for dir in "${directories[@]}"; do - echo "检查setgid权限: $dir" - stat -c '%a %n' "$APP_ROOT/$dir" | grep 's' -done - -echo "=== 检测 PHP 执行用户 ===" - -# 检查命令可用性函数 -command_exists() { - command -v "$1" >/dev/null 2>&1 -} - -# 方法1:通过 PHP 脚本检测当前用户 -echo "方法1: 通过 PHP 检测当前执行用户" -if command_exists php; then - php -r " -if (function_exists('get_current_user')) { - echo '当前 PHP 执行用户: ' . get_current_user() . PHP_EOL; -} else { - echo 'get_current_user() 函数不可用' . PHP_EOL; -} - -if (function_exists('getmyuid')) { - echo '当前用户 ID: ' . getmyuid() . PHP_EOL; -} else { - echo 'getmyuid() 函数不可用' . PHP_EOL; -} - -if (function_exists('getmygid')) { - echo '当前组 ID: ' . getmygid() . PHP_EOL; -} else { - echo 'getmygid() 函数不可用' . PHP_EOL; -} - -if (function_exists('posix_geteuid') && function_exists('posix_getpwuid')) { - echo '当前进程用户: ' . posix_getpwuid(posix_geteuid())['name'] . PHP_EOL; -} else { - echo 'posix 函数不可用,尝试系统方法' . PHP_EOL; - echo '当前用户: ' . exec('whoami') . PHP_EOL; -} -" 2>/dev/null || echo "PHP 执行检测失败" -else - echo "❌ PHP 命令不可用,跳过检测" -fi - -# 方法2:通过进程检测 PHP-FPM 运行用户 -echo "方法2: 检测 PHP-FPM 进程用户" -if command_exists pgrep; then - if pgrep php-fpm > /dev/null 2>&1; then - if command_exists ps; then - ps aux | grep php-fpm | grep -v grep | head -3 2>/dev/null || echo "进程检测失败" - else - echo "ps 命令不可用,但找到 PHP-FPM 进程" - fi - else - echo "PHP-FPM 进程未运行" - fi -else - echo "pgrep 命令不可用,尝试其他方法" - if command_exists ps; then - echo "使用 ps 直接检测:" - ps aux | grep php-fpm | grep -v grep | head -3 2>/dev/null || echo "未找到 PHP-FPM 进程" - else - echo "ps 和 pgrep 命令都不可用,无法检测进程" - fi -fi - -# 方法3:检测配置文件中的用户设置 -echo "方法3: 检查配置文件中的用户设置" - -# PHP-FPM 配置检查 -php_fpm_configs=( - "/usr/local/etc/php-fpm.d/www.conf" - "/etc/php-fpm.d/www.conf" - "/usr/local/etc/php-fpm.conf" - "/etc/php-fpm.conf" -) - -for config_file in "${php_fpm_configs[@]}"; do - if [ -f "$config_file" ]; then - echo "找到 PHP-FPM 配置: $config_file" - if command_exists grep; then - echo "PHP-FPM 用户配置:" - grep -E "^user|^group" "$config_file" 2>/dev/null || echo "未找到用户配置行" - else - echo "grep 命令不可用,但配置文件存在" - fi - break - fi -done - -# Nginx 配置检查 -nginx_configs=( - "/etc/nginx/nginx.conf" - "/usr/local/nginx/conf/nginx.conf" - "/etc/nginx/conf/nginx.conf" -) - -for config_file in "${nginx_configs[@]}"; do - if [ -f "$config_file" ]; then - echo "找到 Nginx 配置: $config_file" - if command_exists grep; then - echo "Nginx 用户配置:" - grep -E "^user" "$config_file" 2>/dev/null || echo "未找到用户配置行" - else - echo "grep 命令不可用,但配置文件存在" - fi - break - fi -done - -# 方法4:使用 /proc 文件系统检测(如果其他方法都失败) -echo "方法4: 使用 /proc 文件系统检测" -if [ -d "/proc" ]; then - echo "当前脚本执行用户: $(whoami 2>/dev/null || echo 'whoami 命令不可用')" - echo "当前脚本用户 ID: $(id -u 2>/dev/null || echo 'id 命令不可用')" -else - echo "/proc 目录不可用" -fi - echo "=== 启动应用 ===" # 执行原有的启动命令 diff --git a/docker/php/supervisord.conf b/docker/php/supervisord.conf index 907b51505..b412e5d3d 100644 --- a/docker/php/supervisord.conf +++ b/docker/php/supervisord.conf @@ -6,15 +6,6 @@ logfile_backups=10 loglevel=info pidfile=/var/run/supervisord.pid -[program:php-permission-change] -command=/bin/bash -c "sleep 15 && /usr/local/bin/entrypoint.sh" -autostart=true -autorestart=true -stopasgroup=true -killasgroup=true -stdout_logfile=/var/log/supervisor/php-permission-change.log -stderr_logfile=/var/log/supervisor/php-permission-change-error.log - [program:php-fpm] command=php-fpm autostart=true