1C2G 轻量云物理机极限压榨:
Halo 2.x + MySQL + Nginx 全栈 Docker 部署
本文为纯命令实操技术文档,基于 Alibaba Cloud Elastic Compute Service (CentOS 7.9) 环境下我的全流程复盘 。
🛠️ 第一阶段:宿主机环境初始化与自建 MySQL 8.0
由于 1C2G 内存极为紧凑,为了榨干每一分硬件性能,我们首先在宿主机层直接部署 MySQL 8.0 服务,并为其初始化库环境。
uname -a # 验证 Linux 内核版本 [cite: 13, 34]
cat /etc/os-release # 确认系统为 CentOS 7.Core [cite: 14, 35, 36, 37]
df -h # 查看磁盘空间空闲 [cite: 6]
2. YUM 源配置与 MySQL 8.0 Server 安装
# 导入 MySQL 8.0 官方 YUM 源
sudo yum install -y https://repo.mysql.com/mysql80-community-release-el7-7.noarch.rpm [cite: 15]
# 禁用旧版 5.7,激活 8.0 社区版引擎
sudo yum-config-manager --disable mysql57-community [cite: 17]
sudo yum-config-manager --enable mysql80-community [cite: 18]
# 清理缓存并导入安全 GPG 密钥,强制跳过 nogpgcheck 安装
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 [cite: 20]
sudo yum clean all [cite: 22]
sudo yum install -y mysql-community-server --nogpgcheck [cite: 24]
3. 启动数据库并捞取初始密码
sudo systemctl start mysqld [cite: 25]
sudo systemctl enable mysqld [cite: 26]
# 抓取系统日志中生成的临时初始密码
grep 'temporary password' /var/log/mysqld.log [cite: 28]
拿到密码后,执行 sudo mysql_secure_installation 进行安全初始化设置 ,登入终端 mysql -u root -p 创建名为 halo 的生产数据库,以便后续容器连接 。
🚀 第二阶段:极端环境自救:2GB 物理内存死锁破局
1C2G 服务器在同时跑 MySQL、Nginx 和 Java(Halo)时,极易因高并发瞬间导致 OOM(内存溢出) 触发 Linux 内核守护机制杀掉 Docker 容器。因此,在部署 Docker 前,必须强行在线挂载 2GB 虚拟内存(SWAP 交换分区)。
1. 内存吞吐与磁盘预分配
free -h # 查看当前空闲内存
# 强行在根目录下开辟一块 2048MB 的空白文件作为交换常驻地
dd if=/dev/zero of=/swapfile bs=1M count=2048
2. 赋予加密权限并强行挂载
chmod 600 /swapfile
mkswap /swapfile # 构建成 SWAP 格式
swapon /swapfile # 激活挂载
# 将挂载规则永久写入系统表,防止服务器重启后断供
echo '/swapfile swap swap defaults 0 0' >> /etc/fstab
free -h # 再次核验,Swap 栏成功从 0 变成 +2.0GiB
🐳 第三阶段:生产级 Docker Engine 引擎生态搭建
1. 废弃官方旧源,同步阿里云高速镜像源
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo yum makecache fast
2. 安装 Docker 生态核心链并激活
sudo yum -y install docker-ce docker-ce-cli containerd.io
sudo systemctl start docker && sudo systemctl enable docker
3. 注入国内多路备用 Docker加速 Registry 镜像(解决 Pull 墙限制)
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.1ms.run",
"https://docker.hotpoint.site"
]
}
EOF
sudo systemctl daemon-reload && sudo systemctl restart docker
🏗️ 第四阶段:全栈反向代理网络拓扑与双容器编排
为了消灭端口裸露、实现 80 端口完美转发,我们采用 Nginx (宿主机默认网桥 IP) $\rightarrow$ Halo 2.x 拓扑链路。
1. 预先构建 Nginx 隔离配置文件
mkdir -p /opt/nginx/conf /opt/nginx/html
cat > /opt/nginx/conf/nginx.conf << 'EOF'
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name slk666.cyou localhost; # 你的公网主域名
location / {
# 核心黑魔法:172.17.0.1 为 Docker 默认网桥的宿主机内网 IP
# 此处直接打通并反向代理到外网隔绝的 Halo 容器端口
proxy_pass http://172.17.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
EOF
2. 启动 Nginx 边缘核心容器
docker run -d \
--name nginx \
-p 80:80 \
-v /opt/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /opt/nginx/html:/usr/share/nginx/html \
--restart=always \
nginx:alpine
3. 终极启动 Halo 2.x 核心 Java 容器
启动 Halo 时,通过 -e 注入变量彻底解开 Spring 默认上传单文件不得超过 2MB 的死锁;并通过 R2DBC 协议池跨容器直连宿主机的 MySQL 服务:
docker run -d \
--name halo \
--restart always \
-p 8080:8090 \
-v ~/.halo2:/root/.halo2 \
-e SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE=10MB \
-e SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE=10MB \
halohub/halo:2.24 \
--spring.r2dbc.url=r2dbc:pool:mysql://172.17.0.1:3306/halo \
--spring.r2dbc.username=root \
--spring.r2dbc.password=你的数据库密码 \
--spring.sql.init.platform=mysql
🎨 第五阶段:Gateway 模版骨架定位与视觉魔改(可选)
后台启动后,为了重绘前台登录界面,我们进入主题数据绝对路径下进行手动重载:
# 切入 Sakura 主题的渲染模版根目录
cd /root/.halo2/themes/theme-sakura/templates/
# 新建严格匹配的网关片段文件夹
mkdir -p gateway_fragments && cd gateway_fragments/
# 深度重写魔改布局模版
vi layout.html
在 layout.html 内写入你精雕细琢的 CSS 及动态 Canvas 脚本,保存退出后,执行:
docker restart halo # 强制触发类加载器重载文件树