📖 학습주제
개발환경 구축을 위한 Docker와 K8S 실습 (2)
웹 서비스를 Docker로 실행해보기
웹서비스를 Docker로 구동해보는 전체 과정
hangman_web이라는 repo의 main에 코드가 머지될 때마다 다음을 수행
- 테스트 수행
- Docker Image 빌드
- 이를 위해 Dockerfile 부터 만들어볼 예정
- 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를 기본으로 사용함
Repo 구성 설명
from flask import Flask,session
app = Flask(__name__)
…
app.secret_key = "Python Study"
if __name__ == "__main__":
app.run()
flask의 메인 함수가 있고 커맨드라인으로 받은 포트에 바인드하고 요청이 들어오기를 기다림
Flask==2.3.2
Flask-HTTPAuth==4.5.0
Flask-Login==0.6.2
Flask-SQLAlchemy==3.0.3
pip3 install -r requirements.txt flask 모듈들을 설치함
- test.py
app.py에 있는 코드의 유닛 테스트 로직이 들어가 있음.
CI/CD 구성시 실행이 되게 구성할 예정
- README.md
Hangman 서비스를 Docker Image로 구성
Docker 컨테이너 내부 프로세스와 호스트 프로세스간의 통신
- Docker 컨테이너 내부 프로세스가 오픈한 포트번호는 바깥 프로세스에는 안 보임
- 예를 들어 4000번 포트는 호스트 프로세스 브라우저에게는 안 보임

- 포트맵핑 : Docker 컨테이너 내부 프로세스가 오픈한 포트번호를 외부로 노출해주는 것
- docker run 수행시 -p 옵션 사용 (docker run -p 4000:4000 이미지이름)
- Docker 컨테이너를 실행할 때 포트 맵핑을 통해 호스트 운영체제 단에서 접근되는 포트를 컨테이너쪽으로 포워드해주어야함

hangman repo에 Dockerfile 추가하기
FROM python:3.8-slim-buster
LABEL Maintainer="*****" #메타데이터로 docker inspect 명령으로 찾아볼 수 있음
WORKDIR /app
COPY app.py ./
COPY requirements.txt ./
RUN pip3 install -r requirements.txt
EXPOSE 4000
CMD ["python3", "-m", "flask", "run", "--host=0.0.0.0", "--port=4000"]
전체 과정 데모
- 과정에서 사용해볼 일부 docker 명령
- docker inspect 명령
- docker run "-d" 옵션
- docker stop 명령
순서:
- docker build --platform=linux/amd64 -t keeyong/hangman .
- docker image ls
- docker inspect keeyong/hangman
- docker run -p 4000:4000 keeyong/hangman
- docker run -p 4000:4000 -d keeyong/hangman
- docker push keeyong/hangman
CI/CD와 Github Actions
소프트웨어 빌드
- 자신(혹은 팀)이 개발한 소프트웨어를 최종적으로 출시하기 위한 형태로 만드는 것
- 테스트가 빌드의 중요한 일부로 포함
- 참여 개발자들이 많을수록 이는 더 중요
- 개발이 끝나기 전부터 빌드를 하면 소프트웨어의 안정성 증대
- Continuous Integration!
Continuous Integration
- Software Engineering Practice의 하나
- 기본 원칙
- 코드 Repo는 하나만 유지 (Master)
- 코드변경을 최대한 자주 반영
- 테스트를 최대한 추가
Test Coverage
- 빌드를 계속적으로 수행 (자동화)
Commit Build vs. Nightly Build
- 성공한 빌드의 프로덕션 릴리스 (자동화)
CD: Continuous Delivery
CI/CD

Git
- 분산환경을 지원하는 소스 버전 컨트롤 시스템
- CVS, SVN은 항상 서버에 연결되어 있다는 전제하에서 사용 가능 (중앙 개발)
- 리눅스를 만든 Linus Torvalds가 개발
- 리눅스 커널 개발을 위해 만들었으며 GPL v2 오픈소스
- SVN/CVS에 비해 현저하게 빠르나 사용법은 훨씬 더 복잡함
장점
- 다수의 개발자가 공동 개발
- 코드 리뷰 가능
- 코드 백업
- 과거의 코드로 롤백 가능
- 팀원들과 코딩을 같이 할 수 있고 코드 충돌이 생기면 이를 해결가능 (구글닥처럼)
- 코드변경을 주기적으로 저장하면서 리뷰를 받을 수 있음
- 모든 코드 변경이 기록 (백업)
- 지금 코드의 스냇샵을 잡아 (이를 버전이라 부름) 나중에 필요시 버전간 이동이 가능
- 사실 이런 모든 작업을 꼭 코드 뿐만 아니라 모든 텍스트 파일에 사용 가능
Git 사용시 필요한 것
- 직접 git을 사용한다면 git이 설치된 컴퓨터와 저장 공간
- 클라우드 버전 사용 (GitHub, BitBucket, GitLab 등등)
- 클라이언트는 별도 설치
- Github이 가장 인기가 많음
Github
- Git repo 호스팅/클라우드 서비스 (http://github.com)
- 대부분의 회사들이 Git을 직접 설치해서 사용하기 보다는 github을 사용
- Git은 텍스트 커맨드라인 툴이지만 Github은 웹기반 인터페이스도 제공 (일부)
- 자신이 만든 repo들이 모두 public일 경우 사용이 무료
– private repo의 수에 따라 가격대가 결정됨
– 개발자들을 위한 Facebook!
- 다양한 툴을 제공하여 생태계 마련
– Code 개발 생산성 증대를 위한 Copilot
– CI/CD등의 다양한 연동을 위한 Workflows 제공
– 또한 문서화를 위한 Wikis와 버그리포트와 트랙킹을 위한 Issues 기능을 제공
Git 관련 용어
Repo : Repository의 준말로 Git으로 관리되는 소프트웨어 프로젝트를 지칭
Master/Main : 한 Repo에서 기본이 되는 메인 코드를 지칭. Git에서는 master이고 github에서는 이제 main
Branch : 자신의 Repo에서 새로운 기능 개발등을 위해 Master 혹은 다른 Branch로부터 만든 코드 작업본을 지칭. 작업 후 나중에 원본 Branch와 다시 병합하려는 목적으로 만들어짐
Clone : 다른 계정에 존재하는 repo로부터 새로운 local repository를 만드는 것
Commit (Check-in) : 내가 만든 코드 변경을 Branch의 Local Repository에 반영하는 것
Pull : Master와 같은 Remote Repo로부터 마지막 Pull이후 변경된 것을 다시 가져오는 작업. 즉 Master(혹은 Branch)와 씽크하는 것을 지칭
Push : 작업 중인 로컬 복사본 (Local Repo)에서 서버(Remote Repo)로 변경사항들을 복사하는 것을 지칭
Merge : Pull이나 Push했을 경우 두 Branch(대부분 이 중 하나는 Master)간의 충돌(Conflict)을 해결하는 과정
메인/마스터 브랜치

- Github에서는 이전에 master라 불렀고 지금은 main이라 부르는 source of truth가 되는 특별한 branch
- 특정한 기능을 구현하기 위해 만들어진 mainline의 복사본. 구현과 테스트가 이뤄진 후에 main branch와 머지됨
전체플로우

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
Workflow
- 트리거 이벤트가 발생하면 시작되는 일련의 동작들을 지칭
e.g.)
코드 커밋 (main과 같은 특정 브랜치를 대상으로만 제한 가능)
PR 생성
다른 Workflow의 성공적인 실행
- Workflow를 위한 명령어들은 YAML 파일로 저장
- 명령어들로는 환경설정과 scripts 실행들이 대표적
- Workflow는 Job들로 나눠지며 각 Job은 일련의 스텝을 수행
- 각 스텝은 하나 혹은 그 이상의 명령어를 실행
이 명령어는 actions라고 부르는 명령어들의 집합이 될 수도 있음
- 각 스텝은 윈도우나 리눅스 서버 위에서 runner에 의해 실행
이걸 Docker Image에서 수행하는 것이 서비스 배포 과정에 따라 더 일반적이기도 함