[docker] 스프링 mysql docker-compose 삽질 기록

Seongho·2024년 2월 12일
0

docker

목록 보기
3/3
post-thumbnail

intro..

나도 알고싶지 않았다..
혹시 이 글을 보는 당신이 아래 에러 중 하나를 마주한 상황이라면
본인과 이 글의 상황을 비교하며 한번 읽어보길 바란다.
1. Access denied for user 'root'@'172.18.0.4' (using password: YES)
2. Host ‘172.18.0.4’ is not allowed to connect to this MySQL server
3. The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.

환경 + 삽질 배경


nginx 컨테이너만이 호스트의 80 포트와 연결돼있다.

1. ClientDev에는 리액트 프로젝트가 있다. 해당 폴더 안에서 리액트와 nginx를 빌드한다.
그러면, 리액트의 모든 정적 파일이 nginx의 /usr/share/nginx/html에 위치하게 된다.
2. 이제 server 폴더로 이동한다. server폴더에는 스프링 부트 프로젝트가 있다. 해당 폴더에서 스프링 부트 프로젝트를 빌드한다.
3. docker-compose.yml이 있는 위치로 나온다.
해당 위치에서 docker-compose up을 하여 모든 이미지(nginx, spring boot, mysql, redis)를 컨테이너화 한다.

docker-compose.yml

version: "3"

services:
  db:
    image: mysql:latest
    container_name: db_container
    volumes:
      - ./db_data:/var/lib/mysql    # mysql 컨테이너 내부 /var/lib/mysql과 host의 db_data를 연결
      # - ./mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf
      # - ./initdb.d/initdb.sql:/docker-entrypoint-initdb.d/initdb.sql  # 데이터베이스 초기화 sql
    expose:
      - "3306"
    # ports:
    #   - "3306:3306"
    restart: always
    command:
      - --lower_case_table_names=1
      # - --init-file /docker-entrypoint-initdb.d/initdb.sql
      - --bind-address=0.0.0.0
    environment:
      - MYSQL_USER=어쩌구
      - MYSQL_PASSWORD=어쩌구
      - MYSQL_ROOT_HOST='%'
      - MYSQL_ROOT_PASSWORD=어쩌구
      - MYSQL_DATABASE=데이터베이스이름	
      - TZ=Asia/Seoul

  redis:
    image: redis:latest
    container_name: redis_container
    volumes:
      - ./redis_data:/data
    expose:
      - "6379"

  backend:
    depends_on:
      - db
      - redis
    image: backend:latest
    container_name: backend_container
    expose:
      - "8080"
    # ports:
    #   - "8080:8080"
    restart: always
    environment:
      SPRING_PROFILE: prod
      spring-datasource-url: jdbc:mysql://db:3306/데이터베이스이름?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul&characterEncoding=UTF-8
      secret-key: 어쩌구
      mysql-pw: 어쩌구
      email-address: 어쩌구
      email-pw: 어쩌구
      mail-secret-string: 어쩌구
      redis-host: 어쩌구
      file-path: 어쩌구

  front_nginx:
    image: front_nginx:latest
    depends_on:
      - backend
    container_name: front_nginx_container
    restart: always
    ports:
      - "80:80"
    environment:
      - TZ=Asia/Seoul

해결 과정

일단 내 상황은, 모든 컨테이너가 띄워지긴 했다. 그런데, jpa에서 mysql에 ddl을 날리는 시점에 에러가 나면서, 처음에 언급했던 세 오류가 났었다. 그러니까, 여기에서 알 수 있는 것은,
1. 컨테이너는 잘 띄워 진다.
2. 스프링부트와 mysql 두 컨테이너 사이 데이터 교환이 안된다.
두 가지였다.

일단 db_container 를 보자

  db:
    image: mysql:latest
    container_name: db_container
    volumes:
      - ./db_data:/var/lib/mysql    # mysql 컨테이너 내부 /var/lib/mysql과 host의 db_data를 연결
      # - ./mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf
      # - ./initdb.d/initdb.sql:/docker-entrypoint-initdb.d/initdb.sql  # 데이터베이스 초기화 sql
    expose:
      - "3306"
    # ports:
    #   - "3306:3306"
    restart: always
    command:
      - --lower_case_table_names=1
      # - --init-file /docker-entrypoint-initdb.d/initdb.sql
      - --bind-address=0.0.0.0
    environment:
      - MYSQL_USER=사용자명
      - MYSQL_PASSWORD=사용자비번
      - MYSQL_ROOT_HOST='%'
      - MYSQL_ROOT_PASSWORD=루트계정 비번 
      - MYSQL_DATABASE=사용할 데이터베이스 이름 	
      - TZ=Asia/Seoul

일단 구글링을 통해서 할 수 있는건 다 해봤다.
주석 처리한 부분을 보면 mysqld.cnf를 만들어서 bind-address = 0.0.0.0도 추가해보고,
데이터베이스 초기화 하는 initdb.sql도 만들어서 넣어봤다.
그런데도 잘 동작하지 않았다.

따라서, db_container에 들어가서 mysql -root -p루트계정 비번으로 접근한 뒤,
show databases; 를 통해 데이터베이스를 봤는데, 내가 설정한 데이터베이스가 생성되어있지 않았다.
-> 여기에서 "환경변수가 제대로 설정되지 않는구나" 라고 예감할 수 있었다.
그래서 일단 컨테이너 내부에서 create database 데이터베이스 이름; 을 통해 수동으로 데이터베이스를 만들어주었다.

-> 이후에도 해결되지 않았다.
"Host ‘172.18.0.4’ is not allowed to connect to this MySQL server"
현재 이 메세지가 계속되고 있었다. 천천히 잘 생각해보았다.
호스트 '어쩌구' 가 mysql 서버에 연결하도록 허용되지 않았다???
-> 여기에서 권한 문제 라는 것을 깨달았다.

db_container 안에서 use mysql; 후에 select user, host from user; 를 통해 msyql 사용자를 보았다.

빨간 줄 그은 부분은 원래 없었다. 다시 에러 메세지를 보자.
"Host ‘172.18.0.4’ is not allowed to connect to this MySQL server"
172.18.0.4 (스프링 컨테이너 ip) 에 대해 권한을 할당해주어야 할 것 같다.
https://yoo-dev.tistory.com/54 를 참고했다.

create user '172.18.0.4'@'%' identified by '비밀번호'; 를 통하여 계정을 등록해주었다.
그리고 grant all privileges on 데이터베이스이름.* to 172.18.0.4@'%'; 를 통하여 스프링 컨테이너에 모든 권한을 부여하였다.

그리하여 이렇게 스프링 컨테이너를 사용자로 등록하였다. 그러니까, 원래는 로컬호스트만 mysql server에 접근할 수 있었는데, 이제는 스프링 컨테이너도 접근할 수 있게 되었고, 등록한 데이터베이스에 대하여 모든 권한을 부여받은 것이다.

이렇게 했더니, docker-compose up을 했을 때, ddl이 msyql에 잘 날아갔다!

MYSQL_USER, MYSQL_PASSWORD, MYSQL_ROOT_HOST와 같은 환경변수에 대한 설명은 해당 페이지에 잘 나와 있다.
https://dev.mysql.com/doc/refman/8.0/en/docker-mysql-more-topics.html

결론

docker-compose.yml에 작성한 mysql에 대한 환경변수가 잘 적용되지 않는 문제였다.

profile
Record What I Learned

0개의 댓글