🟣 서로 다른 docker image를 2개 이상 만듦
- "09-실습)도커파일과 도커이미지 생성"에서 했던
DOCKER FILE
과 더불어 다른DOCKER FILE
도 만들었습니다.DB server
의DOCKER FILE
의 codeFROM ubuntu:18.04 RUN apt-get update -y && apt-get upgrade -y RUN apt-get install mysql-server -y RUN apt-get install vim -y EXPOSE 3306
Web server
의DOCKER FILE
의 codeFROM ubuntu:18.04 RUN apt-get update -y && apt-get upgrade -y RUN apt-get install mysql-client -y RUN apt-get install vim -y RUN apt-get install -y python3-pip python3-dev RUN pip3 install --upgrade pip RUN pip3 install pymysql RUN pip3 install fastapi uvicorn RUN pip3 install python-multipart RUN apt-get install -y python3-jinja2 COPY content/. /home/ EXPOSE 80 CMD cd /home && export LC_ALL=C.UTF-8 && python3 -m uvicorn main:app --reload --host=0.0.0.0 --port=80
🟣 서로 다른 image 간에 통신을 하여 무언가를 주고 받음
- 서로 다른 image 간에 통신을 하기 위해 작성한 code(power-shell 사용)
- database
# 파일이 있는 경로에 cd함 cd C:\Users\yuri\Desktop # docker build -t [이미지이름] docker build -t yuri0329/yuricontainer2:1.0 . # docker run -itd --name [컨테이너이름] yuri0329/yuricontainer2:1.0 docker run -itd --name yuridatabase yuri0329/yuricontainer2:1.0 # docker inspect docker inspect bridge # docker container exec -ti [컨테이너이름] /bin/bash docker container exec -ti yuridatabase /bin/bash # vi /etc/mysql/mysql.conf.d/mysqld.cnf # :wq # service mysql start # mysql -u root -p # password 입력 : --> ubuntu # CREATE USER '[MYSQL ID]'@'%' IDENTIFIED BY '[MYSQL_PASSWD]'; CREATE USER 'yuri95'@'%' IDENTIFIED BY 'dbfl#####'; # CREATE DATABASE IF NOT EXISTS [MYSQL_DATABASE이름]; CREATE DATABASE IF NOT EXISTS yuridatabase; # GRANT ALL PRIVILEGES ON [MYSQL_DATABASE이름].* TO '[MYSQL ID]'@'%'; GRANT ALL PRIVILEGES ON yuridatabase.* TO 'yuri95'@'%'; # quit # mysql -h ###.##.#.# -u yuri95 -p # quit # exit
- docker container 1개 추가
# docker build -t [이미지이름] . docker build -t yuri0329/yuricontainer3:1.0 # docker run --name [컨테이너이름] -d -p 80:80 yuri0329/yuricontainer3:1.0 docker run --name yuriweb -d -p 80:80 yuri0329/yuricontainer3:1.0
- docker image push
# container1 docker push yuri0329/yuricontainer2:1.0 # container2 docker push yuri0329/yuricontainer3:1.0
🟣 Main.py
- database는 통신하기 위한 준비이고, main.py에서 직접적인 통신이 이루어짐
from fastapi import FastAPI, Request, Form from fastapi.responses import HTMLResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates import pymysql #------------------------------- 사전 정의부분 host = '172.17.0.2' # docker inspect bridge 로 컨테이너 IP주소 확인 user_id = 'yuri95' # maria DB 사용자 id user_pw = 'dbfl#####' # maria DB 사용자 PW user_name = 'yuri' # maria DB 사용자 테이블에 저장할 사용자이름 db_name = 'yuridatabase' # maria DB 사용할 데이터베이스명 #-------------------------------------------- # Database 초기화 def init_database(): # pymysql 모듈을 이용하여 Database서버의 mariaDB에 접근 (mariaDB 포트 3306) db = pymysql.connect(host=host, port=3306, user=user_id, passwd=user_pw, db=db_name, charset='utf8') #DB과 통신하기위해 사용하는 cursor cursor = db.cursor() #테이블이 존재하면 무시, 존재하지 않으면 CUSTOMER라는 이름으로 테이블 생성 (ID, PASSWS, USER_NAME) 컬럼을 가짐 create_table =''' CREATE TABLE IF NOT EXISTS CUSTOMER ( ID VARCHAR(20) NOT NULL, PASSWD VARCHAR(20) NOT NULL, USER_NAME VARCHAR(20) NOT NULL ); ''' # create_table에 문자열로 입력한 SQL명령을 cursor로 DB에 보내서 실행 cursor.execute(create_table) # 테이블에 이미 들어가있다면 무시, CUSTOMER테이블에 사전에 정의한 user_id, user_pw, user_name을 테이블에 입력 insert_data=''' INSERT IGNORE INTO CUSTOMER(ID, PASSWD, USER_NAME) VALUES (\'{user_id}\', \'{user_pw}\', \'{user_name}\'); ''' #문자열로 입력한 SQL명령을 cursor로 DB에 보내서 실행 cursor.execute(insert_data) #변경된 DB상태 저장 db.commit() #DB연결해제 db.close() # ID와 PASSWD def SearchID(ID, PASSWD): db = pymysql.connect(host=host, port=3306, user=user_id, passwd=user_pw, db=db_name, charset='utf8') cursor = db.cursor() #로그인 성공, 실패 정보를 전달하기위한 표시 flag = False #문자열로 테이블에서 ID와 PW가 같은 정보 검색하는 SQL명령어를 문자열로 저장 search_table_right ="SELECT * FROM CUSTOMER WHERE ID=\'{ID}\' AND PASSWD=\'{PASSWD}\';".format(ID=ID, PASSWD=PASSWD) cursor.execute(search_table_right) #SQL명령어 실행 후, DB에서 나온 결과를 row에 저장 row = cursor.fetchone() # row에 아무것도 없으면 => ID와 PASSWD가 일치하는게 없으면 if row == None: flag = False row=('0', '0', '0') # ID와 PASSWD가 일치하는 정보가 있어서 로그인 성공이라면 else: flag = True db.close() # 실패하면 [False, 0, 0, 0], 성공하면 [True, ID, PASSWD, USER_NAME] 반환 return [flag, row[0], row[1], row[2]] #Database 초기설정 init_database() app = FastAPI() # image, css들어가있는 static 디렉토리 마운트 app.mount("/static", StaticFiles(directory="static"), name="static") # html을 읽어주는 Jinja2에 html들어있는 templates 디렉토리를 지정 templates = Jinja2Templates(directory="templates") # 메인화면, index.html 띄워줌 @app.get("/") async def read_root(request: Request): return templates.TemplateResponse("index.html", {"request": request}) # 로그인 버튼 눌렀을 때, ID와 PASSWD정보가 들어옴 @app.post("/login") async def login(request:Request, ID: str=Form(...), PASSWD: str=Form(...)): # Database에서 ID와 PASSWD를 검색 result = SearchID(ID, PASSWD) print(ID, PASSWD) # 정보가 없을 떄, 로그인 실패, 메인페이지(index.html)로 돌아감 if not result[0] :return templates.TemplateResponse("index.html", {"request": request}) # 정보가 있을 떄, 로그인 성공, 로그인성공페이지(login.html)와 USER_NAME반환 else :return templates.TemplateResponse("login.html", {"request": request, "USER_NAME":result[3]})
🟣 http://localhost/ --> 화면결과 (1)
- 로그인 전의 모습
- 정보를 받은 후 로그인 후의 모습
🟣 만든 docker image들을 docker Hub에 업로드한 결과
docker hub
홈페이지에서 로그인 후,create repository
에 들어가서yuricontainer2
,yuricontainer3
라는 이름으로 만들었다.
- 만든 결과
🟣 docker image 확인
🐷 정리를 하자면...
- Fast API는 nginx, django와 같은 웹서버로, 파이썬 기반임
- django가 아닌, Fast API를 선택한 이유는? : 도커 컨테이너 간의 통신을 빠르게 실습하기 위해서 사용하였고, 이를 통해 html동작과 파이썬 코드로 데이터베이스서버와 통신을 실습하였음
- fastapi를 구동할때 main.py에서 DB서버의 테이블을 세팅 (없다면 생성 및 초기화), 실습을 위해 기본 계정 생성을 진행함
- 웹에서 post방식으로 아이디와 비밀번호가 들어오면 데이터베이스에서 select문으로 검색해서 확인
- 맞다면, 유저이름과 로그인페이지 반환, 다르다면 초기화면 반환함
- Django와 fastapi 차이점에 대한 참고링크: https://tech.toktokhan.dev/2021/06/28/python-web-framework/