部署自动发卡网站的问题和解决方案

掉进了 Linux 运维和 Docker 部署中最经典的三个"套娃陷阱"

简单来说,我试图在一台小排量的代步车(1G 内存服务器)上,同时拉着三台大卡车(MySQL 8.0、Node 后端、npm 安装),结果导致车轮锁死(I/O 阻塞),而且车门(权限)还被反锁了。

以下是导致我之前"一直不行"的三个核心死结:


1. "资源内耗"陷阱:小马被大车压垮了

这是最初 SSH 连不上、打字卡顿的唯一原因

  • 你做了什么: 你在 1G 内存的服务器上跑了 MySQL 8.0。

  • 发生了什么: MySQL 8.0 默认会预占大量内存。当你启动它的那一刻,物理内存被吃光,Linux 启动了 Swap(虚拟内存) 。由于虚拟内存是靠硬盘模拟的,读写速度比物理内存慢几千倍,这直接导致了你截图里的 74.7% wa(I/O 等待)。

  • 后果: CPU 核心在苦苦等待硬盘响应,导致 SSH 指令排不上队,甚至连 Docker 命令都发不出去。

2. "空间扭曲"陷阱:Nginx 在盲人摸象

之前一直看到 404 的根源。

  • 你做了什么: 你在 Nginx 的 .conf 里写了网页路径,但忘记在 docker run 命令里把宿主机的代码文件夹映射进去。

  • 发生了什么: * 宿主机:/home/channie/gcone/acg-faka(有代码)

    • Nginx 容器:/usr/share/nginx/html/acg-faka空的
  • 后果: Nginx 非常勤快地去它能看到的文件夹找 /install,结果里面空空如也,所以只能无奈地回你一个 404。

3. "权限孤岛"陷阱:PHP 进不去自己的家

哪怕修好了 404,程序依然报错的原因。

  • 做了什么: 可能在某些操作中用了 root 权限(或者容器自动生成的文件夹),导致 runtime 等关键目录的所有者变成了 root

  • 发生了什么: PHP 容器通常是以普通用户身份运行的。当它想要写日志、存缓存或者创建 SQLite 数据库文件时,发现 runtime 目录被 root 锁死了,它没有钥匙。

  • 后果: 程序在初始化阶段就因为"无法写入文件"而卡死,反映到前端就是各种白屏或无法跳转。


💡 为什么现在突然行了?

因为我们针对性地解开了这三个死结:

  1. 释放资源 :我们杀掉了最耗资源的进程,并选择了更轻量的 SQLite

  2. 打通空间 :我们在 docker run 里加入了正确的 -v 挂载参数,让 Nginx 真正看到了代码。

  3. 强制洗白 :我们用 Docker 的 root 权限暴力执行了 chmod -R 777,把所有文件的控制权交还给了程序。

第一阶段:清理战场(释放被榨干的内存)

首先,我们要把那些导致系统卡死、疯狂报错的"僵尸"进程和容器彻底杀掉。

复制代码
# 1. 停止并删除所有相关的旧容器
docker stop gcone-nginx acg-faka-php acg-faka-mysql gcone-server 2>/dev/null
docker rm gcone-nginx acg-faka-php acg-faka-mysql 2>/dev/null

# 2. 杀掉可能还在后台刷报错日志的 Node 进程(释放 CPU 和内存)
pkill -9 node

# 3. 强制释放系统缓存
echo 3 | sudo tee /proc/sys/vm/drop_caches

# 4. 查看当前内存,确保 "available" 至少有 400MB 以上
free -h

第二阶段:权限大赦(拆掉 Docker 的"围墙")

因为部分文件夹是 root 创建的,你的 PHP 容器进不去。我们借用 Docker 的 root 权限强行洗白。

复制代码
# 使用临时容器将代码目录权限全开,并将所有权交还给你的 channie 用户 (UID 1001)
docker run --rm -v /home/channie/gcone/acg-faka:/data alpine sh -c "chmod -R 777 /data && chown -R 1001:1001 /data"

# 检查一下 runtime 目录,确保不再是 root 所有的
ls -l /home/channie/gcone/acg-faka/runtime

第三阶段:部署核心组件(PHP 与 Nginx)

1. 启动 PHP-FPM 并安装缺失扩展

由于 ACG-Faka 需要 gdzip 等插件,原版镜像没有,我们需要跑起来后手动补装:

复制代码
# 运行 PHP 容器
docker run -d --name acg-faka-php --restart always \
  -v /home/channie/gcone/acg-faka:/usr/share/nginx/html/acg-faka \
  --add-host=host.docker.internal:host-gateway \
  php:8.1-fpm-alpine

# 【核心】在容器内安装环境检查里变红的那些插件(这一步可能需要 1-2 分钟,请耐心等待)
docker exec -it acg-faka-php sh -c "apk add --no-cache freetype-dev libjpeg-turbo-dev libpng-dev libzip-dev && docker-php-ext-configure gd --with-freetype --with-jpeg && docker-php-ext-install -j$(nproc) gd pdo_mysql zip"

# 重启 PHP 让插件生效
docker restart acg-faka-php
2. 启动 Nginx(指路明灯)

确保宿主机的代码路径正确挂载到 Nginx 预期的位置。

复制代码
docker run -d --name gcone-nginx --restart always \
  -p 80:80 -p 443:443 \
  -v /home/channie/gcone/nginx/nginx.conf:/etc/nginx/nginx.conf:ro \
  -v /home/channie/gcone/dist:/usr/share/nginx/html:ro \
  -v /home/channie/gcone/acg-faka:/usr/share/nginx/html/acg-faka:rw \
  --add-host=host.docker.internal:host-gateway \
  nginx:latest

第四阶段:数据库方案(SQLite 终极省钱流)

如果你决定用 SQLite(强烈推荐,1H1G 机器的救命恩人):

  • 不需要运行任何数据库容器。

  • 直接访问网页,在数据库类型勾选 SQLite

  • 程序会自动在 config/database.php 同级或 database 目录下创建一个 .db 文件。

如果你非要用 MariaDB,请执行这行(已做内存优化):

复制代码
docker run -d --name acg-faka-mysql --restart always \
  --memory="300m" \
  -e MYSQL_ROOT_PASSWORD=lqyxiaoxiannv666 \
  -e MYSQL_DATABASE=acg_faka \
  -e MYSQL_USER=channie \
  -e MYSQL_PASSWORD=lqyxiaoxiannv666 \
  -v /home/channie/new-db:/var/lib/mysql \
  -p 3306:3306 \
  mariadb:10.11 \
  --innodb-buffer-pool-size=64M

第五阶段:最后的验证与上线

  1. 检查所有容器状态

    Bash

    复制代码
    docker ps

    确认 nginx、php、mysql(如果用了的话)都是 Up 状态。

  2. 清理浏览器缓存

    按下 Ctrl + F5 刷新 https://shop.channie.me/install

  3. 如果安装时提示"目录不可写"

    再次执行那个暴力权限命令(因为 PHP 运行时可能会产生新文件):

    docker run --rm -v /home/channie/gcone/acg-faka:/data alpine chmod -R 777 /data


💡 总结你的"避坑指南"表

环节 坑点 记住这一招
内存 MySQL 8.0 + npm install = 炸弹 1G 内存首选 SQLite
路径 Nginx 找不到文件报 404 -v 挂载路径必须跟 nginx.conf 对齐
权限 root 锁死 runtime 目录 docker run --rm ... chmod 强破
环境 原版 PHP 镜像没插件 docker exec 进去跑 docker-php-ext-install

1. 进入 PHP 容器并安装插件(针对 Alpine 版本的镜像)

docker exec -it acg-faka-php sh -c "apk add --no-cache freetype-dev libjpeg-turbo-dev libpng-dev libzip-dev && docker-php-ext-configure gd --with-freetype --with-jpeg && docker-php-ext-install -j$(nproc) gd pdo_mysql zip"

2. 重启 PHP 容器,让刚装好的插件生效

docker restart acg-faka-php

现在"按不了"是因为底部的按钮是灰色禁用状态 。发卡系统的安装程序非常严谨:只要页面上有一个红色的 "不支持",它就不让你进入下一步,防止安装完后程序崩溃。

你截图里的 gd (图片处理)、pdo_mysql (数据库连接)和 zip(压缩包解压)是必须要装上的"零件"。


🛠️ 解决办法:一键补齐这些"红色"插件

你只需要在 Xshell 里执行下面这一串命令。它会自动进入你的 PHP 容器,把缺少的零件全部安装并配置好。

直接复制并执行:

复制代码
# 1. 进入 PHP 容器并安装插件(针对 Alpine 版本的镜像)
docker exec -it acg-faka-php sh -c "apk add --no-cache freetype-dev libjpeg-turbo-dev libpng-dev libzip-dev && docker-php-ext-configure gd --with-freetype --with-jpeg && docker-php-ext-install -j$(nproc) gd pdo_mysql zip"

# 2. 重启 PHP 容器,让刚装好的插件生效
docker restart acg-faka-php

💡 为什么需要这一步?

Docker 的官方 PHP 镜像为了保持"身材苗条",默认只带了最基础的内核。像 gd 这种处理验证码和图片的插件,或者 zip 这种处理主题包的插件,都需要手动"激活"一下。

执行完后怎么做?

  1. 等待命令执行完 :安装插件可能需要 30 秒到 1 分钟,看到命令提示符重新出现(channie@phone:~$)才算完。

  2. 刷新网页 :回到浏览器,按 F5Crl + F5 刷新安装页面。

  3. 见证奇迹 :你会发现那几个红色选项全部变成了绿色的对勾

一旦全绿了,底部的按钮就会变成彩色可点击状态,你就能进到"数据库配置"环节了。

对于 ACG-Faka 这类基于高性能框架(如 ThinkPHP 或 Laravel)开发的系统,你看到的这些对勾(GD、Zip、PDO)确实是最基础、最标准的运行要求。


1. 为什么这些插件是"基础中的基础"?

虽然名字听起来专业,但它们在 PHP 界就像是电脑的"声卡"和"显卡"驱动一样:

  • GD 库 :没有它,网站就无法生成验证码 ,也无法裁剪商品图片

  • Zip 模块 :没有它,你无法在后台一键更新 系统,也无法解压新下载的主题包

  • PDO/PDO_MySQL:这是数据库的"翻译官"。没有它,PHP 根本听不懂数据库在说什么。


2. 关于"最低配置"的真相(1H1G)

你听别人说"1H1G 就能跑",这话没错,但**"能跑""能随便折腾"**是两回事:

  • "裸奔"模式(1H1G 够用)

    如果你直接在 Linux 上装宝塔面板或者原生 LNMP 环境,不走 Docker,1G 内存会跑得很舒服。

  • "套娃"模式(你现在的状态)

    你用了 Docker。Docker 虽然方便,但每个容器(Nginx、PHP、MySQL、Node)都会额外吃掉几十 MB 内存。加上你还要跑"小手机"后端,这就像是在一个只能坐 4 个人的小轿车里挤了 6 个人。


3. 如何在"地板配置"上跑出"天花板"性能?

既然服务器硬件(1H1G)短期内不打算升级,我们就得在软件上"抠门":

组件 你的选择 为什么它是最低/最优?
系统 Alpine Linux (PHP 镜像) 体积最小,只有几 MB,省内存。
数据库 SQLite 核心推荐。它不需要单独的进程,内存占用几乎为零。1H1G 跑 MySQL 纯属浪费。
Web服务器 Nginx 比 Apache 轻量得多,处理并发能力强。
相关推荐
hiwb2 小时前
Docker 安装 MySQL,DBeaver 连接 MySQL
mysql·docker·容器
万粉变现经纪人2 小时前
如何解决 pip install bitsandbytes 报错 仅支持 Linux+glibc(macOS/Windows 失败)问题
linux·运维·windows·python·scrapy·macos·pip
计算机安禾2 小时前
【Linux从入门到精通】第25篇:循环结构——重复造轮子的终结者
linux·运维·chrome
vortex52 小时前
守护开源世界的猎犬:ClamAV 软件包介绍
linux·网络安全
zzzyyy5382 小时前
基础IO(1)
linux·运维·数据库
zzzb1234562 小时前
WSL(Ubuntu)部署Nginx\+PHP8\.2完整教程(新手友好\+避坑指南)
linux·nginx·ubuntu·php
想拿大厂offer2 小时前
【Linux】编辑器、IDE 与操作系统:Linux 开发工具链的哲学与实践
linux·ide·编辑器
面向对象World3 小时前
养虾从入门到放弃(Windows&Ubuntu)
linux·运维·ubuntu
Danileaf_Guo3 小时前
Ubuntu 26.04桌面版部署
linux·运维·服务器·ubuntu