🏭 Infra/🐳 Docker

[Docker] docker compose로 다중 컨테이너 연결 시 Connection to localhost:5432 refused 에러

gengminy 2022. 8. 7. 20:54

도커 컴포즈로 Spring Boot + PostgreSQL 다중 컨테이너를 띄워서 연결하던 중 발견한 오류

 

일단 결론부터 말하자면 도커에 대한 이해가 얕아서 생긴 오류

알고보면 정말 별 것도 아닌 오류이지만

도커 초심자는 반드시 거쳐가는 오류가 아닐까 싶다..,,

장장 4시간의 삽질

 

 

🔨 작업 환경

Spring Boot (Gradle)
Redis
PostgreSQL
PgAdmin

 

 

💥 원인 찾기

org.postgresql.uti.PSQLException: Conntection to localhost:5432 refused.

 

Spring에서 PostgreSQL 연결 시 호스트나 포트를 잘못 찾아서 연결할 수 없는 오류이다

말 그대로 db 주소를 잘못 입력했다는 거다

 

 

📌 변경 전 파일

📝 docker-compose.yml

version: '3.7'
services:
  app:
    build: .
    container_name: app
    hostname: backend
    env_file:
      - .env
    expose:
      - '8000'
    depends_on:
      - postgres
      - redis

  redis:
    image: redis:alpine
    ports:
      - '6379:6379'

  postgres:
    image: postgres:latest
    container_name: postgres
    restart: always
    ports:
      - '5432:5432'
    env_file:
      - .env
    networks:
      - postgres

  pgadmin:
    links:
      - postgres:postgres
    container_name: pgadmin
    image: dpage/pgadmin4
    ports:
      - '8080:80'
    env_file:
      - .env
    networks:
      - postgres

networks:
  postgres:
    driver: bridge

 

📝 .env

PORT=8000
...
REDIS_HOST=localhost
REDIS_PORT=6379
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
...

 

📝 ./src/main/resources/application.yml

spring:
  # .env import
  config:
    import: optional:file:.env[.properties]
  # Using POSTGRESQL
  datasource:
    url: jdbc:postgresql://${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
    username: ${POSTGRES_USER}
    password: ${POSTGRES_PASSWORD}
    driver-class-name: org.postgresql.Driver
    ...

 

 

장장 4시간을 헤메이다 결국 구글링으로 원인을 찾아냈다

 

https://www.linuxfixes.com/2021/12/solved-docker-is-server-running-on-host.html

 

[SOLVED] Docker: Is the server running on host "localhost" (::1) and accepting TCP/IP connections on port 5432?

Issue I am getting issues while setup and run the docker instance on my local system with ...

www.linuxfixes.com

 

문제는 바로 각 컨테이너가 독립된 상태로 존재하는데

app 이라는 스프링 서버 컨테이너에서 localhost:5432 를 조회하게 되면

자기 자신의 5432 포트를 조회하는 거니까 아무것도 없는 빈 곳을 조회하는 것이다

 

머리가 상당히 띵했다

 

그러니까 결국 localhost:5432 가 아니라 postgres:5432

postgres 서비스의 5432 포트를 조회해야 db에 접근할 수 있다는 것이다

 

 

🔨 코드 수정

 

📌 변경 후 파일

📝 docker-compose.yml

version: '3.7'
services:
  app:
    build: .
    container_name: app
    hostname: backend
    env_file:
      - .env
    expose:
      - '8000'
    depends_on:
      - postgres
      - redis
    networks:
      - postgres

  redis:
    image: redis:alpine
    ports:
      - '6379:6379'

  postgres:
    image: postgres:latest
    container_name: postgres
    restart: always
    ports:
      - '5432:5432'
    env_file:
      - .env
    networks:
      - postgres

  pgadmin:
    links:
      - postgres:postgres
    container_name: pgadmin
    image: dpage/pgadmin4
    ports:
      - '8080:80'
    env_file:
      - .env
    networks:
      - postgres

networks:
  postgres:
    driver: bridge

depends_on 으로 redis 와 postgres 가 먼저 켜진 후에 app을 실행한다

이후 같은 networks 로 묶어서 통신할 수 있도록 해준다

 

 

📝 .env

PORT=8000
...
REDIS_HOST=redis
REDIS_PORT=6379
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
...

이후 환경변수의 호스트 이름을

도커 컴포즈 파일에서 정의한 service 이름과 똑같이 매칭해주면 된다

 

스프링 설정 파일은 건들지 않아도 되었다

 

 

매우 잘된다 ^^

 

이상 도커 컴포즈 삽질의 흔적이었다

막상 삽질했더니 이렇게 하면 안될 거 같아서

postgres docker는 테스트 용으로만 두고 RDS 추가해서 그걸로 설정했다