问题描述:
在开发过程中,我的 Spring Boot
应用程序直接运行在本地,可以通过 localhost
顺利访问 Docker
容器中的 MySQL
和 Redis
服务(做了端口映射)。然而,当我将 Spring Boot
应用程序也打包部署到 Docker
中后,发现应用程序无法再访问这些数据库和缓存服务,提示拒绝连接。
原因分析
当 Spring Boot
应用程序直接运行在宿主机上时,可以通过 localhost
访问 Docker
中的 MySQL
和 Redis
容器。这是因为 Docker
将这些容器的端口映射到宿主机的网络,localhost:port
便能与这些容器通信。
然而,当 Spring Boot
应用程序也部署到 Docker
容器中后,localhost
不再指向宿主机,而是指向 Spring Boot
容器本身。这导致 Spring Boot
容器无法通过 localhost
访问其他服务容器。Docker
中的容器默认彼此隔离,除非它们共享同一个网络,导致 Spring Boot
容器无法找到 MySQL
和 Redis
容器。
解决方案
-
使用容器的虚拟IP地址:
- 可以在
application.yaml
里面配置MySql
和Redis
的虚拟IP
地址,但是这会有一个缺点,因为容器每次重新启动,IP
地址会发生变化。
- 可以在
-
使用 Docker 内部网络:
- 创建一个自定义的 Docker 网络,将所有相关容器(如 Spring Boot、MySQL、Redis)连接到该网络中。在这种情况下,可以使用容器名称作为主机名进行服务访问。
- 示例步骤:
- 创建自定义网络:
docker network create mynetwork
- 启动并连接容器:
docker run --name mysql --network mynetwork -e MYSQL_ROOT_PASSWORD=root -d mysql:latest docker run --name redis --network mynetwork -d redis:latest docker run --name springboot-app --network mynetwork -d my-springboot-image
- 在 Spring Boot 应用程序中,将数据库和 Redis 的主机名配置为
mysql
和redis
,端口保持不变。
- 创建自定义网络: