728x90
문제발생
구성환경
Spring boot 2.7.3
Java 11
Docker 20.10.17
Windows 10
MySQL(Local) 8.0.29
MySQL(Docker) 5.7.39
docker-compose.yml
version: '3'
services:
database:
container_name: mysql_db
image: mysql/mysql-server:5.7
environment:
MYSQL_DATABASE: users_db
MYSQL_ROOT_HOST: '%'
MYSQL_ROOT_PASSWORD: root
TZ: 'Asia/Seoul'
ports:
- "3307:3306"
command:
- "mysqld"
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
application:
container_name: docker-compose-test
build:
context: ./
dockerfile: Dockerfile
ports:
- "8080:8080"
depends_on:
- database
application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/users_db?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
username: root
password: root
jpa:
open-in-view: true
hibernate:
ddl-auto: update
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
use-new-id-generator-mappings: false
show-sql: true
properties:
hibernate.format_sql: true
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
server:
port: 8080
docker-compose-test | com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
docker-compose-test |
docker-compose-test | The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
docker-compose-test | at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174) ~[mysql-connector-java-8.0.30.jar:8.0.30]
docker-compose-test | at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64) ~[mysql-connector-java-8.0.30.jar:8.0.30]
docker-compose-test | at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:828) ~[mysql-connector-java-8.0.30.jar:8.0.30]
docker-compose-test | at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:448) ~[mysql-connector-java-8.0.30.jar:8.0.30]
docker-compose-test | at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:241) ~[mysql-connector-java-8.0.30.jar:8.0.30]
docker-compose-test | at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:198) ~[mysql-connector-java-8.0.30.jar:8.0.30]
docker-compose-test | at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138) ~[HikariCP-4.0.3.jar:na]
docker-compose-test | at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:364) ~[HikariCP-4.0.3.jar:na]
docker-compose-test | at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:206) ~[HikariCP-4.0.3.jar:na]
docker-compose-test | at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:476) ~[HikariCP-4.0.3.jar:na]
docker-compose-test | at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:561) ~[HikariCP-4.0.3.jar:na]
docker-compose-test | at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115) ~[HikariCP-4.0.3.jar:na]
docker-compose-test | at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) ~[HikariCP-4.0.3.jar:na]
docker-compose-test | at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) ~[hibernate-core-5.6.10.Final.jar:5.6.10.F
inal]
docker-compose-test | at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:181) ~[hibernate-core-5.6.10.
Final.jar:5.6.10.Final]
docker-compose-test | at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
docker-compose-test | at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
docker-compose-test | at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:101) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
docker-compose-test | at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
docker-compose-test | at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
docker-compose-test | at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
docker-compose-test | at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.injectServices(DefaultIdentifierGeneratorFactory.java:175) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
docker-compose-test | at org.hibernate.service.internal.AbstractServiceRegistryImpl.injectDependencies(AbstractServiceRegistryImpl.java:286) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
docker-compose-test | at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:243) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
docker-compose-test | at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
docker-compose-test | at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:173) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
docker-compose-test | at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:127) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
docker-compose-test | at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1460) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
docker-compose-test | at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1494) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
docker-compose-test | at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.3.22.jar
:5.3.22]
docker-compose-test | at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.3.22.jar:5.3.22
]
docker-compose-test | at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-5.3.22.jar:5.3.22]
- application.yml 에서 db주소를 localhost:3306 으로 설정하니 위와 같은 수많은 오류들을 발생시켰다.
Communications link failure
오류는 mysql에 connection을 할 수 없는 오류로 주요 문제는 권한에 대한 문제라고한다.
문제발생 원인과 이해
- 아직 도커 입문수준이여서 도커의 전체적인 구조의 이해가 부족해 발생한 문제다.
- 그래서 도커의 컨테이너가 어떤 방식으로 구성되어있는지 글과 그림을 통해 이해하기로 했다.
- 일단 pc의 local에 3306포트로 연결된 mysql이 있다.
- 이 pc안에 docker가 설치되어있어서 이 docker안에 다중컨테이너를 구성한다.
- 현재 docker-compose.yml 에서 데이터베이스
port: 3307:3306
으로 구성되어있고container_name: mysql_db
을 통해 다음과 같이 그렸다.
- application도
port: 8080:8080
을 통해 구성되어있다.
- 여기서 보면 문제발생된 맨 위에 코드의 문제점을 발견할 수 있었다.
- 도커안의 각각 mysql_db와 application은 내부아이피를 쪼개서 서로 다른 네트워크를 구성하게 된다.
- application.yml에서 말하는 localhost:3306은 위 사진의 제일 큰 사각형의 Local에 있는 mysql:3306 을 가르키는게 아니게 된다.
- 여기엔 mysql이 따로 설치되어있지않기때문에 application.yml 에 명시한 localhost:3306은 갈 길을 잃게 되는 것이다.
- 그래서 application안의 컨테이너에는 최소화된 linux기반의 알파인이나 우분투에 다른 것들은 없고 application을 실행하기위한 요소들만 존재하게 된다.
- 이 문제점을 해결하기위해서 2가지의 방법이 있는데
1.application안에 mysql을 설치해서 localhost:3306을 사용할 수 있게한다.
2.새로운 컨테이너에 mysql이 설치되어있는 컨테이너를 생성해 application과 연결시켜준다.
- 1번은 localhost를 사용할 수 있어서 따로 application.yml의 url을 건드리지않아도 그대로 사용할 수 있다는 장점이 있다. 하지만 만약에 여러개의 application이 있을 때는 각각의 서버가 자기만의 DB를 사용하기때문에 회원서비스와 장바구니 서비스 존재할 때 데이터를 공유하기에 어려움이 있다.
- 그래서 2번을 채택하게됐는데 이 경우는 여러개의 서비스가 존재하더라도 하나의 DB를 바라볼 수 있어서 데이터 공유에 대해 문제가 없게된다.
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://mysql_db:3306/users_db?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
# url: jdbc:mysql://localhost:3306/users_db?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
username: root
password: root
- application.yml의 db url을 localhost:3306 대신에 docker-compose의 컨테이너 이름인 mysql_db로 적어준다. 그러면 정상적으로 spring boot 서버가 올라가게 된다.
- 여기에서도 컨테이너 이름으로만 어떻게 연결을 시켜주는지 간단하게 알아보게 됐는데
- 도커안에 DNS resolver라는 친구가 컨테이너 이름을 통해서 접속하게 되면 해당 내부아이피로 접속하게 도와준다는 것을 알게됐다.
느낀점
- 도커에 대한 정보가 없을 때는 당연히 sprin boot를 서버에 올릴 때와 같이 로컬에 있는 DB를 사용한다고 생각했다. 하지만 도커안에 각각의 기능만 최소화하는 컨테이너가 존재하고 다중의 컨테이너의 연결을 통해 큰 서비스 하나를 구성한다는 것을 알수 있었다.
'etc' 카테고리의 다른 글
AWS Route53 도메인 이전 후 오류를 해결하기위해 (1) | 2022.11.09 |
---|---|
캐싱 (Caching) (0) | 2022.04.11 |
6개월간의 회고, 8주간의 스터디와 현재 생각들 (0) | 2021.12.14 |
커밋 1일 1커밋 100일 회고록 (0) | 2021.10.29 |