相关链接

本教程基于Debian13的阿里云服务器,使用Docker部署项目适配的 PHP7.4、MySQL5.7 (其实是APT包已经不支持这两个老版本...),并在宿主机安装 Nginx+Certbot 实现站点上线。

项目资源获取

LGnewUI-2采用授权下载方式,需要在 LGNewUi-Auth - 情侣小站在线授权系统 登录并经授权后,下载项目源代码。

Docker的安装配置

参考阿里云给出的文档,按序执行即可:

#删除Docker相关源
sudo rm -f /etc/apt/sources.list.d/*docker*.list
#卸载Docker和相关的软件包
for pkg in docker.io docker-buildx-plugin docker-ce-cli docker-ce-rootless-extras docker-compose-plugin docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove -y $pkg; done
 
#添加 GPG 密钥
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL http://mirrors.cloud.aliyuncs.com/docker-ce/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
#将该软件源添加到 Apt 源列表中。
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: http://mirrors.cloud.aliyuncs.com/docker-ce/linux/debian
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
 
sudo apt update
#安装Docker社区版本,容器运行时containerd.io,以及Docker构建和Compose插件
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
 
#启动Docker
sudo systemctl start docker
#设置Docker守护进程在系统启动时自动启动
sudo systemctl enable docker

配置镜像源:

sudo nano /etc/docker/daemon.json

轩辕镜像 一键配置脚本:

bash <(wget -qO- https://xuanyuan.cloud/docker.sh)

镜像源配置示例:

{
  "registry-mirrors": [
    "https://docker.m.daocloud.io",
    "https://docker.1panel.live/"
  ]
}

如果配置后仍然无法拉取(docker pull)镜像,请考虑使用科学上网工具。

对于不同设备,可以使用以下命令传输离线镜像包:

# 拉取镜像(设备1)
docker pull ...
 
# 打包镜像(设备1) | <path>/<name>.tar为自定义路径的tar文件,<image_name>为拉取的镜像名称
docker save -o <path>/<name>.tar <image_name>
 
# 将<name>.tar上传到服务器中,然后加载镜像(设备2--服务器)
docker load -i <path>/<name>.tar

使用Docker部署PHP-FPM和MySQL

这里给一个最简单的方法,使用docker-compose.yml进行编排:

# 创建应用目录
mkdir ~/Apps/lgnewui2
# 编辑文件
nano docker-compose.yml

内容参考如下(注意修改数据库密码):

services:
  mysql:
    image: mysql:5.7.44
    container_name: mysql57
    restart: always
    environment:
      MYSQL_DATABASE: LGnewUI2
      # Replace with the existing root password if /data/mysql already contains data.
      MYSQL_ROOT_PASSWORD: yourpassword
    volumes:
      - /data/mysql:/var/lib/mysql
    ports:
      - "3306:3306"
    healthcheck:
      test:
        - CMD-SHELL
        - mysqladmin ping -h 127.0.0.1 -uroot -p"$${MYSQL_ROOT_PASSWORD}" --silent
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 30s
 
  # Set ownership of the application directory before PHP-FPM starts.
  php-permissions:
    image: rol1n/lgnewui2-php74-fpm:latest
    user: "0:0"
    restart: "no"
    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        set -eu
        site_dir=/var/www/love
        mkdir -p "$$site_dir/storage/updates"
        for directory in jobs packages staging backups logs; do
          mkdir -p "$$site_dir/storage/updates/$$directory"
          chmod 755 "$$site_dir/storage/updates/$$directory"
        done
        chown -R 33:33 "$$site_dir"
        chmod 755 "$$site_dir/storage" "$$site_dir/storage/updates"
    volumes:
      - /var/www/love:/var/www/love
 
  php:
    image: rol1n/lgnewui2-php74-fpm:latest
    container_name: php74-fpm
    restart: always
    depends_on:
      mysql:
        condition: service_healthy
      php-permissions:
        condition: service_completed_successfully
    ports:
      - "127.0.0.1:9000:9000"
    volumes:
      - /var/www:/var/www
# 先拉取镜像
sudo docker compose pull
# 启动
sudo docker compose up -d

随后进行Nginx的配置,即可打开网站进行安装。

后面是按照分开的镜像容器部署方法,以及php-fpm的本地构建细节,可看可不看。

MySQL的compose配置

# 创建docker文件夹
mkdir ~/mysql57
 
# 编辑mysql的docker-compose(参考下文给出的 docker-compose.yml)
nano ~/mysql57/docker-compose.yml
# docker-compose.yml
version: '3.9'
services:
    mysql:
        image: 'mysql:5.7.44'
        volumes:
            - '/data/mysql:/var/lib/mysql'
        environment:
            - MYSQL_DATABASE=LGnewUI2
            - MYSQL_ROOT_PASSWORD=yourpassword
        ports:
            - '3306:3306'
        restart: always
        container_name: mysql57

可以先拉取镜像,或者参考上一节的内容,加载离线镜像包:

# 拉取镜像 (方式1)
sudo docker pull mysql:5.7.44
 
# 加载镜像 (方式2)
sudo docker load -i <path>/<name>.tar

随后就可以启用容器了:

cd ~/mysql57
sudo docker compose up -d

PHP-FPM的compose配置

笔者已将构建好的镜像 rol1n/lgnewui2-php74-fpm:latest 上传至 Docker Hub 由于需要安装PHP的一些拓展和依赖,纯净的官方镜像并不能满足需求,所以需要:

  • 从 Dockerfile 配置本地构建新镜像
# 创建docker文件夹
mkdir ~/php74-fpm
 
# 拉取官方纯净镜像
sudo docker pull php:7.4-fpm
 
# 将SourceGuardian加密文件放进构建目录,这里以x86-64文件为例
cd ~/php74-fpm/build
wget https://raw.githubusercontent.com/BaseMax/sourceguardian-loader-linux-x86-64/refs/heads/main/ixed.7.4.lin
 
# 创建构建目录并编辑 Dockerfile(参考下文给出的 Dockerfile)
mkdir -p ~/php74-fpm/build  
nano ~/php74-fpm/build/Dockerfile
 
# 编辑php-fpm的docker-compose(参考下文给出的 docker-compose.yml)
nano ~/php74-fpm/docker-compose.yml
# Dockerfile
FROM php:7.4-fpm
 
# ===== 换阿里云apt源 =====
RUN echo "deb http://mirrors.aliyun.com/debian bullseye main contrib non-free" > /etc/apt/sources.list \
 && echo "deb http://mirrors.aliyun.com/debian-security bullseye-security main contrib non-free" >> /etc/apt/sources.list
 
# ===== 安装系统依赖 =====
RUN apt-get update && apt-get install -y --no-install-recommends \
    libpng-dev libjpeg-dev libwebp-dev libzip-dev libicu-dev \
    libmagickwand-dev default-mysql-client ffmpeg \
 && rm -rf /var/lib/apt/lists/*
 
# ===== PHP内置扩展 =====
RUN docker-php-ext-install pdo_mysql mysqli exif
 
# GD扩展(图片处理)
RUN docker-php-ext-configure gd --with-jpeg --with-webp \
 && docker-php-ext-install gd
 
# Zip扩展(压缩)
RUN docker-php-ext-install zip
 
# Intl扩展(国际化)
RUN docker-php-ext-install intl
 
# ===== PECL扩展 =====
RUN pecl install imagick && docker-php-ext-enable imagick
 
# ===== SourceGuardian =====
# 将 ixed.7.4.lin 放在同目录下,构建时复制进去
COPY ixed.7.4.lin /usr/local/lib/php/extensions/no-debug-non-zts-20190902/
RUN echo "extension=ixed.7.4.lin" > /usr/local/etc/php/conf.d/ixed.ini \
 && echo "sourceguardian.enable_vm_hybrid=1" >> /usr/local/etc/php/conf.d/ixed.ini
 
# ===== PHP基础配置 =====
RUN echo "upload_max_filesize = 100M" > /usr/local/etc/php/conf.d/custom.ini  && echo "post_max_size = 100M" >> /usr/local/etc/php/conf.d/custom.ini  && echo "memory_limit = 512M" >> /usr/local/etc/php/conf.d/custom.ini  && echo "max_execution_time = 300" >> /usr/local/etc/php/conf.d/custom.ini
# docker-compose.yml
version: '3.9'
services:
    php:
        build:
            context: ./build      
            dockerfile: Dockerfile
        image: 'lgnewui2-php74-fpm'
        ports:
            - '9000:9000'
        volumes:
            - '/var/www:/var/www'       
        restart: always
        container_name: php74-fpm
# 进入根目录
cd ~/php74-fpm
 
# 构建镜像
sudo docker compose build
 
# 启动容器
sudo docker compose up -d

MySQL与PHP通信

我们需要创建新的docker网络,用于连通php与mysql:

sudo docker network create mynet
sudo docker network connect mynet php74-fpm
sudo docker network connect mynet mysql57

或者也可以在两段compose里加入如下字段:

# ...
        networks:
            - web_net
 
networks:
    web_net:
        name: web_net
        external: true

Nginx、Certbot安装与配置(网站上线)

# 使用apt-get获取nginx、certbot
apt-get update && apt-get install -y nginx
apt-get install -y certbot
apt-get install -y python3-certbot-nginx
 
# 开机自启动与即刻运行nginx
systemctl enable nginx && systemctl start nginx

创建源码存放目录,并上传资源:

# 需要以root身份
mkdir /var/www/love
cd /var/www/love
# 随后通过SFTP等工具上传源码至此

使用certbot(自动续签)申请ssl证书(确保域名都已在DNS处解析过):

# 将<your-main-domain>更换为你的主要站点域名
sudo certbot certonly --nginx -d <your-main-domain>
 
# 一些相关命令
# 查看所有已安装的证书
sudo certbot certificates
# 删除证书
sudo certbot delete --cert-name example.com
  • <your-main-domain>示例: love.example.com | 作为主要访问地址

编辑Nginx配置文件,并上线网站:

# 编辑配置(参考下文)
sudo nano /etc/nginx/sites-available/default
 
# 创建启用软链接
ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
 
# 测试配置格式正确否
nginx -t
 
# 重载nginx使配置生效
sudo systemctl reload nginx

Nginx(LGnewUI-2)配置文件(将<your-main-domain>替换为自定义域名):

# ==================== Love站点 - HTTP ====================
server {
    listen 80;
    server_name <your-main-domain>;
 
    # HTTP自动跳转HTTPS
    return 301 https://$host$request_uri;
}
 
# ==================== Love站点 - HTTPS ====================
server {
    listen 443 ssl;
    server_name <your-main-domain>;
 
    ssl_certificate /etc/letsencrypt/live/<your-main-domain>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<your-main-domain>/privkey.pem;
 
    root /var/www/love;
    index index.php index.html index.htm;
 
    client_max_body_size 100m;
    client_body_timeout 180s;
 
    gzip on;
    gzip_comp_level 5;              
    gzip_min_length 1k;             
    gzip_vary on;
    gzip_buffers 4 8k;
    gzip_http_version 1.1;
    gzip_proxied any;
    gzip_types
        text/plain
        text/css
        text/javascript
        application/javascript
        application/x-javascript
        application/json
        application/xml
        application/xml+rss
        image/svg+xml
        font/woff2
        font/ttf;
 
    location ~ ^.+?\.php(/.*)?$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        set $path_info $fastcgi_path_info;
        fastcgi_param PATH_INFO $path_info;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 
        fastcgi_read_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_connect_timeout 300;
    }
 
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
}

防IP直连的Nginx配置(选用)

直接给出配置文件新增字段:

# ==================== 防IP访问 - HTTP ====================
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    # 匹配所有未绑定的域名和直接 IP 访问
    # 444直接关闭连接,不返回任何信息,比 403 更安全
    server_name _;
    return 444;
}
 
# ==================== 防IP访问 - HTTPS ====================
server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    server_name _;
 
    # 配置一个无效或自签名的 SSL 证书,或指向不存在的证书路径
    # 目的是让通过 IP 的 HTTPS 访问因证书错误而失败
    ssl_certificate /data/customSSL/dummy.crt;
    ssl_certificate_key /data/customSSL/dummy.key;
 
    # 也可以直接返回错误,但证书错误通常能阻止连接建立
    return 444;
}

启用之前,需要先使用openssl申请自签名无效证书:

mkdir -p /data/customSSL
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
  -keyout /data/customSSL/dummy.key \
  -out /data/customSSL/dummy.crt \
  -subj "/CN=unused"

LGnewUI-2 杂项处理

路径权限问题

在上文中,PHP 的挂载路径为/var/www/,而docker容器的权限身份一般是uid=33(www-data) gid=33(www-data) groups=33(www-data),需要保持路径所属身份一致:

# 确认容器权限身份,一般为uid=33(www-data) gid=33(www-data) groups=33(www-data)
docker exec php74-fpm id www-data
# 1. 创建与容器内匹配的用户和组(UID/GID 都是 33)
sudo groupadd -g 33 www-data 2>/dev/null
sudo useradd -u 33 -g 33 -M -s /sbin/nologin www-data 2>/dev/null
# 2. 设置项目目录所有者
sudo chown -R 33:33 /var/www/

MySQL数据库填写

在上文的compose文件中,已经创建了一个数据库:

  • 地址:mysql57
  • 库名:LGnewUI2
  • 用户:root
  • 密码:yourpassword

MySQL数据库备份与恢复

# 备份数据库
docker exec <容器名mysql57> mysqldump -u <用户名root> -p<密码yourpassword> --single-transaction --hex-blob --default-character-set=utf8mb4 --add-drop-table <数据库名LGnewUI2> > ~/backup.sql
 
# 恢复数据库
docker exec -i <容器名mysql57> mysql -u <用户名root> -p<密码yourpassword> --default-character-set=utf8mb4 <数据库名LGnewUI2> < ~/backup.sql

和风天气API--生成Ed25519密钥对

cd ~
# 生成私钥文件
openssl genpkey -algorithm Ed25519 -out private.pem
# 导出公钥文件
openssl pkey -in private.pem -pubout -out public.pem
# 查看内容
cat private.pem
cat public.pem

获取CDN客户端真实IP

在Nginx配置文件的Server字段中,添加如下配置:

set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

具体功能:

  • 接受来自所有IP的请求(理论上该使用场景只需填写CDN的IP段)
  • 从X-Forwarded-For请求头获取真实IP
  • 递归搜索,从右向左排除所有信任IP段,取第一个不信任IP(当前配置下默认取最左侧第一个IP,通常为CDN自动填写的客户端真实IP)

阿里云ESA(开启HTTP请求头添加后)的默认请求头为ali-real-client-ip,如有开启请替换掉X-Forwarded-For。

敏感目录拒绝访问

在Nginx配置文件的Server字段中,添加如下配置:

# ── 敏感目录 ──
location ^~ /storage/ { return 404; }
location ^~ /config/ { return 404; }
location ^~ /vendor/ { return 404; }
location ^~ /phpmailer/ { return 404; }
location ^~ /cron/ { return 404; }
location ^~ /install/ { return 404; }
 
# ── 敏感根目录文件 ──
location = /composer.json { return 404; }
location = /readme.txt { return 404; }
location = /config.php { return 404; }

服务器性能优化:添加Swap分区

2G内存没有 Swap 很危险,OOM 时会直接杀进程。

# 创建 2G swap 文件
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
 
# 持久化配置
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
 
# 降低swap使用倾向(优先用物理内存)
echo 'vm.swappiness = 10' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
 
# 验证
free -h

源码/容器重装

# 创建install.lock避开安装流程
touch ./install/install.lock
# 填写数据库信息和安全码
vim ./panel/Config_DB.php

其他工具

  • DBeaver | 数据库管理(此处可用来转移、备份MySQL)
  • WinSCP | SFTP工具(上传文件到服务器)
  • MobaXterm | SSH工具(连接服务器、编辑文件)