나도 알고싶지 않았다..
혹시 이 글을 보는 당신이 아래 에러 중 하나를 마주한 상황이라면
본인과 이 글의 상황을 비교하며 한번 읽어보길 바란다.
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)를 컨테이너화 한다.
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: 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에 대한 환경변수가 잘 적용되지 않는 문제였다.