ํฌ๋กค๋งํ ๋ฐ์ดํฐ๋ฅผ MySQL Docker ์ปจํ ์ด๋์ ์ ์ฅํ๊ธฐ
2022.01.31 - [Project/๐DEVOOK] - Selenium์ ์ฌ์ฉํ ๋์ ํ์ด์ง ํฌ๋กค๋ฌ ๊ตฌํ
์์ ์์งํ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ์ผ๋ก ์ ์ฒ๋ฆฌ ๋ฐ ๋ฒกํฐํ ์์ ์ ์งํํด์ผ ํ๊ธฐ ๋๋ฌธ์ ํฌ๋กค๋งํ ๋ฐ์ดํฐ๋ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํ์๋ค.
์ฌ๋ฌ ์ปดํจํฐ ํ๊ฒฝ ๋ฐ AWS EC2 ์๋ฒ์์ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ๊ธฐ ์ํด Docker Compose๋ก MySQL ์ปจํ ์ด๋๋ฅผ ๊ตฌ์ฑํ์๋ค.
โ๏ธ๋ชจ๋ธ๋ง
๊ฐ๋จํ๊ฒ url, title, description, category ํ๋๋ฅผ ๊ฐ์ง๋ ํ ์ด๋ธ 1๊ฐ๋ก ๊ตฌ์ฑํ์๋ค.
โ๏ธdocker-compose.yml ํ์ผ ๊ตฌ์ฑ
# docker-compose-dev.yml
version: "3"
services:
db:
image: mysql
container_name: devook-db
ports:
- "3306:3306"
volumes:
- ./db/conf.d:/etc/mysql/conf.d
command:
--default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_DATABASE: devook_db
MYSQL_ROOT_PASSWORD: cool
TZ: "Asia/Seoul"
MySQL ๋์ปค ์ด๋ฏธ์ง๊ฐ ์์๋ ๋, environment ์ต์ ์ผ๋ก MySQL ์ธ์คํด์ค์ ๊ตฌ์ฑ์ ๋ํ 1๊ฐ ์ด์์ ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ ์ ์๋ค.
MYSQL_ROOT_PASSWORD : ํ์ ์ค์ ์ผ๋ก, root superuser ๊ณ์ ์ ๋ํ ๋น๋ฐ๋ฒํธ๋ฅผ ์ค์ ํ๋ ๊ฒ์ด๋ค. ์ด๋ root superuser๋ ์๋์ผ๋ก ์์ฑ๋๋ค.
MYSQL_DATABASE : ์ ํ ์ฌํญ์ผ๋ก, ์ด๋ฏธ์ง๊ฐ ์์๋ ๋ ๋ช ์๋ ์ด๋ฆ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์์ฑ๋๋ค. MYSQL_USER, MYSQL_PASSWORD ์ค์ ์ ์ถ๊ฐํ๋ค๋ฉด, ํด๋น ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ํด superuser ์ ๊ทผ ๊ถํ์ ๋ถ์ฌ๋ฐ๋๋ค. (GRANT ALL๊ณผ ๋์ผ)
mysql docker image - Environment Variables
๐ก์ด๋ชจ์ง ์ ์ฅ์ ์ํ MySQL ์ค์ ์ถ๊ฐ
๋ธ๋ก๊ทธ ๊ธ์ ํน์ฑ์ ์ด๋ชจ์ง๊ฐ ๋น๋ฒํ ์ฌ์ฉ๋๋ฏ๋ก ์ด๋ฅผ MySQL์ ์ ์ฅํ๊ธฐ ์ํด์๋ ์ถ๊ฐ ์ค์ ์ด ํ์ํ๋ค.
#๏ธโฃ MySQL ์ค์ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ
๊ธฐ๋ณธ MySQL ์ค์ ์ /etc/mysql/my.cnf ํ์ผ์ ์์ฑ๋์ด ์๊ณ , ์๋์ ๊ฐ๋ค.
์์ฑ๋์ด ์๋ ๋ด์ฉ์ ๋ณด๋ฉด, Custom config๋ /etc/mysql/conf.d/ ๋๋ ํ ๋ฆฌ ๋ด๋ถ์ ์์ฑํด์ผ ํ๋ค๊ณ ๋์์๋ค.
!includedir : ๋ช ์๋ ๋๋ ํ ๋ฆฌ ๋ด๋ถ์ ๋ชจ๋ .cnf ํ์ผ๋ค์ ํฌํจํ๋ค๋ ๊ฒ์ด๋ค.
๋ฐ๋ผ์ ๋ก์ปฌ์์ ์ถ๊ฐ๋ก ์ปค์คํ ์ค์ ์ด ํฌํจ๋ .cnf ํ์ผ์ ๊ตฌ์ฑํ์ฌ ํด๋น ํ์ผ์ docker ์ปจํ ์ด๋ ๋ด๋ถ์ /etc/mysql/conf.d/์ ์ ๋ฌํ๋ฉด ๋๋ ๊ฒ์ด๋ค.
์์์ ์์ฑํ docker-compose.yml์ volumes ์ต์ ์ ํตํด ์ ๋ฌ์ด ๊ฐ๋ฅํ๋ค.
MySQL ์ปจํ ์ด๋๊ฐ ์์๋ ๋ ๊ธฐ์กด์ /etc/mysql/my.cnf์ /etc/mysql/conf.d/~~.cnf์ ์ค์ ์ด ์ข ํฉ์ ์ผ๋ก ๋ฐ์๋๋ค.
#๏ธโฃ MySQL ์ค์ ์ถ๊ฐ
MySQL์ UTF-8์ 3byte๋ก ํํ๋๋ ๋ฒ์๋ด์ Char๋ง ์ ๋ ฅํ ์ ์์ง๋ง ์ด๋ชจ์ง์ฒ๋ผ 4byte๋ก ํํ๋๋ ๋ฌธ์๋ฅผ ์ ์ฅํ๊ธฐ ์ํด์๋ MySQL ์๋ฒ์ DBMS์ ์ธ์ฝ๋ฉ์ utf8mb4๋ก ์ค์ ํด์ผ ํ๋ค.
# /conf.d/my.cnf
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
์์ ๊ฐ์ด []์ ์์ฑ๋ ๊ทธ๋ฃน๋ณ๋ก ์ต์ ์ ์ค์ ํ ์ ์๋ค.
[client] : ๋ชจ๋ ์ฐ๊ฒฐ๋ clients์๊ฒ ๋ฐ์๋จ (mysql cli ํฌํจ)
[mysql] : mysql command line client์ ๋ฐ์๋จ
[mysqld] : mysql server์ ๋ฐ์๋จ
stackoverflow - MySQL configuration file sections
โ๏ธMySQL ์ฐ๊ฒฐ ๋ฐ ๋ฐ์ดํฐ ์ ์ฅ
๐กdocker ๊ด๋ จ ๋ช ๋ น์ด
$ docker-compose -f docker-compose-dev.yml up -d
$ docker-compose -f docker-compose-dev.yml down
# ์ปจํ
์ด๋ ์ ์
$ docker exec -it devook-db /bin/bash
# MySQL ์ ์
$ mysql -u root -p cool
mysqlclient ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ MySQLdb ๋ชจ๋์ ์ฌ์ฉํ์๋ค.
import MySQLdb
def connect_db(user, passwd, host, db):
return MySQLdb.connect(
user=user,
passwd=passwd,
host=host,
db=db
)
def disconnect_db(conn):
conn.commit()
conn.close()
def insert_into_database(items, user, passwd, host, db):
conn = connect_db(user=user, passwd=passwd, host=host, db=db)
cursor = conn.cursor()
cursor.execute("DROP TABLE IF EXISTS post") # ํด๋น ํ
์ด๋ธ์ด ์ด๋ฏธ ์กด์ฌํ ๊ฒฝ์ฐ ์ญ์
cursor.execute(
"CREATE TABLE post "
"(id int AUTO_INCREMENT PRIMARY KEY, "
"url char, "
"title char, "
"description text, "
"category char)"
) # ์๋ก์ด ํ
์ด๋ธ ์์ฑ
sql = "INSERT INTO post(url, title, description, category) VALUES(%s, %s, %s, %s)"
for item in items:
values = (item[0], item[1], item[2], item[3])
cursor.execute(sql, values)
disconnect_db(conn=conn)