[E-commerce App] Docker Container를 이용한 애플리케이션 배포 - 3. MySQL
이전 글에 이어서 진행해보자.
Docker Container
5. MySQL (MariaDB)
order-service
에서 사용할 MariaDB를 컨테이너화 시켜보자.
(원래는 MariaDB를 사용하는데, 나는 에러가 발생해 MySQL을 사용할 것이다.)
1) init 데이터 생성
방법 1 과 방법 2 중 아무렇게나 해도 상관없다.
(나는 방법 2를 선택했다.)
[방법 1] 로컬 mysql에서 생성한 테이블 데이터를 옮기기
로컬에서 사용하던 DATABASE가 저장되어있는 위치로 이동한 뒤, 해당 데이터 파일들을 Dockerfile
을 생성할 위치에 미리 복사해 두자!
MySQL에서 저장된 DATABASE의 경로를 확인하는 방법
이 글을 참고했다.
(보통/usr/local/mysql/bin
위치에 있다는데 나는 없었다..ㅜㅜ)
$ mysql -u admin -p
# DATABASE 경로 확인
mysql> show variables like 'datadir';
이제 이 데이터들을 우리가 원하는 폴더로 옮겨보자.
# 폴더 생성
$ mkdir docker-files
$ cd docker-files
$ mkdir mysql-data
$ cd mysql-data
# mysql 데이터 copy
$ cp -R /opt/homebrew/var/mysql .
[방법 2] init 스크립트 생성
Dockerfile이 있는 위치에 mysql-init-files
디렉토리를 생성한 뒤, 그 안에서 create.sql
파일을 생성한다.
create.sql
-- CREATE DATABASE mydb;
create table mydb.users(
id int auto_increment primary key,
user_id varchar(20),
pwd varchar(20),
name varchar(20),
created_at datetime default NOW()
);
create table mydb.orders (
id int auto_increment primary key,
product_id varchar(20) not null,
qty int default 0,
unit_price int default 0,
total_price int default 0,
user_id varchar(50) not null,
order_id varchar(50) not null,
created_at datetime default NOW()
);
-- create masteruser and grant privileges
-- create user root'%' identified by '1234';
-- grant all privileges on *.* to root'%' identified by '1234';
2) Dockerfile을 통해 이미지 만들기
[방법 1] 선택
init 데이터를 생성할 때, [방법 1]을 선택했다면 아래와 같이 하자.
Dockerfile
은 아까 복사해둔 mysql-data
디렉토리와 같은 위치에 생성하자.
FROM mariadb
ENV MYSQL_ROOT_PASSWORD 1234
ENV MYSQL_DATABASE mydb
COPY ./mysql-data/mysql /var/lib/mysql
EXPOSE 3306
ENTRYPOINT ["mysqld","--user=root"]
COPY ./mysql-data/mysql /var/lib/mysql
- 데이터 베이스를 만들 때, 초기에 생성할 테이블 정보를 스크립트를 이용해 생성해도 괜찮지만,
지금은 로컬 db에서 만들어둔 테이블을 컨테이너 안으로 복사하여 사용해볼 것이다.
- 이 때,COPY ./mysql-data/mysql
자리에는 로컬에서 기동시킨 mariadb의 데이터들이 저장되어 있는 위치를 명시해주면 된다.
[방법 2] 선택
init 데이터를 생성할 때, [방법 2]를 선택했다면 아래와 같이 하자.
Dockerfile
은 아까 생성한 mysql-init-files
디렉토리와 같은 위치에 생성하자.
FROM mysql
MAINTAINER minju412 <mj441@naver.com>
ADD ./mysql-init-files /docker-entrypoint-initdb.d
ENV MYSQL_ROOT_PASSWORD 1234
ENV MYSQL_DATABASE mydb
EXPOSE 3306
(mysql-data
디렉토리는 이전에 시도할 때 생성했던 것이므로 없어도 된다.)
패스워드는 1234로 지정해보자. (지금 새로 만드는 것!)
3) 이미지 빌드
# 이미지 파일 빌드
$ docker build -t ln8847/my_mysql:1.0 .
# 생성된 이미지 확인
$ docker images | grep my_mysql
만약 아래와 같은 오류가 발생한다면?
m1 Mac에서 이미지 빌드 시, 아래와 같은 에러가 발생할 수 있다.
failed to solve with frontend dockerfile.v0: failed to create LLB definition: no match for platform in manifest sha256:94176d0ad4ed85767fc0d74b8071387109a0390e7c1afd39788269c96d2dad74: not found
이 경우에는, --platform
옵션을 추가하자.
$ docker build --platform linux/x86_64 -t ln8847/my_mysql:1.0 .
4) 도커 컨테이너 실행
실행 전에 기존에 로컬에서 기동 중인 mysql이 있다면 먼저 중지하자! (포트가 겹치면 에러가 발생한다.)
# mysql 기동 중인지 확인
$ brew services list
# mysql 정지 (기동 중이라면..)
$ brew services stop mysql
# 컨테이너 실행
$ docker run -d -p 3306:3306 --network ecommerce-network \
--name mysql \
ln8847/my_mysql:1.0
# 로그 확인
$ docker logs mysql
정상적으로 기동되었을 때 로그는 아래와 같다.
이전과 마찬가지로 네트워크를 확인해보자.
$ docker network inspect ecommerce-network
만약 Dockerfile을 수정하고 싶다면?
Dockerfile을 수정한 뒤에,
아래 순서대로 다시 도커 컨테이너를 기동하자.
# 기존 컨테이너 중지
$ docker stop mysql
# 실행중이지 않은 컨테이너 및 네트워크, 캐시 삭제
$ docker system prune
# 이미지 빌드
$ docker build -t ln8847/my_mysql:1.0 .
# 컨테이너 실행
$ docker run -d -p 3306:3306 --network ecommerce-network \
--name mysql \
ln8847/my_mysql:1.0
실행을 확인해보고, 정상적으로 기동되지 않았다면 로그까지 확인해보자.
$ docker ps -a
$ docker logs mysql
5) db 접속 후 테이블 확인 및 권한 설정
mysql 컨테이너 내부에 접속한 뒤,
mydb 라는 데이터베이스에 접속해 users
와 orders
테이블이 만들어져 있는지 확인해보자.
그리고 mysql의 root 계정이 어떠한 IP Address로 접속한다 하더라도 접속 가능하도록 권한을 설정해보자.
$ docker exec -it mysql /bin/bash
bash-4.4# mysql -h127.0.0.1 -uroot -p
# 패스워드는 아까 지정한대로 1234 입력
# 데이터 베이스 확인
mysql> show databases;
mysql> use mydb;
# 테이블 확인
mysql> show tables;
아래와 같이 두 개의 테이블이 생성되어 있는 것을 확인할 수 있다.
이제 권한을 설정하자.
# 권한 부여
mysql> grant all privileges on *.* to 'root'@'%';
# 적용
mysql> flush privileges;
# 권한 확인
mysql> show grants for 'root'@'%';
root 라는 계정의 어떤 IP Address로 접속하더라도, 모든 데이터베이스에 접속 가능하도록 권한을 부여하는 커맨드이다.
💛 개인 공부 기록용 블로그입니다. 👻