목차
1. GitLab 프로젝트 생성
GitLab은 설치형과 인터넷 서비스형이 있는데, 이 실습에서는 인터넷 서비스형을 사용한다.
Get free trial
그룹 생성 후 프로젝트 생성
Plan > Issue boards
칸반 보드
티켓을 할당하고 티켓을 처리하는 과정을 모니터링하여 전체 업무를 관리하는 기능.
open → 작업 → Review or QA → closed
Build > Pipelines
현재 프로젝트가 CI/CD의 어느 단계에 있는지, 어느 상태에 있는지를 모니터링할 수 있는 기능.
Build > Pipeline editor
파이프라인을 설계하는 기능.
Build, Test, Deploy 등의 과정을 설계한다. (회사, 업무 마다 다름)
2. SSH Key 설정하기
프로젝트를 Private로 생성했기 때문에 “Clone with SSH”를 하려면 SSH Key가 있어야 한다.
터미널을 실행한다.
`ssh-keygen` 명령어로 SSH Key를 만들 수 있다.
ssh-keygen -t rsa
- `-t rsa`: 타입은 rsa
위의 출력된 디렉토리에서 확인할 수 있다.
private key와 public key가 생성되었다.
공개 키를 프로젝트에 등록하면 된다.
cat id_rsa.pub
key를 복사하여 “Add SSH Key”로 들어간다.
Add SSH Key > Add new key
이 계정에서 GitLab에 CLone을 하게 되면 권한을 확인해야 한다. 권한을 Private Key를 통해 확인하고 Clone이나 여러가지 Git 작업을 수행할 수 있는 권한을 획득하게 된다.
3. 개발 환경 세팅하기
“flask-app” 프로젝트를 Clone한다.
“Clone with SSH”를 복사한다.
터미널에서 /home/workspace에 Clone 한다.
git clone {git URL}
vi test.txt
테스트 파일을 추가한 후,
git status
git add test.txt
git commit -m "example code"
git push
Git 저장소가 성공적으로 세팅되었다.
4. 프로젝트 코드 작업
GitLab > Groups > New groupn > Create group
TeamJoinc > New project > Creat blank project
터미널 실행 > workspace 디렉터리로 이동
git clone {git URL}
test-app 디렉터리로 이동
`code .` 를 통해 vs code 사용
app.py
from flask import Flask
app = Flask(__name__)
@app.route('/') # Route URL 호출
def home():
return 'Hello, Flask World!'
if __name__ == '__main__':
app.run(debug=True)
requirements.txt
flask
의존성 설치
pip install -r requirements.txt
오류 발생
Ubuntu에서는 시스템 Python 환경을 보호하기 위해 `pip install` 을 막고 있으며, 공식적으로 가상환경을 만들어서 패키지를 설치하는 방법을 권장한다.
sudo apt install python3.12-venv
python3 -m venv venv // 가상환경 생성
source venv/bin/activate // 가상환경 활성화
pip install -r requirements.txt
작업 마친 후, 가상환경 비활성화
deactivate
실행
python3 app.py
http://127.0.0.1:5000 로 실행된 것을 확인할 수 있다.
웹 브라우저로 접속해보면,
Flask 애플리케이션 개발까지 완료되었다.
5. Docker Image 만들기
Dockerfile 생성
FROM python:3.9-slim
WORKDIR /opt/app
COPY . /opt/app
RUN pip install -r requirements.txt
CMD ["python3", "app.py"]
- `FROM`: 어떤 이미지를 바탕으로 만들지. (Base Image)
- `WORKDIR`: 컨테이너가 실행되고 나서 작업 디렉터리
- `COPY`: 현재 모든 파일을 WORKDIR로 복사
- `RUN`: 컨테이너 안에서 해당 명령을 실행
- `CMD`: 컨테이너가 실행되었을 때 실행할 명령어
app.py
from flask import Flask
app = Flask(__name__)
@app.route('/') # Route URL 호출
def home():
return 'Hello, Flask World!'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
- `host='0.0.0.0'`: 외부에서 작동하도록 설정
Docker Image 빌드
docker build -t teamjoinc/test-app:0.1 .
- `docker build`: Docker 이미지를 생성하는 명령어.
- `-t teamjoinc/test-app:0.1`
- t 옵션은 태그(tag) 지정을 의미.
- teamjoinc/test-app → 이미지 이름
- 0.1 → 이미지 버전(tag)
- 따라서, teamjoinc/test-app이라는 이름으로 0.1 버전의 이미지를 생성.
- `.` (현재 디렉토리)
- Dockerfile이 위치한 현재 디렉토리에서 이미지를 빌드함.
- 즉, .는 Dockerfile과 필요한 파일들이 있는 위치를 나타냄.
⇒ 현재 디렉토리(.)에 있는 Dockerfile을 기반으로 Docker 이미지를 빌드하는 명령어
ubuntu@ubuntu-VirtualBox:~/workspace/test-app$ docker build -t teamjoinc/test-app:0.1 .
[+] Building 5.9s (9/9) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 152B 0.0s
=> [internal] load metadata for docker.io/library/python:3.9-slim 1.5s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/4] FROM docker.io/library/python:3.9-slim@sha256:bb8009c87ab69e751a1dd2c6c7f8abaae3d9fce8e072802d4a23c95594d16d84 0.0s
=> [internal] load build context 0.1s
=> => transferring context: 143.56kB 0.1s
=> CACHED [2/4] WORKDIR /opt/app 0.0s
=> [3/4] COPY . /opt/app 0.2s
=> [4/4] RUN pip install -r requirements.txt 3.5s
=> exporting to image 0.3s
=> => exporting layers 0.3s
=> => writing image sha256:5db84badb501abd8551cf8effcd0999a012fbb2ac015ac6f30889ded626fc977 0.0s
=> => naming to docker.io/teamjoinc/test-app:0.1
Docker Image 확인
docker images
컨테이너 만들기
docker run --name test-app -p 5000:5000 teamjoinc/test-app:0.1
- `docker run`: 새 컨테이너를 생성하고 실행
- `--name test-app`: 컨테이너의 이름을 test-app으로 지정
- `-p 5000:5000`: 호스트의 5000번 포트를 컨테이너의 5000번 포트에 매핑
- `teamjoinc/test-app:0.1`: 실행할 Docker 이미지 이름과 태그(버전)
확인하는 방법
curl localhost:5000
Docker Image 만들기 완료.
현재 상태
1단계까지 완료했다.
6. Docker Image를 ECR에 push하기
AWS > Elastic Container Registry > 리포지토리 생성 > 생성
접근 권한 설정
푸시 명령을 수행하기 전에 ECR에 대한 접근 권한 설정이 필요하다.
AWS Cloud에서는 IAM이라는 서비스를 이용해 권한을 관리할 수 있다.
IAM을 이용해 Access Key와 Secret Key를 발급하고, 이 키를 가지고 있는 사용자만 ECR에 접근할 수 있도록 설정한다.
IAM > 사용자 > 사용자 생성
모든 권한을 가지는 admin 권한을 선택한다.
다음은 Secret Key를 만든다.
ecr-user > 보안 자격 증명> 액세스 키 > 액세스 키 만들기
터미널을 사용하기 때문에 CLI 선택
“.csv 파일 다운로드”하여 키를 받는다.
파일을 열어보면 Access Key와 Secret Key 두 개로 이루어져 있다. 이 키를 사용하여 접근 권한을 설정한다.
먼저 AWS CLI를 설치한다.
참고: https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-install.html
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
설치 완료
`aws configure` → Access Key 입력 → Secret Key 입력 → Region(서울) 입력 → 출력 포멧(JSON) 입력
키 설정 완료
확인 명령어 (/home 에서)
cd .aws/
cat config
cat credeintials
사용자는 credeintial을 여러 개 가질 수 있다.
예시) `vi credeintials`
[default]
aws_access_key_id = {aws_access_key_id}
aws_secret_access_key = {aws_secret_access_key}
[devops]
aws_access_key_id = XXXXXXXXX
aws_secret_access_key = YYYYYYYYYYYY
프로파일 이름(예시: devops)을 지정하여 작업을 수행할 수 있다.
푸시 명령 실행
1. AWS ECR 로그인
Elastic Container Registry > 리포지토리 > 푸시 명령 보기
> 1. AWS CLI 사용
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 277707140590.dkr.ecr.ap-northeast-2.amazonaws.com
AWS ECR 로그인 명령어이다.
- `aws ecr get-login-password --region ap-northeast-2`: AWS ECR에서 로그인 비밀번호를 가져옴
- `docker login --username AWS --password-stdin <ECR_URL>`: AWS ECR 레지스트리에 Docker 로그인
권한이 있기 때문에 로그인 성공.
> 푸시 명령 보기 > 2. 이미지 빌드
이미 이미지 빌드는 위에서 수행했기 때문에 넘어간다.
2. 이미지에 태그를 지정
푸시 명령 보기 > 3. 이미지에 태그를 지정
docker tag teamjoinc/test-app:0.1 277707140590.dkr.ecr.ap-northeast-2.amazonaws.com/teamjoinc/test-app:0.1
기본 명령어에서 태그만 lastest → 0.1 로 변경했다.
3. 푸시
> 푸시 명령 보기 > 4. AWS 리포지토리로 푸시
docker push 277707140590.dkr.ecr.ap-northeast-2.amazonaws.com/teamjoinc/test-app:0.1
기본 명령어에서 태그만 lastest → 0.1 로 변경했다.
푸시 완료.
ECR에 잘 들어가 있는지 확인한다.
ECR > 리포지토리
0.1 버전이 잘 들어가 있는 것을 확인할 수 있다.
테스트
실제 저장소에 있는 이미지를 가지고 와서 컨테이너를 실행할 수 있는지 테스트한다.
먼저 기존의 image를 강제로 지워준다.
docker rmi {IMAGE_ID} -f
이미지 URL을 복사한다.
docker run --name ecr-test -p 5000:5000 277707140590.dkr.ecr.ap-northeast-2.amazonaws.com/teamjoinc/test-app:0.1
잘 작동하는 것을 확인했다.
프로세스 확인
docker ps
ECR에 Image를 Push하고, Image를 Pull해서 실행하는 것까지 완료했다.
이제 자동화 단계로 넘어간다.
7. GitLab을 이용한 Build Push 자동화
GitLab이 사람이 하는 일을 코드로 자동화한다.
build, log,tagging, push 작업들을 GitLab이 스크립트로 관리하고, 스트립트를 실행하여 전 과정을 자동화한다.
GitLab Runner 설치
https://docs.gitlab.com/runner/install/linux-manually.html
패키지를 직접 다운로드하면 된다.
# Replace ${arch} with any of the supported architectures, e.g. amd64, arm, arm64
# A full list of architectures can be found here https://s3.dualstack.us-east-1.amazonaws.com/gitlab-runner-downloads/latest/index.html
curl -LJO "https://s3.dualstack.us-east-1.amazonaws.com/gitlab-runner-downloads/latest/deb/gitlab-runner-helper-images.deb"
curl -LJO "https://s3.dualstack.us-east-1.amazonaws.com/gitlab-runner-downloads/latest/deb/gitlab-runner_${arch}.deb"
Architecture은 직접 입력해줘야 함. `amd64` 로 입력.
의존 패키지 먼저 설치한다.
sudo dpkg -i gitlab-runner-helper-images.deb
다음으로 gitlab-runner 설치한다.
sudo dpkg -i gitlab-runner_amd64.deb
그리고 ps 명령어로 확인해보면
GitLab Runner가 실행 중인 것을 확인할 수 있다.
이제 GitLab CI에서 GitLab Runner를 등록시켜 주면 된다.
GitLab Runner 등록
GitLab > Project > Settings > CI/CD > Runner
> Project runners > New project runner
GitLab Runner는 GitLab CI에서 발급한 token을 가지로 등록 요청을 하게 된다. GitLab CI는 자신이 발급한 token인지 확인하여 GitLab Runner가 프로젝트에 접근할 수 있는 권한을 준다.
이후 GitLab은 주기적으로 변동 사항을 확인하여 코드를 읽어와서 CI/CD 작업을 수행한다.
Step1의 명렁어를 GitLab이 설치면 호스트에 실행해주면 된다.
ubuntu@ubuntu-VirtualBox:~$ gitlab-runner register --url https://gitlab.com --token glrt-t3_NxNLh1KSFd2zr4Fi9sV1
Runtime platform arch=amd64 os=linux pid=4873 revision=690ce25c version=17.8.3
WARNING: Running in user-mode.
WARNING: The user-mode requires you to manually start builds processing:
WARNING: $ gitlab-runner run
WARNING: Use sudo for system-mode:
WARNING: $ sudo gitlab-runner...
Enter the GitLab instance URL (for example, https://gitlab.com/):
[https://gitlab.com]:
Verifying runner... is valid runner=t3_NxNLh1
Enter a name for the runner. This is stored only in the local config.toml file:
[ubuntu-VirtualBox]: test-app
Enter an executor: custom, shell, parallels, kubernetes, docker-autoscaler, ssh, virtualbox, docker, docker-windows, docker+machine, instance:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
Configuration (with the authentication token) was saved in "/home/ubuntu/.gitlab-runner/config.toml"
- GitLab 서버 URL을 입력하라고 요청: [https://gitlab.com]은 기본값(Default), 그냥 Enter를 누르면 그대로 적용된다.
- Runner의 이름을 지정: test-app으로 입력. (이 이름은 로컬 파일에만 저장되고, GitLab에는 저장되지 않는다.)
- Runner가 빌드를 실행할 방식(Executor) 선택: shell 입력 (Runner가 빌드를 로컬 셸 환경에서 실행하도록 설정)
만들어진 설정파일로 이동.
cd .gitlab-runner/
vi config.toml
name, url, token 등이 모두 설정된 것을 확인할 수 있다.
GitLab Ci는 token 값이 일치하면 등록된 runner라는 것을 인증하고 실행할 수 있도록 권한을 준다.
GitLabl Runner 실행
gitlab-runner run
"View runners"로 이동.
프로젝트를 위한 runner가 활성화된 것을 확인할 수 있다.
Instance runner는 비활성화 시켜준다.
GitLab Runner 자동 실행 설정
systemctl 설정을 변경한다.
cd /etc/systemd/system
vi gitlab-runner.service
config와 working-directory, user를 변경했다.
cd ~
ls -al .bash_logout
vi .bash_logout
가장 밑의 3줄 주석 처리.
서비스 재시작.
systemctl daemon-reload
sudo systemctl restart gitlab-runner
부팅할 때 매번 자동으로 실행하도록 해야한다.
sudo systemctl enable gitlab-runner
8. GitLab PIPLINE 구성
project > Build > Pipline editor > Configure pipline
main 브랜치에 commit
예시
doc-job:
stage: build
script:
- echo "Create API document..."
- echo "Create complete."
위처럼 job을 추가하거나, stage를 추가하여 사용할 수 있다.
"Visualize" 탭에서도 확인할 수 있다.
> Piplines
실패하는 예시도 확인한다.
unit-test-job: # This job runs in the test stage.
stage: test # It only starts when the job in the build stage completes successfully.
script:
- echo "Running unit tests... This will take about 60 seconds."
- sleep 20
- exit 1
`exit`에서 0이 아닌 값은 실패했다고 출력된다.
특정 stage에서 실패하면 다음 stage로 넘어가지 않는다.
> project
yml 파일이 main 브랜치에 들어가 있는 것을 확인할 수 있다.
9. Makefile 푸시 및 GitLab CI/CD 실행
Makefile 빌드 및 푸시
`git pull`을 통해 GitLab CI에서 작업했던 내용을 가져온다.
`vi Makefile`로 Makefile을 추가한다.
PRJ_NAME=YOUR_PROJECT_NAME
ECR_URI=YOUR_ECR_URL
VERSION:=$(shell git rev-parse --short HEAD)
build:
docker build -t $(PRJ_NAME):$(VERSION) .
push:
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin $(ECR_URI)
docker tag $(PRJ_NAME):$(VERSION) $(ECR_URI)/$(PRJ_NAME):$(VERSION)
docker tag $(PRJ_NAME):$(VERSION) $(ECR_URI)/$(PRJ_NAME):latest
docker push $(ECR_URI)/$(PRJ_NAME):$(VERSION)
docker push $(ECR_URI)/$(PRJ_NAME):latest
- `git rev-parse --short HEAD`: 현재 버전에 대한 hash 값을 출력한다. 이 값을 이용해 버전을 설정할 수 있다. 결과적으로 build 명령이 `docker build -t teamjoinc/test-app: {버전값}`이 된다.
다음으로 `make build`를 하게 되면, 변수가 치환되어 이미지가 만들어 지는 것을 확인할 수 있다.
`docker images`를 통해 확인할 수 있다.
`make push`
login, tag, push 까지 자동으로 실행된다.
ECR에서 잘 푸시되었는지 확인한다.
ECR > 리포지토리
Make Script를 GitLab에서 호출
GitLab > project > Build > Pipline editor
실제 작동하는 스크립트를 작성한다.
stages: # List of stages for jobs, and their order of execution
- build
- test
- deploy
build-job: # This job runs in the build stage, which runs first.
stage: build
script:
- echo "Docker build start"
- make build
- echo "Docker build complete."
push-job: # This job runs in the build stage, which runs first.
stage: build
script:
- echo "Docker push start"
- make push
- echo "Docker push complete."
unit-test-job: # This job runs in the test stage.
stage: test # It only starts when the job in the build stage completes successfully.
script:
- echo "Running unit tests."
- sleep 5
- echo "Unit tests complete."
lint-test-job: # This job also runs in the test stage.
stage: test # It can run at the same time as unit-test-job (in parallel).
script:
- echo "Linting code... This will take about 10 seconds."
- sleep 5
- echo "No lint issues found."
deploy-job: # This job runs in the deploy stage.
stage: deploy # It only runs when *both* jobs in the test stage complete successfully.
environment: production
script:
- echo "Deploying application..."
- echo "Application successfully deployed."
- build는 두 개의 job을 가진다.
- `build-job`: 이미지를 build 하는 작업을 수행한다.
- `push-job`: build된 이미지를 push 하는 작업을 수행한다.
- test는 두 개의 job을 가진다.
- 현재는 test 작업을 하기 않기 때문에 echo만 사용한다.
- deploy는 다음에서 다룬다.
현재는 Makefile과 코드들을 올리지 않았기 때문에 실패한다.
코드들을 올린다.
git pull
git add .
git commit -m "my source code"
git push
GitLab > project > Build > Pipelines
3개의 stage가 잘 돌아가는 것을 확인할 수 있다.
'Study > Docker' 카테고리의 다른 글
[Docker_CI/CD_스터디] 3. GitLab으로 AWS Cloud로의 지속적인 배포 (0) | 2025.02.04 |
---|---|
[Docker_CI/CD_스터디] 1. AWS EC2 인스턴스 생성 및 Docker 설치 (0) | 2025.01.26 |
댓글