LAB: GitLab CI/CD Docker ๋ฐฐํฌ to AWS EC2
Iโm ready to translate the article for you, but Iโll need the full text youโd like translated. Could you please paste the content (excluding the source line you already provided) here? Once I have it, Iโll translate it into Korean while preserving the original formatting, markdown syntax, and technical terms.
๐ฏ Lab Objective
Build a full CI/CD pipeline that:
- Connects GitLab to Mac terminal
- Builds Docker image
- Pushes image to GitLab Registry
- SSH into EC2
- Deploys container
- Handles realโworld production errors
๐๏ธ ์ํคํ ์ฒ
Mac Terminal
โ
GitLab Repo
โ
GitLab CI/CD Pipeline
โ
Docker Image Build
โ
Push to GitLab Container Registry
โ
SSH to AWS EC2
โ
Docker Pull & Run
โ
Application Live on Port 80
๐น ๋จ๊ณ
STEPโฏ1 โ GitLab Pages ๊ธฐ๋ณธ ํ์ดํ๋ผ์ธ
.gitlab-ci.yml
image: busybox
pages:
stage: deploy
script:
- echo "The site will be deployed"
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
ํ์ดํ๋ผ์ธ ํธ๋ฆฌ๊ฑฐ:
git commit --allow-empty -m "Trigger pipeline"
git push origin master
STEPโฏ2 โ Docker ๋น๋ ๋จ๊ณ ์ถ๊ฐ
Dockerfile ์์ฑ (ํ๋ก์ ํธ ๋ฃจํธ):
FROM nginx:alpine
COPY public /usr/share/nginx/html
EXPOSE 80
.gitlab-ci.yml ์
๋ฐ์ดํธ:
stages:
- build
- push
- deploy
variables:
IMAGE_NAME: registry.gitlab.com/$CI_PROJECT_PATH:latest
build_image:
stage: build
image: docker:24
services:
- docker:24-dind
script:
- docker build -t $IMAGE_NAME .
STEPโฏ5 โ GitLab ์ปจํ ์ด๋ ๋ ์ง์คํธ๋ฆฌ๋ก ํธ์
ํธ์ ์์ ์ถ๊ฐ:
push_image:
stage: push
image: docker:24
services:
- docker:24-dind
script:
- echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
- docker push $IMAGE_NAME
๐ด ์ค๋ฅ ๋ฐ ํด๊ฒฐ์ฑ
์ค๋ฅ #1 โ ์ด๋ฏธ์ง ์ฐพ์ ์ ์์
์ค๋ฅ
An image does not exist locally with the tag
ํด๊ฒฐ ๋ฐฉ๋ฒ
build ๋จ๊ณ์ push ๋จ๊ณ์์ ๋์ผํ $IMAGE_NAME์ ์ฌ์ฉํ๋๋ก ํฉ๋๋ค.
STEPโฏ6 โ AWS EC2์ ๋ฐฐํฌ
Deploy ์์ :
deploy_ec2:
stage: deploy
image: alpine
before_script:
- apk add --no-cache openssh
script:
- echo "$EC2_KEY" > key.pem
- chmod 600 key.pem
- ssh -o StrictHostKeyChecking=no -i key.pem ubuntu@$EC2_HOST "
docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY &&
docker pull $IMAGE_NAME &&
docker stop web || true &&
docker rm web || true &&
docker run -d -p 80:80 --name web $IMAGE_NAME
"
์ค๋ฅ #2 โ SSH ํธ์คํธ ์ด๋ฆ์ ํ์ธํ ์ ์์
์์ธ
CI/CD ๋ณ์๋ค์ด ์ค์ ๋์ง ์์.
ํด๊ฒฐ ๋ฐฉ๋ฒ
Settings โ CI/CD โ Variables ์์ ๋ค์ ๋ณ์๋ฅผ ์ถ๊ฐํฉ๋๋ค (๋ณดํธ๋์ง ์์ผ๋ฉฐ, ํ์ ๊ฐ๋ฅ):
| ํค (Key) | ๊ฐ (Value) |
|---|---|
EC2_HOST | EC2 ํผ๋ธ๋ฆญ IP ์ฃผ์ |
EC2_KEY | .pem ํ์ผ ์ ์ฒด ๋ด์ฉ |
์ค๋ฅ #3 โ ํฌํธโฏ80 ์ด๋ฏธ ์ฌ์ฉ ์ค
ํ์ดํ๋ผ์ธ ์ค๋ฅ
failed to bind host port 80
address already in use
์กฐ์ฌ ๋ฐฉ๋ฒ
ssh -i key.pem ubuntu@$EC2_HOST
sudo lsof -i :80
๊ฒฐ๊ณผ์ nginx ๊ฐ ํฌํธโฏ80์ ์ฌ์ฉ ์ค์ธ ๊ฒ์ด ํ์๋ฉ๋๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ
sudo systemctl stop nginx
sudo systemctl disable nginx
ํ์ดํ๋ผ์ธ์ ๋ค์ ์คํ โ ์ฑ๊ณต.
๐น ์ต์ข ๊ฒฐ๊ณผ
์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๊ทผํ ์ ์์ต๋๋ค:
http://
๐ง ์ค์ DevOps ๋ฌธ์ ํด๊ฒฐ ๊ตํ
| ๋ฌธ์ | ์ฌ์ฉ ๋๊ตฌ |
|---|---|
| SSH ๊ฑฐ๋ถ | ssh-add |
| ํ์ดํ๋ผ์ธ ๋ณ์ ๋๋ฝ | GitLab CI/CD variables |
| Docker ํ๊ทธ ๋ถ์ผ์น | Inspect $IMAGE_NAME |
| SSH ํธ์คํธ๋ช ์ค๋ฅ | Verify variables |
| ํฌํธ ์ถฉ๋ | lsof -i :80 |
| Nginx ์ถฉ๋ | systemctl stop |
์ด๋ ์ผ๋ฐ์ ์ธ ํ๋ก๋์ ์์ค ๋๋ฒ๊น ๋จ๊ณ์ ๋๋ค.
๐ ์ธํฐ๋ทฐ ์ค๋ช ๋ฒ์
๋ฉด์ ๊ด์ด โGitLab CI/CD๋ฅผ ์ฌ์ฉํด EC2์ ๋ฐฐํฌํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ๋์?โ ๋ผ๊ณ ๋ฌผ์ผ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ตํ ์ ์์ต๋๋ค:
- ์ ํ๋ฆฌ์ผ์ด์
์ฉ
Dockerfile์ ์์ฑํฉ๋๋ค. - ๋ฉํฐโ์คํ
์ด์ง
.gitlab-ci.ymlํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํฉ๋๋ค (๋น๋, ํธ์, ๋ฐฐํฌ). - Docker ์ด๋ฏธ์ง๋ฅผ ๋น๋ํ๊ณ GitLab Container Registry์ ํธ์ํฉ๋๋ค.
- EC2 SSH ๊ฐ์ธ ํค์ ํธ์คํธ IP๋ฅผ CI/CD ๋ณ์๋ก ์ ์ฅํฉ๋๋ค.
- deploy ๋จ๊ณ์์ EC2 ์ธ์คํด์ค์ SSH๋ก ์ ์ํ๊ณ , ๋ ์ง์คํธ๋ฆฌ์ ๋ก๊ทธ์ธํ ๋ค ์ด๋ฏธ์ง๋ฅผ ํ(pull)ํฉ๋๋ค. ๊ธฐ์กด ์ปจํ ์ด๋๋ฅผ ์ค์งยท์ญ์ ํ๊ณ , ์ ์ปจํ ์ด๋๋ฅผ ํฌํธโฏ80์์ ์คํํฉ๋๋ค.
- ์ผ๋ฐ์ ์ธ ๋ฌธ์ (๋ณ์ ๋๋ฝ, ํฌํธ ์ถฉ๋, ๊ธฐ์กด ์๋น์ค ๋ฑ)๋ฅผ ์ฒ๋ฆฌํ์ฌ **๋ฉฑ๋ฑ(idempotent)**ํ๊ณ ํ๋ก๋์ ์ ์ ํฉํ ๋ฐฐํฌ๋ฅผ ๋ณด์ฅํฉ๋๋ค.