출처 : 변성윤님 블로그.
출처 : 부스트캠프 AI Tech.
1. Docker 소개
1.1 가상화란?
- 도커에 대해 알기 전에 먼저 “가상화” 라는 개념을 잘 알아야 수월함
- 가상화란 무엇이고, 왜 알아야 하는걸까요?
- 개발할 때, 서비스 운영에 사용하는 서버에 직접 들어가서 개발하지 않음
- Local 환경에서 개발하고, 완료되면 Staging 서버, Production 서버에 배포
- 개발을 진행한 Local 환경과 Production 서버 환경이 다른 경우
- 예) Local 환경은 윈도우 - 서버 환경은 Linux
- OS가 다르기 때문에 라이브러리, 파이썬 등 설치할 때 다르게 진행해야 함
- 예) Local 환경은 윈도우 - 서버 환경은 Linux
- Local 환경과 서버가 같은 OS를 사용해도, 서버에서 올바르게 작동하지 않을 수 있음
- 예)
- Local의 환경 변수
- Production 서버의 환경 변수(Env)
- Production 서버의 사용자 그룹, Permission
- 예)
- 다양한 설정을 README 등에 기록하고, 항상 실행하도록 하는 방법
- 사람이 진행하는 일이라 Human Error 발생
- 매번 이런 작업을 해야 하는 과정이 귀찮음
- 예)
- Jupyter Notebook 서버를 만들기 위해 클라우드에서 클릭 - 이름 - 클릭 만들기 => 인스턴스로 접속해서 필요한 패키지 설치하는 과정
- 운영하고 있는 Server가 100대라면?
- 특정 서버 업데이트가 진행되었다면(윈도우, 스마트폰 OS 자동 업데이트 실행) => 나머지 서버에도 모두 접속해 업데이트 필요
- 이 부분에서 생기는 고민 : 서버 환경까지도 모두 한번에 소프트웨어화 할 수 없을까? 밀키트처럼 만들어서 집에서도 사용하고 레스토랑에서도 사용하는 방법은?
- 이런 고민을 해결하기 위해 나온 개념이 “가상화” (엄밀하게는 하드웨어 가상화 등 더 넓은 개념이지만, 여기선 소프트웨어 가상화로 한정)
- 특정 소프트웨어 환경을 만들고, Local, Production 서버에서 그대로 활용
- 개발(Local)과 운영(Production) 서버의 환경 불일치가 해소
- 어느 환경에서나 동일한 환경으로 프로그램을 실행할 수 있음
- 개발 외에 Research도 동일한 환경을 사용할 수 있음
1.2 Docker 등장하기 전
- 가상화 기술로 주로 VM(Virtual Machine)을 사용
- VM은 호스트 머신이라고 하는 실제 물리적인 컴퓨터 위에, OS를 포함한 가상화 소프트웨어를 두는 방식
- 예)
- 호스트 머신은 Window인데, Window에서 Linux를 실행
- 호스트 머신은 Mac인데, Mac에서 Window를 실행
- 그러나 OS 위에 OS를 하나 더 실행시키는 점에서 VM은 굉장히 리소스를 많이 사용
- 이런 경우를 “무겁다” 라고 표현
- Container : VM의 무거움을 크게 덜어주면서, 가상화를 좀 더 경량화된 프로세스의 개념으로 만든 기술
- 이 기술의 등장으로 이전보다 빠르고 가볍게 가상화를 구현할 수 있음
1.3 Docker 소개
- Container 기술을 쉽게 사용할 수 있도록 나온 도구가 바로 Docker
- 2013년에 오픈소스로 등장
- 컨테이너에 기반한 개발과 운영을 매우 빠르게 확장
- Docker와 비슷한 느낌
- PC방에서 특정 게임만 설치하고, 고객이 특정 프로그램을 깔아도 재부팅할 때 항상 PC방에서 저장해둔 형태로 다시 복구
- Docker Image로 만들어두고, 재부팅하면 Docker Image의 상태로 실행
- Docker Image
- 컨테이너를 실행할 때 사용할 수 있는 “템플릿” - Read Only
- Docker Container
- Docker Image를 활용해 실행된 인스턴스 - Write 가능
1.4 Docker로 할 수 있는 일
- 다른 사람이 만든 소프트웨어를 가져와서 바로 사용할 수 있음
- 예) MySQL을 Docker로 실행
- 예) Jupyter Notebook을 Docker로 실행
- 다른 사람이 만든 소프트웨어 : Docker Image
- OS, 설정을 포함한 실행 환경
- Linux, Window, Mac 어디에서나 동일하게 실행할 수 있음
- 자신만의 이미지를 만들면 다른 사람에게 공유할 수 있음
- 원격 저장소에 저장하면 어디서나 사용할 수 있음
- 원격 저장소 : Container Registry
- 회사에서 서비스를 배포할 때는 원격 저장소에 이미지를 업로드하고, 서버에서 받아서 실행하는 식으로 진행
2. Docker 실습하며 배워보기
2.1 설치하고 실행하기
- 도커 공식 홈페이지에서 자신의 운영체제에 맞는 Docker Desktop 설치
- 설치 후, 터미널에서 docker 커맨드가 동작하는지 확인
2.1.1 docker image 다운
- docker pull "이미지 이름:태그"
# docker pull mysql:8로 mysql 8 버전의 이미지를 다운
$ docker pull mysql:8
2.1.2 docker image 확인
- docker images
$ docker images
2.1.3 docker container 실행
- docker run "이미지 이름 :태그"
- name : container 이름
- e : environment : 환경변수설정 (비밀번호 설정)
- d : demon(background) mode : background 모드
- p : port 3306:3306 : local port/container port -> local 포트로 3306 접속시 container 연결되도록 설정
- mysql default port : 3306
- mysql:8 : Docker Image
$ docker run --name mysql-tutorial -e MYSQL_ROOT_PASSWORD=1234 -d -p 3306:3306 mysql:8
2.1.4 docker ps
- 실행중인 컨테이너 확인
- a : 모든 컨테이너
$ docker ps -a
2.1.5 docker container 진입
- docker exec -it "Container Name, ID" /bin/bash
- it : interactive
- ssh 접속과 유사
$ docker exec -it mysql-tutorial /bin/bash
root@c02eb58c9ee7:/# mysql -u root -p
2.1.6 docker container 진입 안될 경우 // docker logs 보기
- docker 가 빌드 되다 망가졌을때
- Error response from daemon: Container 81c07e4a69519c785b12ce4512a8ec76a10231ecfb30522e714b0ae53a0c9c68 is restarting, wait until the container is running
- docker logs --tail 50 --follow --timestamps "Container Name, ID"
$ docker logs --tail 50 --follow --timestamps mediawiki_web_1
$ docker exec -it mysql-tutorial /bin/bash
root@c02eb58c9ee7:/# mysql -u root -p
2.1.7 docker rm "컨테이너 이름"
- 멈춘 컨테이너를 삭제
- f : 실행중인 컨테이너 삭제
$ docker rm "mysql-tutorial"
$ docker rm "mysql-tutorial" -f
2.1.8 docker rmi "이미지 이름"
- 도커 이미지 삭제
$ docker rmi mysql:8
$ docker rmi 8f6dd244e5bf
2.1.9 docker stop "컨테이너 이름"
- 실행중인 컨테이너 중지
$ docker stop "mysql-tutorial"
2.1.10 docker start "컨테이너 이름"
- 중지 컨테이너 재시작
$ docker start "mysql-tutorial"
2.1.11 docker restart "컨테이너 이름"
- 가동중인 컨테이너 재시작
$ docker restart "mysql-tutorial"
2.1.12 Docker Volume Mount
- Docker Container 내부는 특별한 설정이 없으면 컨테이너를 삭제할 때 파일이 사라짐
- (Host Container 사이에 파일 공유 X)
- Host 와 Container 사이의 저장소 공유필요
- Volumne Mount 진행, Host/Container 폴더가 공유
- v : -p 와 유사 : -v Host_Folder:Container_Folder
$ docker run it -p 8888:8888 -v /path/to/the/host/directory:/home/path/to/the/container/directory
2.1.12 Docker Hub Registry
- Dockerhub에 공개된 모든 이미지를 다운받을 수 있음
- MySQL도 Dockerhub에서 다운로드
- Dockerhub에 왠만한 오픈소스들이 공개되어 있고, 우리는 필요한 이미지를 찾아 실행!
2.2 Docker Image 만들기
2.2.1 Docker 환경 설정
- 먼저 폴더를 하나 만들고, 여기에 가상환경 세팅과 FastAPI 패키지를 설치
- GET /hello 로 요청하면, 메시지를 전달하는 간단한 코드를 작성
- pip freeze : 설치한 라이브러리를 모두 보여줌
- 또는 pip list --not-required --format=freeze : 의존성에 따라 설치된 라이브러리는 보이지 않음 pip로 설치한 라이브러리를 모두 requirements.txt에 저장
2.2.2 Dockerfile 작성
- Dockerfile라는 파일을 만들어 다음처럼 작성(Docker Image를 빌드하기 위한 정보가 담김)
2.2.3 Docker Image Build
- docker build “Dockerfile이 위치한 경로”
- 이미지 생성(빌드라고 표현)
- 아래 이미지에서 . 는 현재 폴더에 Dockerfile이 있음을 의미
- t "이미지 이름:태그" 옵션으로 이미지 이름과 태그 지정할 수 있음 태그는 미 지정시 "latest"로 채워짐
$ docker build . -t my-fastapi-app
- 빌드를 마치면 docker images 명령어로 방금 빌드한 이미지를 확인할 수 있음
$ docker build . images
2.2.4 Docker Container 실행
- docker run “이미지 이름:태그” 방금 만든 이미지를 실행!
- 태그가 “latest” 인 경우 생략 가능
- 다른 터미널을 열어 curl로 애플리케이션이 잘 작동하는지 확인할 수 있음
2.2.5 Docker Image 정리
- 파이썬 환경 및 애플리케이션 코드를 작성
- Dockerfile 작성
- FROM으로 베이스 이미지를 지정
- COPY로 로컬 내 디렉토리 및 파일을 컨테이너 내부로 복사
- WORKDIR로 RUN, CMD 등을 실행할 컨테이너 내 디렉토리 지정
- RUN으로 애플리케이션 실행에 필요한 여러 리눅스 명령어들을 실행
- CMD로 이미지 실행 시 바로 실행할 명령어를 지정
- docker build “Dockerfile이 위치한 경로” -t “이미지 이름:태그” 으로 이미지 빌드
- docker run “이미지 이름:태그”로 빌드한 이미지를 실행
- 그 외에 Dockerfile에서 사용하는 것
- EXPOSE : 컨테이너 외부에 노출할 포트 지정
- ENTRYPOINT : 이미지를 컨테이너로 띄울 때 항상 실행하는 커맨드
- RUN vs CMD vs ENTRYPOINT 차이점
- RUN : docker container 실행시 이미지 빌드를 위해 진행. 즉, 재실행되는 contiainer 의 경우에는 실행 안함
- Base Image의 Layer를 추가하는 작업
- Layer가 많아질수록 효율적이지 않으므로 한줄 작업 추천
- CMD : docker container 실행시 default로 실행되는 프로세스 - docker 실행시 overriding 가능
- ENTRYPOINT : dokcer container 실행시 default로 실행되는 프로세스 - docker 실행시 overriding 불가 (가능은 함)
- RUN : docker container 실행시 이미지 빌드를 위해 진행. 즉, 재실행되는 contiainer 의 경우에는 실행 안함
2.3 Registry에 Docker Image Push
- 도커 이미지를 인터넷에 업로드!
- 이를 위해 이미지 저장소인 Container Registry에 Docker Image Push
- Container Registry : Dockerhub, GCP GCR, AWS ECR 등
- 별도로 지정하지 않으면 기본적으로 Dockerhub를 사용. 우리는 GCP의 GCR을 사용
- 이제 로컬에서 GCR로 이미지를 Push할 준비
- 먼저 gcloud를 로그인하고, 프로젝트 세팅
- gcloud : 구글 클라우드 플랫폼 제품을 CLI로 쉽게 사용할 수 있도록 만든 도구
- Cloud SDK Install 에서 OS를 확인한 후 다운로드 및 실행
3. Docker 이미지로 배포하기
3.1 Serverless Cloud 서비스(Cloud Run)
- [Product Serving] 3-2. Docker.pdf 참고
3.2 Compute Engine에 Docker Image 배포하기(Streamlit)
- [Product Serving] 3-2. Docker.pdf 참고
Error1 발생 - github action 에서 에러. ㅜㅜ
Error: Unable to resolve action `google-github-actions/setup-gcloud@master`, unable to find version `master`
Error1 Fix
- 해결법 : https://stackoverflow.com/questions/71578595/github-actions-error-on-run-google-github-actions-setup-gcloudmaster-how-to
- Boostcamp-AI-Tech-Product-Serving/.github/workflows/deploy_docker.yml 파일
- 아래 1번을 2번으로 수정
#1 - uses: google-github-actions/setup-gcloud@master #2 - uses: google-github-actions/setup-gcloud@v0
Error2 발생 - github action 완료 but deploy failed
Error2.1. 발생 로그 check
- GCP SSH에서 2.1.5 docker container 진입 하려고 했으나 아래와 같은 에러 발생
- Error response from daemon: Container 81c07e4a69519c785b12ce4512a8ec76a10231ecfb30522e714b0ae53a0c9c68 is restarting, wait until the container is running
- 2.1.6 docker container 진입 안될 경우 // docker logs 보기 보기 실행
- gcp TypeError: Descriptors cannot not be created directly.
~
Error2.2. Fix
- Boostcamp-AI-Tech-Product-Serving/part2/04-cicd/Dockerfile 에 PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION env 설정
FROM python:3.8.7-slim-buster
COPY requirements.txt ./requirements.txt
RUN pip install -r ./requirements.txt
COPY . /app
WORKDIR /app
ENV PROTOCOL\_BUFFERS\_PYTHON\_IMPLEMENTATION python
EXPOSE 8501
ENTRYPOINT \["streamlit", "run", "app.py", "--server.port", "8501"\]
잘돌아감
3.3 Docker Compose
```
- [Product Serving] 3-2. Docker.pdf 참고
```
'MLOps' 카테고리의 다른 글
MLOps - 17. MLFlow (0) | 2022.06.01 |
---|---|
MLOps - 16.Logging (0) | 2022.05.31 |
MLOps - 14. FastAPI (0) | 2022.05.29 |
MLOps - 13. FastAPI (0) | 2022.05.28 |
MLOps - 12. FastAPI (0) | 2022.05.27 |
댓글