Emlog Docker 部署实战:从 0 到上线的完整记录(1Panel + OpenResty)
这篇文章记录我用 Docker + 1Panel + OpenResty 从零部署一个 Emlog 博客的完整过程,包括踩过的坑和最终的稳定方案。如果你也打算用容器化方式跑 Emlog,这篇应该能帮你少走不少弯路。
Emlog Docker 部署实战:从 0 到上线的完整记录(1Panel + OpenResty)
分类:建站运维 · 标签:Emlog、Docker、1Panel、OpenResty、伪静态
这篇文章记录我用 Docker + 1Panel + OpenResty 从零部署一个 Emlog 博客的完整过程,包括踩过的坑和最终的稳定方案。如果你也打算用容器化方式跑 Emlog,这篇应该能帮你少走不少弯路。
一、写在前面
传统方式部署 Emlog 需要在服务器上装 PHP、Apache/Nginx、MySQL,环境配起来繁琐,迁移也麻烦。用 Docker 之后,整个博客就是一个容器,迁移、备份、重建都很方便。
但 Docker 部署也不是「一键起飞」,我这次就踩了几个不小的坑,最典型的一个是容器跑起来后全站 404。下面把完整流程和这些坑一次性讲清楚。
最终效果:一个带伪静态、邮件通知、CDN 加速的 Emlog 博客,所有配置持久化,容器重建不丢。
二、最终架构
先看一下整体架构,心里有个数:
用户 → CDN → OpenResty(反向代理)→ Emlog 容器(Apache + PHP)→ MySQL 容器
各组件分工:
- OpenResty:由 1Panel 管理,负责接收请求、伪静态 rewrite、反向代理到 Emlog 容器
- Emlog 容器:内置 Apache + PHP,运行博客程序
- MySQL 容器:独立数据库容器,存储博客数据
为什么用 OpenResty 反代而不是直接暴露 Emlog 容器?因为这样可以在前面统一处理伪静态、SSL、缓存,Emlog 容器只管跑程序,职责清晰,也方便后续加 CDN。
三、环境准备
我的环境如下,供对照:
- 服务器:一台 Linux VPS(Debian)
- 面板:1Panel
- 博客程序:Emlog Pro
- 镜像:
emlog/emlog:pro-latest-php7.4-apache - 数据库:MySQL 8.x 容器
需要准备的参数(下文用占位符表示,替换成你自己的):
| 占位符 | 含义 |
|---|---|
| 你的域名 | 博客正式域名 |
| 你的服务器IP | 服务器内网 IP |
| 你的数据目录 | Emlog 数据在宿主机的存放路径 |
| 你的数据库密码 | MySQL 密码 |
四、第一步:部署 MySQL 容器
Emlog 需要数据库。我用独立的 MySQL 容器,方便管理和备份。
在 1Panel 的应用商店里安装 MySQL,或者直接用命令:
docker run -d \
--name mysql \
--restart always \
-e MYSQL_ROOT_PASSWORD=你的数据库密码 \
-v /opt/mysql/data:/var/lib/mysql \
mysql:8.4
装好后进入容器创建 Emlog 专用数据库:
docker exec -it mysql mysql -u root -p
CREATE DATABASE emlog CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
注意:数据库端口不用对外开放,容器之间通过内部网络通信即可,更安全。
五、第二步:部署 Emlog 容器
在 1Panel 应用商店找到 Emlog 安装,或者用命令部署。这里先按默认方式跑起来:
docker run -d \
--name emlog容器 \
--restart always \
-p 8080:80 \
-v 你的数据目录:/app \
-e EMLOG_DB_HOST=mysql \
-e EMLOG_DB_NAME=emlog \
-e EMLOG_DB_USER=root \
-e EMLOG_DB_PASSWORD=你的数据库密码 \
emlog/emlog:pro-latest-php7.4-apache
关键参数说明:
-p 8080:80:把容器 80 端口映射到宿主机 8080,后面 OpenResty 反代这个端口-v 你的数据目录:/app:Emlog 程序和数据都在容器的/app,挂载到宿主机实现持久化
容器跑起来后,先别急着访问,因为大概率会遇到下面这个坑。
六、第三步:那个绕不开的 404 坑
容器跑起来后访问首页,返回的是这样一个 Apache 404:
Not Found
The requested URL was not found on this server.
Apache/2.4.54 (Debian) Server at www.你的域名 Port 80
排查方法:先看 Apache 的 DocumentRoot 指向哪里。
docker exec emlog容器 apache2ctl -S 2>&1 | head -20
输出里会看到:
Main DocumentRoot: "/var/www/html"
再看这个目录:
docker exec emlog容器 ls /var/www/html/
空的。而 Emlog 的真实文件其实在 /app:
docker exec emlog容器 ls /app/index.php
根因:这个 Emlog 镜像的 Apache 默认配置 000-default.conf 把 DocumentRoot 指向了空的 /var/www/html,而程序文件实际在 /app。所以所有请求都 404。
同时,Apache 默认的 AllowOverride 全是 None,就算放了 .htaccess 也不会被读取。
所以必须同时修两个地方:把 DocumentRoot 指向 /app,并开启 AllowOverride All。
七、第四步:配置伪静态(含 404 修复)
1. 准备 .htaccess
数据目录挂载到容器 /app,所以直接在宿主机数据目录里建 .htaccess:
cat > 你的数据目录/.htaccess << "EOF"
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
EOF
2. 准备自定义站点配置
写一个 Apache 站点配置,把 DocumentRoot 改到 /app 并开启 AllowOverride:
mkdir -p /opt/emlog/conf
cat > /opt/emlog/conf/emlog-site.conf << "EOF"
<VirtualHost *:80>
DocumentRoot /app
<Directory /app>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
EOF
3. 用 docker run 重建容器(关键)
这里要特别提醒:不要用 1Panel 图形界面改挂载,会报错:
includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed
这是 1Panel 把路径当成了命名卷。直接用 docker run 重建,把站点配置挂载进去覆盖默认的 000-default.conf:
docker run -d \
--name emlog容器 \
--restart always \
-p 8080:80 \
-v 你的数据目录:/app \
-v /opt/emlog/conf/emlog-site.conf:/etc/apache2/sites-enabled/000-default.conf \
-e EMLOG_DB_HOST=mysql \
-e EMLOG_DB_NAME=emlog \
-e EMLOG_DB_USER=root \
-e EMLOG_DB_PASSWORD=你的数据库密码 \
emlog/emlog:pro-latest-php7.4-apache
这样 DocumentRoot 和 AllowOverride 两个问题一次性解决,而且配置在宿主机上,容器重建也不会丢。
4. 配置 OpenResty 反代和伪静态
在 1Panel 里创建网站,添加反向代理指向 你的服务器IP:8080,然后在「站点设置 → 伪静态」填入:
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php last;
}
如果面板的伪静态入口对反代站点不生效,就手动编辑 OpenResty 配置:
server {
listen 80;
server_name 你的域名 www.你的域名;
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php last;
}
location / {
proxy_pass http://你的服务器IP: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;
}
}
改完重载:
docker exec openresty容器 nginx -s reload
八、第五步:Emlog 后台初始化
站点能访问后,登录后台做几项基础设置:
- 链接结构:设置 → 链接结构,选「文件格式」(
/post-1.html),SEO 友好 - 站点地址:设置 → 基本设置,站点地址填
https://你的域名,千万别填http://服务器IP:8080,否则生成的链接全带 IP 端口 - 保存报错处理:如果保存链接结构时提示「.htaccess不可写」,是因为文件归属问题,执行:
chown 33:33 你的数据目录/.htaccess
还不行就 chmod 666。容器里 Apache 运行用户是 www-data(UID 33),root 创建的文件它写不了。
九、第六步:美化邮件通知(可选)
Emlog 自带邮件通知功能(比如评论回复提醒),默认模板比较朴素。可以在后台「设置 → 邮件通知」里替换成自定义 HTML 模板。
模板里有两个变量,发信时自动替换,不用改:
{{mail_site_title}}→ 站点名称{{mail_content}}→ 邮件正文
一个简洁美观的模板结构参考:顶部品牌区(站点名 + 标语)、中间白色正文卡片、底部信息区(站点链接 + 联系方式 + 版权)。具体样式可以根据自己网站的配色调整,核心是保留那两个变量。
十、持久化清单
这套方案所有配置都在宿主机上,容器重建不丢。需要保管好的就这些:
| 宿主机路径 | 容器路径 | 说明 |
|---|---|---|
| 你的数据目录/ | /app | Emlog 全部数据(含 .htaccess) |
| /opt/emlog/conf/emlog-site.conf | /etc/apache2/sites-enabled/000-default.conf | Apache 站点配置 |
| /opt/mysql/data/ | /var/lib/mysql | 数据库数据 |
备份时把这几个目录打包即可,迁移到新服务器原样恢复就能跑。
十一、故障排查速查
留一份命令清单,遇到问题按顺序敲:
# 确认容器名(重建后可能变)
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}"
# 检查 mod_rewrite 是否启用
docker exec emlog容器 apache2ctl -M | grep rewrite
# 查看 DocumentRoot 指向(404 时第一个要看)
docker exec emlog容器 apache2ctl -S 2>&1 | head -20
# 检查 .htaccess(注意是 /app 不是 /var/www/html)
docker exec emlog容器 cat /app/.htaccess
# 检查站点配置是否挂载成功
docker exec emlog容器 cat /etc/apache2/sites-enabled/000-default.conf
# 确认 Emlog 文件存在
docker exec emlog容器 ls /app/index.php
# 查看挂载情况
docker inspect emlog容器 --format '{{json .Mounts}}' | python3 -m json.tool
# 看 Apache 错误日志
docker exec emlog容器 tail -20 /var/log/apache2/error.log
常见问题对照:
| 症状 | 原因 | 解决 |
|---|---|---|
| 全站 404(Apache 返回) | DocumentRoot 指向空的 /var/www/html | 挂载 emlog-site.conf 覆盖默认配置 |
| 首页正常内页 404 | .htaccess 未生效 | 检查 /app/.htaccess 和 AllowOverride All |
| 链接带 IP:端口 | 站点地址填错 | 后台改成正式域名 |
| 502 Bad Gateway | 反代地址错误 | proxy_pass 用宿主机内网 IP,不用 127.0.0.1 |
| 改配置没效果 | 没重载 OpenResty | nginx -s reload |
| 1Panel 改挂载报错 | UI 把路径当命名卷 | 改用 docker run |
| .htaccess 不可写 | 文件归属是 root | chown 33:33 |
十二、踩坑总结
把这次的坑集中列一下:
- DocumentRoot 陷阱:Emlog 镜像的 Apache 默认指向空的
/var/www/html,真实文件在/app,必须用自定义站点配置覆盖。 - AllowOverride 默认 None:放了
.htaccess也不生效,必须显式开启AllowOverride All。 - 别用 1Panel UI 改挂载:会报命名卷错误,直接
docker run。 - proxy_pass 别用 127.0.0.1:容器内 127.0.0.1 指向自己,要用宿主机内网 IP。
- 站点地址填正式域名:填 IP:端口会导致链接全带 IP。
- .htaccess 写权限:root 建的文件 www-data 写不了,记得
chown 33:33。 - 改完 OpenResty 要重载:否则不生效。
十三、结语
整体下来,Docker 部署 Emlog 的思路很清晰:MySQL 容器 + Emlog 容器 + OpenResty 反代,三层各司其职,数据全部挂载持久化。唯一的「惊喜」是镜像的 DocumentRoot 指向问题,只要知道真实文件在 /app,用自定义站点配置覆盖一下就能解决。
这套方案跑下来很稳定,迁移和备份也方便——打包几个数据目录就能整体搬走。如果你也在用容器跑 Emlog,希望这篇能帮你少踩点坑。
发表评论