Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.production
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
DJANGO_DEBUG=False
DJANGO_ALLOWED_HOSTS='api.misiklog.com www.api.misiklog.com'
DJANGO_ALLOWED_HOSTS='api.misiklog.com www.api.misiklog.com localhost'
DJANGO_BASE_URL='https://api.misiklog.com/'

DJANGO_CSRF_TRUSTED_ORIGINS='https://api.misiklog.com'
Expand Down
41 changes: 41 additions & 0 deletions .github/workflows/build-and-push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Build and Push to ECR

on:
workflow_dispatch:
push:
branches: [release]

jobs:
build-and-push:
runs-on: ubuntu-latest

steps:
# https://github.com/actions/checkout
- name: Checkout the code
uses: actions/checkout@v4
with:
submodules: true
token: ${{ secrets.PAT_TOKEN }}

# https://github.com/aws-actions/configure-aws-credentials
# TODO: apply 'Assume Role directly using GitHub OIDC provider' method
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ vars.AWS_REGION }}

# https://github.com/aws-actions/amazon-ecr-login
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2

- name: Build, tag, and push docker image to Amazon ECR
env:
REGISTRY: ${{ steps.login-ecr.outputs.registry }}
REPOSITORY: ${{ secrets.ECR_REPOSITORY }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG .
docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG
105 changes: 105 additions & 0 deletions .github/workflows/cd-prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
name: Build, Push to ECR, and Deploy

on:
push:
branches: [release]
workflow_dispatch:

jobs:
build-and-push:
runs-on: ubuntu-latest

outputs:
REGISTRY: ${{ steps.login-ecr.outputs.registry }}

steps:
- name: Checkout the code
uses: actions/checkout@v4
with:
submodules: true
token: ${{ secrets.PAT_TOKEN }}

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ vars.AWS_REGION }}

# ECR 로그인
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2

# Docker 이미지 빌드 및 푸시
- name: Build, tag, and push docker image to Amazon ECR
env:
REGISTRY: ${{ steps.login-ecr.outputs.registry }}
REPOSITORY: ${{ secrets.ECR_REPOSITORY }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG .
docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG

deploy:
runs-on: ubuntu-latest
needs: build-and-push

steps:
- name: Checkout the code
uses: actions/checkout@v4
with:
submodules: true
token: ${{ secrets.PAT_TOKEN }}

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ vars.AWS_REGION }}

# 필요한 파일을 서버로 전송
- name: Copy files to server
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
port: ${{ secrets.EC2_SSH_PORT }}
source: "./deploy/"
target: /home/${{ secrets.EC2_USER }}/

- name: Create .env on server
uses: appleboy/ssh-action@v0.1.5
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
port: ${{ secrets.EC2_SSH_PORT }}
script: |
echo "REGISTRY=${{ secrets.ECR_REGISTRY }}" > /home/${{ secrets.EC2_USER }}/deploy/.env
echo "REPOSITORY=${{ secrets.ECR_REPOSITORY }}" >> /home/${{ secrets.EC2_USER }}/deploy/.env
echo "AWS_REGION=${{ vars.AWS_REGION }}" >> /home/${{ secrets.EC2_USER }}/deploy/.env
echo "IMAGE_TAG=${{ github.sha }}" >> /home/${{ secrets.EC2_USER }}/deploy/.env
echo "AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }}" >> /home/${{ secrets.EC2_USER }}/deploy/.env
echo "AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}" >> /home/${{ secrets.EC2_USER }}/deploy/.env

# 배포 실행
- name: Deploy via SSH
uses: appleboy/ssh-action@v0.1.5
env:
REGISTRY: ${{ needs.build-and-push.outputs.REGISTRY }}
REPOSITORY: ${{ secrets.ECR_REPOSITORY }}
AWS_REGION: ${{ vars.AWS_REGION }}
IMAGE_TAG: ${{ github.sha }}
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
port: ${{ secrets.EC2_SSH_PORT }}
envs: REGISTRY, REPOSITORY, AWS_REGION, IMAGE_TAG
script: |
cd /home/${{ secrets.EC2_USER }}/deploy
chmod +x deploy.sh
./deploy.sh
41 changes: 0 additions & 41 deletions .github/workflows/deploy.yml

This file was deleted.

33 changes: 24 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
FROM python:3.11
ENV PYTHONUNBUFFERED 1
WORKDIR /
FROM python:3.11-slim

COPY requirements.txt ./
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
# 파이썬 출력의 버퍼링을 없애기 위한 환경변수
ENV PYTHONUNBUFFERED=1

# System dependencies 설치
RUN apt-get update && apt-get install -y \
build-essential \
libpq-dev \
--no-install-recommends && \
rm -rf /var/lib/apt/lists/*

WORKDIR /app

ENV PYTHONPATH=/app/src

COPY requirements.txt /app/

# 패키지 설치(캐시를 저장하지 않도록 지정)
RUN pip install --no-cache-dir -r requirements.txt

ENV MISIKLOG_ENV=production

COPY src/ .
COPY . .
RUN python manage.py collectstatic --noinput

# Static files 수집
RUN python src/manage.py collectstatic --noinput

EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "config.wsgi:application"]

CMD ["gunicorn", "src.config.wsgi:application", "--bind", "0.0.0.0:8000"]
66 changes: 66 additions & 0 deletions deploy/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/bin/bash

set -e

# 환경 변수 로드
source .env

export AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY

# AWS ECR 로그인
aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $REGISTRY

# IMAGE_TAG는 GitHub Actions에서 전달된 값을 사용
IMAGE_TAG=${IMAGE_TAG}

# 현재 활성화된 버전 확인
if [ -f active_version ]; then
CURRENT_VERSION=$(cat active_version)
else
CURRENT_VERSION="green" # 초기 배포 시 기본값
fi

# 다음 배포할 버전 결정
if [ "$CURRENT_VERSION" = "blue" ]; then
NEW_VERSION="green"
ACTIVE_PORT=8002
else
NEW_VERSION="blue"
ACTIVE_PORT=8001
fi

# Docker Compose 환경 변수 설정
export REGISTRY
export REPOSITORY
export IMAGE_TAG

# 새로운 이미지 풀
docker pull $REGISTRY/$REPOSITORY:$IMAGE_TAG

# 새로운 서비스 시작
docker compose up -d app_${NEW_VERSION}

# 헬스 체크 대기
echo "새로운 버전의 컨테이너 헬스 체크 중..."
sleep 10

# 헬스 체크 수행
if ! curl -f http://localhost:${ACTIVE_PORT}/v1/health; then
echo "새로운 컨테이너가 헬스 체크에 실패했습니다. 롤백합니다."
docker compose stop app_${NEW_VERSION}
exit 1
fi

# Nginx 설정 업데이트
sed "s/\${ACTIVE_UPSTREAM}/app_${NEW_VERSION}/g" nginx.conf.template > nginx.conf
sudo cp nginx.conf /etc/nginx/conf.d/default.conf
sudo systemctl reload nginx

# 이전 서비스 중지
docker compose stop app_${CURRENT_VERSION}

# 활성화된 버전 업데이트
echo "${NEW_VERSION}" > active_version

echo "${NEW_VERSION} 버전으로 배포 완료."
26 changes: 26 additions & 0 deletions deploy/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: '3.8'

services:
app_blue:
image: ${REGISTRY}/${REPOSITORY}:${IMAGE_TAG}
container_name: app_blue
environment:
- MISIKLOG_ENV=production
ports:
- "8001:8000"
depends_on:
- redis

app_green:
image: ${REGISTRY}/${REPOSITORY}:${IMAGE_TAG}
container_name: app_green
environment:
- MISIKLOG_ENV=production
ports:
- "8002:8000"
depends_on:
- redis

redis:
image: "redis:alpine"
container_name: redis
2 changes: 1 addition & 1 deletion nginx/nginx.conf → deploy/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ server {
}

location /static {
alias /static/;
alias /app/static/;
}
}
44 changes: 44 additions & 0 deletions deploy/nginx.conf.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
upstream app_blue {
server 127.0.0.1:8001;
}

upstream app_green {
server 127.0.0.1:8002;
}

server {
listen 80;
server_name api.misiklog.com;

if ($host !~* ^(api.misiklog.com)$) {
return 444;
}

location / {
return 301 https://$host$request_uri;
}
}

server {
listen 443 ssl;
server_name api.misiklog.com;

ssl_certificate /etc/letsencrypt/live/api.misiklog.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.misiklog.com/privkey.pem;

if ($host !~* ^(api.misiklog.com)$) {
return 444;
}

location / {
proxy_pass http://${ACTIVE_UPSTREAM};
proxy_set_header Host $host:$server_port;
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;
}

location /static/ {
alias /home/ubuntu/static/;
}
}
Loading
Loading