Docker:Springboot 容器无法连接到 PostgreSql 容器
Posted
技术标签:
【中文标题】Docker:Springboot 容器无法连接到 PostgreSql 容器【英文标题】:Docker: Springboot container cannot connect to PostgreSql Container 【发布时间】:2021-02-09 16:44:08 【问题描述】:我正在构建一个使用 PostgreSQL 和 docker-compose 的 Spring Boot 应用程序。
当我使用 docker-compose up --build
运行容器时,我的 Spring Boot 应用程序无法启动,因为它找不到 PostgreSQL 容器的主机名。
Spring Boot Dockerfile
FROM maven:3.6.3-openjdk-14-slim AS build
COPY src /usr/src/app/src
COPY pom.xml /usr/src/app
RUN mvn -f /usr/src/app/pom.xml clean package
FROM openjdk:14-slim
COPY --from=build /usr/src/app/target/server-0.0.1-SNAPSHOT.jar /usr/app/server-0.0.1-SNAPSHOT.jar
EXPOSE 9000
ENTRYPOINT ["java","-jar","/usr/app/server-0.0.1-SNAPSHOT.jar"]
docker-compose.yml
version: '3'
services:
db:
image: postgres
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: my_db
ports:
- "5432:5432"
volumes:
- db-data:/var/lib/postgresql/data
networks:
- db-network
restart: always
server:
build: './server'
depends_on:
- db
restart: always
ports:
- "9000:9000"
networks:
- db-network
volumes:
- ./server:/server
networks:
db-network:
volumes:
db-data:
application.properties
spring.datasource.url=jdbc:postgresql://db:5432/my_db
spring.datasource.username=postgres
spring.datasource.password=postgres
错误输出
Caused by: java.net.UnknownHostException: db
我的猜测是在 Spring Boot Dockerfile 的构建阶段还没有创建 docker-compose 的虚拟网络。 关于如何解决这个问题的任何想法?
【问题讨论】:
【参考方案1】:这里有很多信息:https://docs.docker.com/compose/networking/
在 Web 容器中,您与 db 的连接字符串如下所示 postgres://db:5432,以及来自主机的连接字符串 看起来像 postgres://DOCKER_IP:8001。
这就是说 db:5432 可以在 docker-compose.yaml 中使用,并且 IP 地址将被传递(不是“db”),但在应用程序代码中外部使用它是行不通的。但是,您可以从 docker-compose.yaml
db
作为应用程序输入变量传递,您的应用程序可以将其填充到配置文件中。这将使您能够连接。
像这样的外部化配置是相当普遍的做法,所以应该是一个相对容易的修复。
例如:
Docker-compose.yaml
version: '3'
services:
db:
container_name: db
image: postgres
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: my_db
ports:
- "5432:5432"
volumes:
- db-data:/var/lib/postgresql/data
networks:
- db-network
restart: always
server:
build: './server'
depends_on:
- db
environment:
DB_HOST: db # untested, but there should be a way to pass this in
DB_PORT: 5432
DB_DATABASE: my_db
DB_USER: postgres
DB_PASSWORD: postgres
restart: always
ports:
- "9000:9000"
networks:
- db-network
volumes:
- ./server:/server
networks:
db-network:
volumes:
db-data:
然后有一个位于src/main/java/resources/application.properties
下的application.properties文件
spring.datasource.url=jdbc:postgresql://$DB_HOST:$DB_PORT/$DB_DATABASE
spring.datasource.username=$DB_USERNAME
spring.datasource.password=$DB_PASSWORD
【讨论】:
我尝试了您的解决方案,但环境变量甚至没有加载。我收到错误java.net.UnknownHostException: $DB_HOST
,好像application.properties 没有用db
替换$DB_HOST
旋转时是否在容器内?您可以检查docker exec -it [containerId] bash
,它可以让您进入容器,然后env
列出环境变量...如果DB_HOST
未正确设置为环境变量,它将不会在 application.properties 中被替换文件。一旦你验证了它的设置,变量应该级联到你的应用程序中
将整个项目复制到镜像中,添加WORKDIR /usr/src/app
,那么应该可以添加标准的RUN mvn clean package
。除非pom.xml
中有错误,否则只要 pom.xml 在您指定的目录中,该命令就应该运行。即不要只做COPY src /usr/src/app/src
,而是做COPY . /usr/src/app
我刚刚检查过,DB_HOST 设置不正确,这很奇怪,因为它是在我的 docker-compose 中定义的
今晚我会尝试测试一下 - 获得最小的工作版本应该不会太难【参考方案2】:
This post 完全解决了我的问题。
事实证明,maven 在构建 .jar 文件时试图建立与数据库的连接。我所要做的就是用这行 RUN mvn -f /usr/src/app/pom.xml clean package -DskipTests
修改我的 Dockerfile。
【讨论】:
【参考方案3】:请注意,在构建图像时,该服务将无法访问数据库,因为它尚未运行。只有在构建镜像并且容器运行之后,服务才可以访问。因此,当您尝试将主机作为 db 传递时,它在构建阶段尚不可用。只有在 db 容器开始运行时才可用。
【讨论】:
以上是关于Docker:Springboot 容器无法连接到 PostgreSql 容器的主要内容,如果未能解决你的问题,请参考以下文章
Springboot 应用程序无法使用 docker-compose 连接到 MongoDB 容器
Spring boot JDBC无法连接到docker容器中的mysql
无法从 docker 容器内的 Spring Boot 连接到 Redis
Spring Boot + MySQL + Docker Compose - 无法使 Spring Boot 连接到 MySQL