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

掉进了 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 需要 gd、zip 等插件,原版镜像没有,我们需要跑起来后手动补装:

复制代码
# 运行 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. 刷新网页 :回到浏览器,按 F5 或 Crl + 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 轻量得多,处理并发能力强。
相关推荐
2035去旅行10 小时前
bootcmd 详细讲解
linux·嵌入式·arm·soc
陈希12310 小时前
Linux 防火墙配置实战:firewalld、iptables 与云安全组
linux·运维·服务器
女神下凡11 小时前
芯参谋(95):嵌入式文件系统_开发指南
linux·服务器·arm开发·驱动开发·设计规范
且从容.15 小时前
Ubuntu安装flume
linux·ubuntu·flume
承渊政道15 小时前
Linux网络学习【Reactor反应堆模式】
linux·网络·学习·ubuntu·reactor
且从容.18 小时前
ubuntu安装flink
linux·ubuntu·flink
爱和冰阔落19 小时前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
程序员沉梦听雨19 小时前
WSL2的安装与使用
linux·wsl
微小的鱼20 小时前
Linux的渲染与显示系统链路
android·java·linux
lisanmengmeng20 小时前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器