[Product Serving Part.3] Docker
- -
가상화
- 개발을 진행한 Local 환경과 Production 서버 환경이 다른 경우,
OS가 다르기 때문에 라이브러리, 파이썬 등 설치할 때 다르게 진행해야 한다.
Local: 윈도우 ↔ Production 서버: Linux - Local과 Production 서버가 같은 OS를 사용해도, Local의 환경 변수와 Production 서버의 환경 변수등이 달라서 올바르게 작동하지 않을 수 있다.
- 개발환경 설정을 README에 기록하고 실행하도록 하면 사람이 진행하는 일이라 Human Error가 발생하거나 번거롭다.
또 운영하는 서버가 1000대이고, 특정 서버 업데이트가 진행되었다면 나머지 서버에도 다 업데이트가 필요한데 일일이 하기에는 너무 오래걸린다.
⇒ 서버 환경까지도 모두 소프트웨어화 할 수 없을까? ⇒ 가상화
특정 소프트웨어 환경을 만들고, Local/Production 서버에서 그대로 활용할 수 있다.
Docker 등장 전에는 가상화 기술로 VM을 사용하였다.
VM : 호스트 머신이라고 하는 실제 물리적인 컴퓨터 위에, OS를 포함한 가상화 소프트웨어를 두는 방식
ex) 호스트 머신은 Window인데, Window에서 Linux를 실행
→ GCP의 Compute Engine 또는 AWS의 EC2
클라우드 회사에서 미리 만든 이미지를 바탕으로 Computing 서비스를 통해 사용자에게 동일한 컴퓨팅 환경 제공
그러나 OS 위에 OS를 하나 더 실행시키는 것은 리소스를 굉장히 많이 사용하는 일이다.
이를 해결하기 위해 등장한 기술이 Container 이다.
Container : VM의 무거움을 크게 덜어주면서, 가상화를 좀 더 경량화된 프로세스의 개념으로 만든 기술
Docker
이런 Container 기술을 쉽게 사용할 수 있도록 나온 도구
Docker Image
- 컨테이너를 실행할 때 사용할 수 있는 "템플릿"
- Read Only
- 다른 사람이 만든 소프트웨어라고 생각할 수 있다.
- OS, 설정을 포함한 실행환경
- Linux, Window, Mac 어디에서나 동일하게 실행할 수 있다.
Docker Container
- Docker Image를 활용해 실행된 인스턴스
- Write 가능
Docker로 할 수 있는 일
- 자신만의 이미지를 만들고 원격저장소(Container Registry)에 저장하면 어디서나 사용할 수 있다.
Docker로 MySQL 실행하기
이미지 다운로드
docker pull "이미지 이름:태그"
docker pull mysql:8
다운받은 이미지 확인
docker images
컨테이너 실행
docker run --name mysql_practice -e MYSQL_ROOT_PASSWORD=1234 -d -p 3306:3306 mysql:8
- --name : 컨테이너 이름 설정
지정하지 않으면 랜덤설정 - -e : 환경변수 설정
MYSQL root 계정 비밀번호 설정 - -d : 데몬(백그라운드) 모드
이 설정을 하지 않으면 현재 실행하는 셸 위에서 컨테이너가 실행되어 컨테이너의 로그를 바로 확인할 수는 있지만 컨테이너를 나가면 실행이 종료된다. - -p : 포트 지정 (로컬 호스트 포트:컨테이너 포트)
로컬 포트 3306으로 접근 시 컨테이너 포트 3306으로 연결되도록 설정
mysql은 기본적으로 3306 포트를 통해 통신 - mysql:8
아까 다운받은 이미지
실행된 컨테이너 확인
docker ps
중지된 컨테이너까지 확인
docker ps -a
MySQL이 실행되고 있는지 확인하기 위해 컨테이너 진입
User@DESKTOP-FEQ0UC5 /usr/bin
$ docker exec -it mysql_practice bash
MySQL 프로세스로 진입
User@DESKTOP-FEQ0UC5 /usr/bin
$ docker exec -it mysql_practice bash
bash-4.4# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.31 MySQL Community Server - GPL
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
컨테이너 중지
docker stop "컨테이너 이름(ID)"
멈춘 컨테이너 삭제
docker rm "컨테이너 이름(ID)"
실행 중인 컨테이너 삭제
docker rm "컨테이너 이름(ID)" -f
Volume Mount
Host와 Container간의 파일 공유가 되지 않는다.
만일 파일을 유지하고 싶다면 Host와 Container의 저장소를 공유해야한다.
→ -v 옵션
-p 처럼 사용할 수 있다.
-v Host_Folder:Container_Folder
docker run -it -p 8888:8888 -v Host_folder:Container_folder
프로젝트를 위한 Docker Image 만들기
가상환경 생성
User@DESKTOP-FEQ0UC5 MINGW64 ~/Desktop/docker_project_setting
$ py -3.8 -m venv venv
User@DESKTOP-FEQ0UC5 MINGW64 ~/Desktop/docker_project_setting
$ source venv/Scripts/activate
(venv)
User@DESKTOP-FEQ0UC5 MINGW64 ~/Desktop/docker_project_setting
$ pip install pip --upgrade
User@DESKTOP-FEQ0UC5 MINGW64 ~/Desktop/docker_project_setting
$ pip install "fastapi[all]"
FastAPI 코드 작성
#main.py
from fastapi import FastAPI
import uvicorn
app = FastAPI()
@app.get("/hello")
def hello():
return {
"message" : "World!"
}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
사용 라이브러리 requirements.txt에 저장
pip freeze > requirements.txt
Dockerfile 작성
- FROM <baseImage:tag> : 이미지 빌드에 사용할 베이스 이미지를 지정
FROM python:3.8.7-slim-buster - COPY <로컬 디렉토리(파일)> <컨테이너 내 디렉토리(파일)>
컨테이너는 자체적인 파일 시스템과 디렉토리를 가짐
COPY 명령어는 Dockerfile이 존재하는 경로 기준 로컬 디렉토리를 컨테이너 내부의 디렉토리로 복사
COPY . /app → 로컬 프로젝트 폴더 최상위에 존재하는 모든 파일을 컨테이너 내부 /app 디렉토리로 복사 - WORKDIR <컨테이너 내 디렉토리>
Dockerfile의 RUN, CMD 등의 명령어를 실행할 컨테이너 경로 지정
WORKDIR /app → 이 라인 뒤의 등장하는 명령어는 컨테이너 내부의 /app 에서 실행 - ENV <환경변수 이름=값>
컨테이너 내 환경변수를 지정
ENV PYTHONPATH=/app
ENV PYTHONBUFFERED=1 → 파이썬 애플리케이션의 경우 통상 위 두 값을 지정함 - RUN <실행할 리눅스 명령어>
RUN pip install pip==22.3.1 && \
pip install -r requirements.txt
이전 라인에서 COPY와 WORKDIR이 실행되었기 때문에 container 내에 requirements.txt가 존재하고 이를 pip install -r로 실행시킬 수 있다.
&& \ → 한번에 실행할 명령어가 여러개인 경우 이어주는 역할 - CMD [<"실행할 명령어">, <"인자">, ... ]
CMD ["python", "main.py"]
docker run으로 이 이미지 기반 컨테이너를 만들 때 실행할 명령어를 담는다.
CMD는 띄어쓰기를 사용하지 않는다.
RUN과 CMD의 차이는?
RUN 명령어
: 도커파일로부터 도커 이미지를 빌드하는 순간에 실행이 되는 명령어
Docker는 Container를 실행할 때 도커 이미지가 필요하다.
이 이미지를 만들때는 보통 도커 허브의 이미 만들어진 이미지를 베이스 이미지로 놓고,
이 베이스 이미지에 Docker 명령어를 가지고 자신에게 맞는 환경을 하나하나 얹는다. (layer를 더한다고 표현함)
RUN 명령어는 명령을 실행한 결과를 새로운 layer를 더하는 과정으로 볼 수 있다.
CMD 명령어
: RUN 명령어는 이미지를 작성하기 위해 실행하는 명령어라면, CMD는 이미지를 바탕으로 생성된 컨테이너 안에서 명령을 실행하기 위한 명령어
ENTRYPOINT 명령어
: CMD와 마찬가지로 컨테이너 안에서 명령을 실행하기 위한 명령어
그러나 ENTRYPOINT로 정의하는 명령어는 컨테이너가 수행될 때 변경되지 않는다.
Example)
# Dockerfile FROM ubuntu:latest CMD ["echo", "hello"]
prac이라는 이름의 이미지를 빌드
빌드한 이미지 컨테이너로 실행하면서 echo world 명령까지 실행해보면
기존 도커 파일은 "hello"로 실행되도록 되었지만 "world"라고 출력됨을 알 수 있다.
⇒ parser argument의 default값이라고 생각하면 될 것 같다.$ sudo docker build --tag prac . $ sudo docker run prac echo world world
FROM ubuntu:latest ENTRYPOINT ["echo", "hello"]
ENTRYPOINT로 지정하면 명령 인자를 무엇을 주든 무조건 ENTRYPOINT 값이 실행된다.
그리고 뒤에 추가로 실행한 명령어인 echo world 는 매개변수로 처리되어 뒤에 함께 처리된다.$ sudo docker build --tag prac . $ sudo docker run prac echo world hello echo world
그래서 CMD 명령어는 ENTRYPOINT 명령어로 지정된 커맨드에 디폴트로 넘길 파라미터를 지정할 때 사용한다.ENTRYPOINT ["python"] CMD ["helloworld.py"]
Docker 이미지 생성
docker build <Dockerfile이 위치한 경로> -t <이미지 이름:태그>
docker build . -t my-fastapi
생성된 이미지를 확인해보면 잘 생성된 것을 알 수 있음
User@DESKTOP-FEQ0UC5 MINGW64 ~/Desktop/docker_project_setting
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-fastapi latest bebcf58eb45c About a minute ago 253MB
mysql 8 2a04bf34fdf0 5 days ago 535MB
Docker 이미지를 이용해 컨테이너 실행
docker run -p 8000:8000 my-fastapi:latest
User@DESKTOP-FEQ0UC5 MINGW64 ~/Desktop/docker_project_setting
$ docker run -p 8000:8000 my-fastapi:latest
INFO: Started server process [1]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
다른 터미널을 열어 curl로 애플리케이션 동작 확인해보면 정상동작함
User@DESKTOP-FEQ0UC5 MINGW64 ~/Desktop/docker_project_setting
$ curl localhost:8000/hello
{"message":"World!"}(venv)
'부스트캠프 AI Tech 4기' 카테고리의 다른 글
[WEEK08] 회고 (0) | 2022.11.14 |
---|---|
[Product Serving Part.3] MLFlow (0) | 2022.11.11 |
[Product Serving Part.2] Streamlit (0) | 2022.11.08 |
[Product Serving Part.2] Voila (0) | 2022.11.08 |
[Product Serving 개론] 3.머신러닝 프로젝트 라이프 사이클 (0) | 2022.11.07 |