博客部署到 Docker 后,如何访问宿主机上的 MySQL、Redis 和 Meilisearch
这篇只记一个具体问题:
博客应用跑进 Docker 后,怎么访问宿主机上的 MySQL、Redis、Meilisearch。
这个问题的关键点只有一句话:
容器里的
127.0.0.1不是宿主机,而是容器自己。
所以在 Docker 环境里,如果还是继续连:
127.0.0.1localhost
大概率就会直接失败。
应用配置怎么改
Docker 环境下,宿主机地址改成:
properties
ph.mysql.host=host.docker.internal
ph.redis.host=host.docker.internal
ph.meilisearch.host=http://host.docker.internal:84/
这里只改配置还不够,启动容器时还要加:
bash
--add-host=host.docker.internal:host-gateway
也就是 docker run 至少要包含这一段:
bash
docker run --add-host=host.docker.internal:host-gateway ...
没有这段,容器里不一定能正确解析 host.docker.internal。
宿主机服务要满足什么条件
这类问题不是只改一个 host 就结束了,至少要同时满足三件事。
1. 服务监听地址不能只绑 127.0.0.1
宿主机服务如果只监听本地回环地址,容器访问不到。
至少要绑定到 Docker 可达的地址,比如:
172.17.0.10.0.0.0
否则应用配置写对了也没用。
2. 防火墙要允许 Docker 网段访问
如果宿主机开了 ufw,那 Docker 网段要显式放行。
Redis 的放行例子:
bash
sudo ufw allow in on docker0 from 172.17.0.0/16 to 172.17.0.1 port 6379 proto tcp
Meilisearch 代理端口的放行例子:
bash
sudo ufw allow from 172.17.0.0/16 to any port 84
如果这些规则没开,服务虽然启动了,容器里还是会表现成“连不上”。
3. 权限本身也要允许当前来源
这一点对 MySQL 尤其明显。
之前直接用局域网 IP 访问 MySQL 时,就已经不是只改 host 就行了,还要同时处理:
bind-address- 用户授权
比如不能只停留在:
text
'user'@'localhost'
而要允许实际访问来源所在的网段或主机。
Docker 部署后本质没有变,只是访问来源从“局域网机器”变成了“Docker 网段里的容器”。
Redis 也一样,不只是改 host,还要一起看:
bindprotected-mode- 密码认证
- 防火墙规则
Meilisearch 为什么走 Nginx
Meilisearch 这里没有让容器直接访问原始端口,而是走宿主机上的 Nginx 代理:
properties
ph.meilisearch.host=http://host.docker.internal:84/
实际链路是:
text
容器 -> host.docker.internal:84 -> 宿主机 Nginx -> Meilisearch
这样做的好处是:
- 应用里统一只连一个入口
- 宿主机更方便做代理
- 后面调整搜索服务入口时,应用层改动更小
怎么测试网络是否通
最省时间的做法不是先怀疑应用代码,而是直接在容器里测端口。
可以直接跑:
bash
docker run --rm --add-host=host.docker.internal:host-gateway busybox sh -c "nc -zv host.docker.internal 3306"
docker run --rm --add-host=host.docker.internal:host-gateway busybox sh -c "nc -zv host.docker.internal 6379"
docker run --rm --add-host=host.docker.internal:host-gateway busybox sh -c "nc -zv host.docker.internal 84"
这三条分别测:
- MySQL
- Redis
- 宿主机 Nginx 代理出来的 Meilisearch 入口
如果这里都不通,优先查下面几项:
docker run有没有加--add-host=host.docker.internal:host-gateway- 宿主机服务是不是只监听在
127.0.0.1 ufw有没有放行 Docker 网段- MySQL 用户权限是不是允许当前来源访问
- Nginx 代理是不是正常
最后归纳
这类问题不要只盯着应用配置。
真正要一起处理的是:
- 容器里的访问地址
- 宿主机服务监听地址
- 防火墙规则
- 数据库或缓存本身的访问权限
只改 host,不改监听地址,不改 ufw,不改 MySQL 或 Redis 的访问控制,最后大概率还是不通。
GitHub 登录
Gitee 登录
QQ 登录