CI/CD에 대해 공부해보자 - 3. Docker&AWS
저번 포스트에서 test를 어떻게 하는지 알아봤으니 이제 배포를 해보겠다. 배포에 필요한 서버는 AWS의 ec2인스턴스를 사용하였다.
처음에 말한 github action을 이용해서 CD를 구현할건데 기본적인 flow는 이렇다 (출처 까먹었다)
github action (.yml에 정의됨)=> 소스코드 image를 build -> dockerhub에 push -> ec2서버에 접속해서 image pull -> pull 한 image로 container run
이런 식으로 굴러가게 된다
다음은 작성한 .yml, dockerfile, nginx.conf파일이다. 아 nginx.conf은 Django의 static이랑 media 파일들을 특정 포트에 serve해주기 위해서 사용했다. 이걸 안하면 templates에 static 파일 안에 js파일들이 적용이 안 된다..
.yml
name: Django Tests
on:
push:
branches:
- main
- test
- depy
pull_request:
branches:
- main
jobs:
test:
runs-on: ubuntu-latesta
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m venv venv
source venv/bin/activate
pip install django
- name: Change directory
run: |
source venv/bin/activate
python -m pip install Pillow
cd SOS
python manage.py makemigrations question
python manage.py migrate
python manage.py test
deploy:
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push Docker image
run: |
cd SOS
docker build -t sos_init .
docker tag sos_init ${{ secrets.DOCKER_USERNAME }}/sos:latest
docker push ${{ secrets.DOCKER_USERNAME }}/sos:latest
- name: Set up SSH
uses: webfactory/ssh-agent@v0.5.3
with:
ssh-private-key: ${{ secrets.EC2_PRIVATE_KEY }}
- name: Deploy to EC2
run: |
ssh -o StrictHostKeyChecking=no ec2-user@***.ap-northeast-2.compute.amazonaws.com << 'EOF'
docker pull ${{ secrets.DOCKER_USERNAME }}/sos:latest
docker stop django_sos || true
docker rm django_sos || true
docker run -d --name django_sos -p 80:80 -e DJANGO_SETTINGS_MODULE=SOS.settings ***/sos:latest
EOF밑에 docker run~부분을 보면 -p 80:80이 있는데 저게 호스트의 80포트를 컨테이너의 80포트와 맵핑시키는 역할이다.
http -> 80포트
https -> 443포트
Dockerfile(requirements.txt안에 필요한 dependencies들이 들어있다)
FROM python:3.11.9
WORKDIR /SOS
COPY . /SOS/.
#Dependencies setting
RUN pip install --no-cache-dir -r requirements.txt
RUN apt-get update && apt-get install -y nginx
ENV DJANGO_SETTINGS_MODULE=SOS.settings
ENV PYTHONUNBUFFERED 1
COPY nginx.conf /etc/nginx/sites-available/default
RUN rm -f /etc/nginx/sites-enabled/default && ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled
RUN python manage.py collectstatic --noinput
CMD service nginx start && \
python manage.py makemigrations question && \
python manage.py migrate && \
python manage.py load_questions && \
gunicorn --bind 0.0.0.0:8000 SOS.wsgi:application
EXPOSE 80필요한 dependency들을 깔아주고, 저 collectstatic은 내가 setting.py에 정의한 경로대로 (지금은 static파일) 정적파일을 자동으로 수집해준다.
밑에 CMD부분은 컨테이너가 실행될 때 자동으로 실행해주는 CLI명령어다. database build와 맨 밑에 gunicorn이 있는데 production할 때는 runserver가 아닌 저 명령어로 실행하는 것이 좋다고 한다 (애초에 runserver은 개발 단계에서 사용하기 위해 만들어졌다고 한다).
가장 밑에는 EXPOSE 80이 있는데 저것이 container의 80포트를 외부에 노출시킨다는 것이다.
nginx.conf
server {
listen 80;
server_name localhost;
location /static/ {
alias /SOS/static/;
}
location /media/ {
alias /SOS/media/;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}nginx가 뭔지 하나도 몰라서 조금 고생했는데(아직도 모름..) 80포트로 들어온 요청 중 url 경로에 media와 static들을 포함한 요청은 파일dir을 맵핑시켜서 처리하고 나머지 요청은 8000포트에서 실행 중인 server에 전달한다는 거 같다.
사실 아직 정리되지 않은 부분이 많은데(event trigger, 도메인 연결..) 마지막 최종 발표 전에 시간이 있으면 정리해야겠다.
정말 배포에 대한 기본지식이 너무 없어서 시간을 꽤나 많이 잡아먹었다. aws는 정말 한번 제대로 공부해봐야겠다. CI/CD 끝!
댓글
로그인 후 댓글을 남길 수 있습니다.
아직 댓글이 없습니다.