Docker, Github Actions
주요 메모 사항
웹 서비스를 Docker로 실행해보기
Hangman 웹서비스를 Github을 통해 Docker Image로 Docker Hub에 업로드
이 챕터를 위해 필요한 것들
Github 계정
Docker Hub 계정
Docker가 설치된 컴퓨터
본인 Github 계정 아래 존재하는 hangman repo
- https://github.com/learndataeng/hangman_web 를 포크
-> 이에 대해 별도로 설명하고 이 repo에 Dockerfile을 추가해볼 예정
웹서비스를 Docker로 구동해보는 전체 과정 익히기
hangman_web이라는 repo의 main에 코드가 머지될 때마다 다음을 수행
1. 테스트 수행
2. Docker Image 빌드
- 이를 위해 Dockerfile 부터 만들어볼 예정
3. Docker Image를 Docker Hub로 푸시
ㄴ> 위 과정을 Github repo에 Github Actions으로 구현!
전체 과정을 시각화
Hangman 프로그램
https://github.com/learndataeng/hangman_web
hangman 프로그램을 flask를 사용하여 웹으로 노출
- 포트번호는 어디든 바인딩 가능하며 실행할 때 지정
- flask 관련 모듈 설치가 필요함: requirements.txt
실행 방법
- python3 -m flask run --host=0.0.0.0 --port=4000, -> 이 경우 app.py를 기본으로 사용함
app.py
flask의 메인 함수가 있고 커맨드라인으로 받은 포트에 바인드하고 요청이 들어오기를 기다림
test.py
app.py에 있는 코드의 유닛 테스트 로직이 들어가 있음. CI/CD 구성시 실행이 되게 구성할 예정
requirements.txt - flask 모듈들을 설치
로컬에서 먼저 테스트
그리고 나의 ubuntu 서버에서도 테스트
Hangman 서비스를 Docker Image로 구성
Docker 컨테이너 내부 프로세스와 호스트 프로세스간의 통신
Docker 컨테이너로 포트 4000에 실행된 Flask app이 있다
이 app을 호스트 운영체제에서 접근하려면? 포트포워딩 필요
Docker 컨테이너 내부 프로세스가 오픈한 포트번호는 바깥 프로세스에는 안 보임
-> 예를 들어 앞서 4000번 포트는 호스트 프로세스 브라우저에게는 안 보임
Docker 컨테이너 내부 프로세스가 오픈한 포트번호를 외부로 노출해주는 것이 포트포워딩
ssh 서버를 열때 필요한 포트포워딩이랑 똑같은 의미
docker run 수행시 -p 옵션 사용
- $ docker run -p 4000:4000 이미지이름
hangman repo에 Dockerfile 추가하기
앞서 1장에서 만들어본 Dockerfile에 대한 설명을 참고하여 Dockerfile 추가
- FROM에 사용할 베이스 이미지로는 python:3.8-slim-buster을 사용
- RUN에서는 pip3 install -r requirements.txt가 지정되어야함
이 이미지를 labs.play-with-docker.com에서 다운로드받아 실행해볼 것
필자는 wsl -> ubuntu에서 진행
- 여기서 해당 Flask app을 오픈해볼 수 있음
dockfile build image
만약 여기에서 inspect 명령어를 사용해보면? 중간에 Labels로 지정한 Maintainer 확인 가능
그러면 빌드한 이미지를 실행해보자
오류가 발생함, 왜? -> 4000번 포트를 열었으나, container - image 에서 4000번 포트포워딩을 한것이지 서버 - 컨테이너 에서의 포트포워딩은 안되어있는 것임
그렇다면 명령어를 바꿔서 실행해보자
잘 실행되는 것을 확인할 수 있음!
아마도 -p 명령어로 서버:컨테이너 포트포워딩을 해주는게 아닌가 싶음
docker container를 명령어로 종료시키기, 포트를 지정하지 않았던 컨테이너 종료
이미지를 Docker Hub에 등록해볼 것
- 사실 Docker Hub에 가서 repo를 먼저 만들지 않고 바로 docker push 명령으로 만들면서 업로드 가능
- 위의 방법을 사용해 실습할 예정
먼저 필자의 docker hub repo를 보자, 없는 것을 확인
docker push 명령어 실행
그러면 웹에서 새로고침, 바로 업로드된 것을 확인할 수 있음
해당 docker repo를 임시 인스턴스 에서 다시 테스트 해보자
- https://labs.play-with-docker.com/
-> Dockerfile을 본인 github repo에 커밋 (밑에서 다룸 먼저 CI/CD와 Github Actions 부터 설명)
CI/CD와 Github Actions 소개
소프트웨어 빌드란?
- 자신(혹은 팀)이 개발한 소프트웨어를 최종적으로 출시하기 위한 형태로 만드는 것
ㄴ> 테스트가 빌드의 중요한 일부로 포함
- 참여 개발자들이 많을수록 이는 더 중요
- 개발이 끝나기 전부터 빌드를 하면 소프트웨어의 안정성 증대
ㄴ> Continuous Integration, 빌드를 성공적으로 마치면 이렇게 표현
결국에 회사에서 이를 실현하기 위해서는 그만한 이유와 인력, 비용이 필요함
Continuous Integration이란?
Software Engineering Practice의 하나
기본 원칙
- 코드 Repo는 하나만 유지 (Master)
- 코드변경을 최대한 자주 반영
ㄴ 작은 기능을 변경해도 브랜치 하나 생성해서 merge하고 하는 방식으로 해야함. 나중에 한번에 하려다가 고생!
- 테스트를 최대한 추가 >> Test Coverage
- 빌드를 계속적으로 수행 (자동화) >> Commit Build vs. Nightly Build
- 성공한 빌드의 프로덕션 릴리스 (자동화) >> CD: Continuous Delivery
빌드 실패!
- 새 코드의 커밋으로 인해 테스트가 실패하는 경우
- 많은 회사들이 빌드 실패시 빌드가 다시 성공할때까지 코드 변경을 금지
ㄴ 즉 빌드 실패는 모든 사람들을 잡아두는 족쇄
ㄴ 그래서 어느 정도 조직이 커지면 빌드만 전담하는 엔지니어가 생김
ㄴ 이 사람의 업무 중의 하나는 빌드 실패시 누가 주범인지 알아내는 것이라고 한다 ㄷ
ㄴ 빌드실패시 가벼운 형태로 페널티 부여 >> 기용님이 Youtube eo 채널에서 인터뷰 하신 내용을 찾아보면 재미있는 문화인 것 같음
CI/CD란?
Git이란? 패스
Push나 Merge 시점이 CI/CD를 실행하기 위한 절호의 순간
코드가 메인/마스터나 브랜치에 추가되는 순간 CI/CD를 트리거
ㄴ 이를 특정 메인/마스터나 특정 브랜치만 대상으로 하도록 설정 가능
ㄴ 이 때 테스트 수행하고 최종적으로 Docker Image등을 만들도록 하는 것이 가능
ㄴ 그래서 CI/CD는 Github에 구현하는 것이 가장 자연스러움
Github에서는 이를 Actions라는 기능을 통해 Workflow라는 이름으로 구현 가능
Github Actions이란?
CI/CD를 Github위에서 구현하기 위한 서비스
ㄴ 코드 테스트, 빌드, 배포 자동화 기능 제공
Workflow라 부르며 아래 컴포넌트로 구성
ㄴ Events
ㄴ Jobs
ㄴ Actions
ㄴ Runner
ㄴ Github hosted runners
ㄴ self hosted runners
Github Actions - Workflow
Workflow는 트리거 이벤트가 발생하면 시작되는 일련의 동작들을 지칭
트리거 이벤트의 예들은?
- 코드 커밋, main과 같은 특정 브랜치를 대상으로만 제한 가능
- PR 생성
- 다른 Workflow의 성공적인 실행
Workflow를 위한 명령어들은 YAML 파일로 저장
ㄴ 명령어들로는 환경설정과 scripts 실행들이 대표적
Workflow는 Job들로 나눠지며 각 Job은 일련의 스텝을 수행
- 각 스텝은 하나 혹은 그 이상의 명령어를 실행
ㄴ 이 명령어는 actions라고 부르는 명령어들의 집합이 될 수도 있음
- 각 스텝은 윈도우나 리눅스 서버 위에서 runner에 의해 실행
ㄴ 이걸 Docker Image에서 수행하는 것이 서비스 배포 과정에 따라 더 일반적이기도 함
Github에서 어떻게 Github Actions을 선택?
적용하려는 repo에 보면 Actions 메뉴
다음으로 workflow를 하나 생성
yml 파일을 직접 생성 혹은 템플릿(CI Templates) 선택 후 수정
ㄴ Python Application 혹은 Docker Image
Github Actions : 테스트 추가
https://github.com/usiohc/hangman_web
learndataeng/hangman_web repo를 본인의 Github 어카운트로 fork
ㄴ 여기에 앞서 만든 Dockerfile도 있어야함!
ㄴ test.py에 unittest 모듈을 이용한 테스트 코드가 존재
Github Actions를 통해 main 브랜치에 push나 PR이 있는 경우 test.py를 실행할 예정
ㄴ 하나의 repo에 대해 다수의 workflow들이 존재 가능
ㄴ 모두 .github/workflows/ 밑에 yml 파일 형태로 존재
사용해볼 CI Template: Python Application
Python Application이란 CI Template을 사용할 예정
ㄴ 테스트 코드 실행 이외에도 flake8을 사용해서 코딩 스타일을 체크해볼 예정
기본으로 pytest를 테스트 프레임웍으로 설치 -> 우리는 unittest로 작성되어 있음
Python code linting tool으로 flake8을 설치하고 문법 에러와 코딩 스타일 체크
파이썬 코드 스타일 체크 - flake8
파이썬 코드에서 에러나 코딩 스타일 등에서 이슈를 체크해주는 툴
ㄴ 이런 툴을 Linting tool이라 부름 (언어별로 존재)
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
ㄴ 위와 같은 방식으로 사용함, 다양한 옵션이 존재하는 듯?
line 3에 12번째에 구문에러, 콜론이 없음!
테스트 코드 소개
unittest를 사용 (pytest라는 대안도 있음)
테스트 코드 실행
Github Actions 세팅
.github/workflows/python-app.yml
“on”: 트리거 이벤트 지정. main 브랜치에 push되거나 PR이 만들어지는 경우
jobs: 여기에 실제 CI 프로세스가 스텝(name)별로 기술됨. 여긴 빌드 하나임
기본값이 pytest로 되어 있는 것을 수정 -> unittest
30번 line requirements.txt가 있으면 이를 설치 requirements.txt가 있으면 이를 설치
29번 line에 pytest는 삭제, 37 39번 라인도 pytest를 unittest 리팩터링!
새롭게 브랜치를 만들고 PR 생성 -> 병합 -> 해당 브랜치 삭제
만약 빌드가 실패하면 X 표시가 나오는 것 같다! -> .yml에 ' 를 빼먹었다
노란색 점으로 나오면 빌드를 진행중이라는 뜻
빌드 성공시 초록색 체크표시!
테스트로 README를 커밋해 트리거가 잘 동작하는지 확인!
Github Actions Dockerization 추가
Hangman Github repo에 Github Action을 통해 Docker Image 빌드/푸시
사용해볼 Template: Docker Image
1. docker login
ㄴ 이 때 Docker hub ID와 Password를 읽어와야함. 하드코딩하지 않고 Github내에 저장 (뒤에서 더 설명)
ㄴ secrets.DOCKER_USER, secrets.DOCKER_PASSWORD 환경변수처럼 세팅하는 것 같다
사용할 repo의 Settings에서 Secrets and variables >> Actions를 들어가면 추가할 수 있다.
Docker Hub 정보 보관
DOCKER_USER, DOCKER_PASSWORD 라는 이름으로 KEY를 설정
그러면 이를 YML에서 어떻게 접근할까?
ㄴ ${{secrets.DOCKER_USER}}
ㄴ ${{secrets.DOCKER_PASSWORD}}
2. docker build
사실 18번 라인의 env로 굳이 해줄 필요는 없음, 21번 라인에서 바로 작성해도 가능!
3. docker push
기존에 설정한 Python applications Actions도 같이 작동하는 것을 확인할 수 있음
그 외
사실 2개의 CI Actions을 만든거지만, 이거를 1개로 작성해도 된다고 하심
아마도 python-app.yml 에서 docker-image 템플릿을 사용해 repo에 맞게 수정하고 한번에 작성하는 것 같음
공부하며 어려웠던 내용
vscode로 ubuntu 서버에 접속해서 실습하는데 git을 연동하는데 애먹었다...
ㄴ> 서버에서 .git/config 파일에 기존에 clone할때 http로 접속했던걸 ssh로 바꿔주는 작업과 rsa Key를 등록하는 과정이 필요했음!
'프로그래머스 데브코스-데이터 엔지니어 > TIL(Today I Learned)' 카테고리의 다른 글
06/15 49일차 개발환경 구축을 위한 Docker & K8s (4) (0) | 2023.06.15 |
---|---|
06/14 48일차 개발환경 구축을 위한 Docker & K8s (3) (2) | 2023.06.14 |
06/12 46일차 개발환경 구축을 위한 Docker & K8s (1) (0) | 2023.06.12 |
06/09 45일차 데이터 파이프라인과 Airflow (5) (0) | 2023.06.09 |
06/08 44일차 데이터 파이프라인과 Airflow (4) (0) | 2023.06.08 |