前言
最近在docker部署了几个容器需要用到数据库的,但是又不想用host模式,所以查了一些相关资料,做个记录。
容器设置
一般用docker-compose安装,通用的格式见下代码
version: '3'
services:
容器:
image: 地址
restart: always
network_mode: "bridge"
ports:
- 本地端口:容器端口
environment:
DATABASE_TYPE: mysql
DATABASE_URL: mysql://username:secret@172.17.0.1:3306/数据库名称
APP_SECRET: replace-me-with-a-random-string
container_name: 容器名称
数据库地址
这里需要注意的是network_mode我们选择bridge。之前查了很多资料,基本上说的是通过开放数据库端口到公网,然后通过公网ip:端口号的模式访问。但是这个方式暴露数据库到公网了,很不安全。这里讲一种方法,可以直接通过访问桥接网络的网关来访问宿主机的服务。所以这里数据库的地址就变成"172.17.0.1",这个地址是”bridge“的网关。每个容器的网关地址不同,可以通过以下指令查看:
docker inspect 容器名称
一般网络这一项是在最下面,"Gateway"这一项:
数据库权限
数据库的访问权限要设置一下,不然一般是只能本地ip地址访问。
登录MySQL控制台
mysql -u root -p // -u表示用户,-p表示需要密码,root可以改成其他用户 Enter password: // 输入密码 use mysql // 切换到数据库
查看下每个数据库的访问权限
SELECT user, host FROM mysql.user WHERE user='用户名'; // 注意分号';'
右边host显示的可以访问的ip,这里可以看到只有"localhost",也就是只能本地访问。我们需要增加一个上面提到的容器网关地址对应的网段,这里是"172.17.0.%",'%'表示只匹配前面三个。
删除用户的原有主机权限
只有一个本地访问的可以跳过这一步
REVOKE ALL PRIVILEGES ON *.* FROM '用户名'@'原有主机地址'; FLUSH PRIVILEGES;
增加访问ip权限
// 注意密码是你下次访问的密码,建议设置成之前一样 GRANT ALL PRIVILEGES ON *.* TO '用户名'@'新主机地址' IDENTIFIED BY '密码'; FLUSH PRIVILEGES;
最后
到这里容器就可以连接到宿主数据库了
本文作者:HelloGakki
本文链接:https://pinaland.cn/archives/docker-mysql.html
版权声明:所有文章除特别声明外均系本人自主创作,本文遵循署名-非商业性使用-禁止演绎 4.0 国际许可协议,转载请注明出处。。
bridge?network_mode默认就是bridge啊。
是呀,但是这个模式用本地ip连不上不是docker部署的数据库呀,所以要稍微绕个弯
用bridge的话,每次bridge重建,容器ip都会变,而且这个网段仅宿主机可以访问。
而bridge场景下,宿主机可以值机用127.0.0.1或localhost接容器端口就可以访问容器的服务,不需要绕桥。
我之前docker容器直接访问数据库链接不上,然后查了下,发现可以用正文里提到的这个方法来,所以记录了下。
这个应用场景是docker容器访问非docker容器数据库。
如果没分析错的话,是非 docker 容器数据库,mysql://username:secret@172.17.0.1:3306指向的其实是宿主机。
非常不建议这么写URI。最完美情况下要把协议、认证信息、服务地址都分开写。最低限度下也不可以使用IP作为服务地址,因为这玩意会变。
可靠方式是使用--add-host(Docker Cli)或extra_hosts(Docker Compose)为容器添加一个host。容器的网关,也就是宿主机的桥,是host.docker.internal。
参考资料:https://stackoverflow.com/questions/70725881/what-is-the-equivalent-of-add-host-host-docker-internalhost-gateway-in-a-comp
当然,我个人认为Docker在这一块的确做得不好,尤其是在宿主机与容器的Host沟通上总是差一节,Cli和Compose的参数甚至不是对称的。
感谢提供后面这个方法,下次可以试试