Spring Boot + MySQL + Docker Compose - 无法使 Spring Boot 连接到 MySQL
Posted
技术标签:
【中文标题】Spring Boot + MySQL + Docker Compose - 无法使 Spring Boot 连接到 MySQL【英文标题】:Spring Boot + MySQL + Docker Compose - Cannot make Spring Boot connect to MySQL 【发布时间】:2020-07-12 15:56:09 【问题描述】:我一直在尝试在后端(在 Spring Boot 上运行)容器和预构建的 mysql 容器之间建立连接。但是,我无法连接。我的 docker compose 文件是:
version: '3.7'
services:
test-mysql:
image: mysql
restart: always
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_DATABASE: testdb
MYSQL_USER: test
MYSQL_PASSWORD: test
MYSQL_ROOT_PASSWORD: root
backend:
depends_on:
- test-mysql
build:
context: backend
dockerfile: Dockerfile
ports:
- "8080:8080"
restart: always
volumes:
db_data:
我的应用程序属性:
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.datasource.url=jdbc:mysql://test-mysql:3306/testdb?autoReconnect=true&failOverReadOnly=false&maxReconnects=10
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=test
spring.datasource.password=test
当我使用docker-compose up
时,Spring Boot 无法识别容器名称test-mysql
。它抛出:java.net.UnknownHostException
当我将其更改为 IP 时,它说连接被拒绝。我一直在到处寻找,无法解决。我希望任何人都可以帮助我。谢谢!
【问题讨论】:
【参考方案1】:您必须在 composer 文件中提及后端 mysql 属性,如下所示,
backend:
depends_on:
- test-mysql
build:
context: backend
dockerfile: Dockerfile
ports:
- "8080:8080"
restart: always
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://test-
mysql:3306/testdbautoReconnect=true&failOverReadOnly=false&maxReconnects=10
SPRING_DATASOURCE_USERNAME: test
SPRING_DATASOURCE_PASSWORD: test
links:
- test-mysql:test-mysql
如果这不起作用,请尝试创建一个通用 docker 网络并将其添加到您的作曲家文件中,如下所示,
backend:
depends_on:
- test-mysql
build:
context: backend
dockerfile: Dockerfile
ports:
- "8080:8080"
restart: always
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://test-
mysql:3306/testdbautoReconnect=true&failOverReadOnly=false&maxReconnects=10
SPRING_DATASOURCE_USERNAME: test
SPRING_DATASOURCE_PASSWORD: test
networks:
-common-network
test-mysql:
image: mysql
restart: always
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_DATABASE: testdb
MYSQL_USER: test
MYSQL_PASSWORD: test
MYSQL_ROOT_PASSWORD: root
networks:
-common-network
#Docker Networks
networks:
common-network:
driver: bridge
#Volumes
volumes:
dbdata:
driver: local
【讨论】:
您好,感谢您的回复。我仍然收到java.net.UnknownHostException
另外,环境变量似乎没有覆盖 application.properties 变量。对此有任何想法吗?
也尝试暴露mysql端口。 test-mysql: image: mysql restart: always ports: - "3306:3306" volumes: - db_data:/var/lib/mysql environment: MYSQL_DATABASE: testdb MYSQL_USER: test MYSQL_PASSWORD: test MYSQL_ROOT_PASSWORD: root
@Steven 如果这不起作用,您应该尝试像我的第二个示例一样设置网络。可能这就是问题所在。容器无法识别它们的主机。容器可以轻松地与常见的 docker 网络进行通信。
@Steven 在尝试第二个示例之前尝试添加链接。也更新了我的答案。链接:-test-mysql:test-mysql【参考方案2】:
您可以定义一个公共网络,应用程序服务器和数据库都可以在该网络上连接。请检查下面我定义了公共网络的文件 (docker-compose.yml):backend
# Docker Compose file Reference (https://docs.docker.com/compose/compose-file/)
version: '3.7'
# Define services
services:
# App backend service
app-server:
# Configuration for building the docker image for the backend service
build:
context: . # Use an image built from the specified dockerfile in the `springboot-app-server` directory.
dockerfile: Dockerfile
ports:
- "8080:8080" # Forward the exposed port 4000 on the container to port 4000 on the host machine
restart: always
depends_on:
- db # This service depends on mysql. Start that first.
environment: # Pass environment variables to the service
SPRING_DATASOURCE_URL: jdbc:mysql://test-mysql:3306/testdb?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
SPRING_DATASOURCE_USERNAME: test
SPRING_DATASOURCE_PASSWORD: test
networks: # Networks to join (Services on the same network can communicate with each other using their name)
- backend
# Database Service (Mysql)
db:
image: mysql:5.7
ports:
- "3306:3306"
restart: always
environment:
MYSQL_DATABASE: testdb
MYSQL_USER: test
MYSQL_PASSWORD: test
MYSQL_ROOT_PASSWORD: root
volumes:
- db-data:/var/lib/mysql
networks:
- backend
# Volumes
volumes:
db-data:
# Networks to be created to facilitate communication between containers
networks:
backend:
我在 GitHub 上写了一篇博客和一个简单的 Spring Boot MySQL 应用程序,它讲述了如何使用 Docker Compose。请查收:http://softwaredevelopercentral.blogspot.com/2020/10/spring-boot-mysql-docker-compose-example.html
【讨论】:
【参考方案3】:如果你想在你的 spring 配置中使用这个 test-mysql
spring.datasource.url=jdbc:mysql://test-mysql:3306/testdb?autoReconnect=true&failOverReadOnly=false&maxReconnects=10
然后在服务test-mysql
处添加主机名属性
version: '3.7'
services:
test-mysql:
image: mysql
hostname: test-mysql
...
【讨论】:
【参考方案4】:我希望这已经解决了,但如果还没有,问题在于mysql docker容器启动滞后。
另一个问题是您可能需要构建 jar 文件,然后将其复制到容器中。这是一个大问题,因为当您构建 jar 文件时,以 db 作为主机名的数据库不可用。因此,当您构建 jar 文件时,请跳过测试。 这是我创建的 bash 脚本,但您可以一个一个地运行命令:
#!/bin/bash
cd storage-service
rm -rf target/
mvn clean compile package -Dmaven.test.skip=true
cd ..
docker-compose up
如果您想在容器中初始化 db。该文件位于我有一个文件 database.env 的文件夹 env 中
-- create the databases
CREATE DATABASE IF NOT EXISTS model_storage;
-- create the users for each database
CREATE USER 'arsene'@'localhost' IDENTIFIED BY 'arsene';
GRANT CREATE, ALTER, INDEX, LOCK TABLES, REFERENCES, UPDATE, DELETE, DROP, SELECT, INSERT ON `model_storage`.* TO 'arsene'@'localhost';
FLUSH PRIVILEGES;
后端服务 Dockerfile 如下所示:
FROM adoptopenjdk/openjdk11
COPY target/*.jar storage.jar
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /storage.jar" ]
EXPOSE 8089
数据库 env 文件如下所示:
MYSQL_ROOT_PASSWORD=arsene
MYSQL_DATABASE=model_storage
MYSQL_USER=arsene
MYSQL_PASSWORD=arsene
DATABASE_HOST=model_storage
DATABASE_USER=arsene
DATABASE_PASSWORD=arsene
DATABASE_NAME=model_storage
DATABASE_PORT=3306
如果您打算在图像中传递 JAVA_OPTS 环境。这些可以稍后使用,如下面的 docker-compose.yml 所示
您的后端(依赖于 mysql db 的服务)需要重新启动,直到 docker-compose 能够解析 mysql 的容器名称,在我的例子中它的名称是 db。并且不要忘记在 docker-compose 后端服务映像中包含数据源连接属性,如下所示。我不是 spring boot 方面的专家,也不是 docker 方面的专家,但现在它可以工作!
以下是我的结构方式: 我正在使用 docker version: "3.8"
仓储服务storage-service:
container_name: storage-service
restart: always
build:
context: storage-service
image: "service_storage_image"
depends_on:
- db
ports:
- "8089:8089"
links:
- db
env_file:
- env/database.env
environment:
WAIT_HOSTS: db:3306
SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/model_storage?allowPublicKeyRetrieval=true&useSSL=false
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: arsene
healthcheck:
test: "/usr/bin/mysql --user=arsene --password=arsene--execute \"SHOW DATABASES;\""
interval: 2s
timeout: 20s
retries: 10
environment:
- JAVA_OPTS=
-DEUREKA_SERVER=http://eureka-registry-server:7070/eureka
-DZIPKIN_SERVER=http://zipkin:9411/
networks:
- private-network-mms
我在 docker-compose 中的数据库是这样构造的:
mysql数据库db:
hostname: db
container_name: db
image: "mysql:latest"
env_file:
- env/database.env
volumes:
- type: bind
source: ./env/setup.sql
target: /docker-entrypoint-initdb.d/setup.sql
- db_volume:/var/lib/mysql
ports:
- 3307:3306
networks:
- private-network-mms
【讨论】:
以上是关于Spring Boot + MySQL + Docker Compose - 无法使 Spring Boot 连接到 MySQL的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot + MySQL + Docker Compose - 无法使 Spring Boot 连接到 MySQL
Spring boot??????????????????Spring boot??????MySql,Mybatis???PageHelper??????
Spring Boot 2.0:Docker Compose + Spring Boot + Nginx + Mysql 实践