Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 

Repository files navigation

Miky Blog Backend

Django 블로그 백엔드. 기존 SQLite DB(mkblog-db.sqlite3)와 미디어(mkblog-media/)를 그대로 사용합니다.

DB 현재 상태 (로컬 검증)

항목
DB 파일 mkblog-db.sqlite3 (~995KB)
Post 264건
Update_note 140건
IT_Diary 5건
code_review 2건
Users 5명
미디어 mkblog-media/ (295 files)

헬스체크: GET /health/ → DB 경로 + posts 수 반환


AWS Lightsail 512MB 배포 가이드

왜 서버가 멈추는가?

원인 설명
OOM (메모리 부족) 512MB에서 Docker + Nginx + Gunicorn + collectstatic + --build 시 메모리 초과
SQLite WAL 파일 DB 파일만 마운트하면 WAL/SHM 파일이 컨테이너 내부에만 생성되어 재시작 시 DB 손상 위험
서버에서 이미지 빌드 pip compile 시 RAM 급증 → 프로세스 kill

적용한 수정

  1. 프로젝트 디렉터리 전체 마운트 (./:/data/project) → WAL 파일 호스트에 저장
  2. Gunicorn workers=1, threads=2 → SQLite 동시 접근 + 메모리 절약
  3. 메모리 limit web 384MB, nginx 64MB
  4. CI에서 이미지 빌드 → GHCR push → 서버는 pull만 (서버에서 build 안 함)
  5. 1GB Swap (scripts/lightsail-setup.sh)
  6. collectstatic 1회만 (static volume sentinel)
  7. /health/ 엔드포인트로 DB 연결 확인

1단계: Lightsail 서버 초기 설정

# SSH 접속
ssh -i django.pem ubuntu@<LIGHTSAIL_IP>

# 스크립트 실행
bash scripts/lightsail-setup.sh

Lightsail 콘솔 → Networking → HTTP(80), HTTPS(443) 포트 열기


2단계: 프로젝트 + DB 업로드 (최초 1회)

# 로컬 PC에서
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/<USER>/<REPO>.git
git push -u origin main

# DB/미디어 서버 업로드 (Git에 포함하지 않음)
scp -i django.pem mkblog-db.sqlite3 ubuntu@<IP>:/home/ubuntu/Django_Blog/Django_Blog_Back/
scp -i django.pem -r mkblog-media ubuntu@<IP>:/home/ubuntu/Django_Blog/Django_Blog_Back/

서버에서:

cd /home/ubuntu/Django_Blog/Django_Blog_Back
git clone https://github.com/<USER>/<REPO>.git .
cp .env.server.example .env.server
nano .env.server   # SECRET_KEY, ALLOWED_HOSTS, DOCKER_IMAGE 수정

3단계: GitHub Secrets (CI/CD)

Repository → Settings → Secrets → Actions:

Secret 필수
SERVER_HOST Lightsail IP
SERVER_USER ubuntu
SSH_PRIVATE_KEY django.pem 파일 내용 전체
DEPLOY_PATH /home/ubuntu/Django_Blog/Django_Blog_Back
GHCR_TOKEN GitHub PAT (read:packages, write:packages)
SERVER_PORT 22 (기본값) 선택

GHCR_TOKEN 생성: GitHub → Settings → Developer settings → Personal access tokens → read:packages, write:packages 권한

GHCR 패키지 공개 (선택): GitHub → Packages → miky-blog → Package settings → Change visibility → Public


4단계: 배포 실행

# main 브랜치 push → 자동 CD
git push origin main

수동 배포 (서버):

cd /home/ubuntu/Django_Blog/Django_Blog_Back
docker compose -f docker-compose.server.yml up -d
bash scripts/server-check.sh

5단계: 배포 확인

curl http://<LIGHTSAIL_IP>/health/
# {"status": "ok", "database": "/data/project/mkblog-db.sqlite3", "posts": 264}

브라우저: http://<LIGHTSAIL_IP>/ 또는 도메인


로컬 Docker (nginx + web)

cp .env.local.example .env.local
docker compose -f docker-compose.local.yml up --build

브라우저: http://localhost:8000 (nginx → gunicorn)


CI/CD 흐름

push main
  ├─ CI (develop/PR): check → test → docker build
  └─ CD (main):
       1. GitHub Actions에서 Docker 이미지 빌드
       2. ghcr.io/<user>/<repo>/miky-blog:latest push
       3. SSH → Lightsail
       4. docker compose pull (빌드 없음)
       5. docker compose up -d
       6. /health/ 확인

Lightsail 바로 배포 (IP / 도메인 고정)

항목
IP 3.37.248.157
도메인 https://mikysdailylife.com/

0) Lightsail 콘솔

Networking → IPv4 Firewall:

  • SSH 22
  • HTTP 80
  • HTTPS 443

1) 로컬 PC → 서버로 파일 올리기

# 프로젝트 + DB + 미디어 (pem 경로 맞게 수정)
scp -i django.pem -r Django_Blog_Back ubuntu@3.37.248.157:/home/ubuntu/Django_Blog/

또는 서버에서 git clone 후 DB만 업로드:

scp -i django.pem mkblog-db.sqlite3 ubuntu@3.37.248.157:/home/ubuntu/Django_Blog/Django_Blog_Back/
scp -i django.pem -r mkblog-media ubuntu@3.37.248.157:/home/ubuntu/Django_Blog/Django_Blog_Back/

2) SSH 접속 후 실행

ssh -i django.pem ubuntu@3.37.248.157
cd /home/ubuntu/Django_Blog/Django_Blog_Back

# 예전 gunicorn/nginx가 80포트를 쓰고 있으면 중지
sudo systemctl stop gunicorn 2>/dev/null || true
sudo systemctl stop nginx 2>/dev/null || true

# 최초 1회: Swap + Docker + Watchdog
sudo bash scripts/lightsail-setup.sh

# 앱 기동 (env 생성 + docker build + up)
bash scripts/deploy-lightsail.sh

3) 확인

curl http://127.0.0.1/health/
curl http://3.37.248.157/health/
# 브라우저: https://mikysdailylife.com/

설정값 (.env.server.example에 반영됨):

  • ALLOWED_HOSTS=mikysdailylife.com,www.mikysdailylife.com,3.37.248.157,...
  • CSRF_TRUSTED_ORIGINS=https://mikysdailylife.com,https://www.mikysdailylife.com

GitHub Secrets (CI/CD 사용 시)

Secret
SERVER_HOST 3.37.248.157
SERVER_USER ubuntu
SSH_PRIVATE_KEY pem 전체
DEPLOY_PATH /home/ubuntu/Django_Blog/Django_Blog_Back

서버 중단 원인 진단 + 자동 복구

Lightsail 512MB에서 중단은 보통 메모리(OOM) 또는 디스크 full 입니다.

즉시 진단

cd /home/ubuntu/Django_Blog/Django_Blog_Back
bash scripts/diagnose-crash.sh
# 설치 후:
miky-blog-diagnose
결론 의미
memory OOM Killer가 프로세스 kill (가장 흔함)
disk / 파티션 용량 부족 (Docker 로그/이미지)
memory+disk 둘 다 위험

Watchdog (자동 정리 + 재시작)

sudo bash scripts/install-watchdog.sh

2분마다 실행:

  1. 메모리 >= 88% 또는 가용 <= 40MB → cache/docker prune → compose 재시작
  2. 디스크 >= 85% → docker/journal/apt 정리 → compose 재시작
  3. /health/ 실패 → compose 강제 재기동
tail -f /var/log/miky-blog/watchdog.log
systemctl status miky-blog-watchdog.timer
bash scripts/server-check.sh

초기 세팅(Swap + Docker 로그 로테이션 + Watchdog):

sudo bash scripts/lightsail-setup.sh

프로젝트 구조

자세한 아키텍처/디렉터리/요청 흐름은 아래 문서를 참고하세요.

docs/ARCHITECTURE.md

Django_Blog_Back/
├── mkblog-db.sqlite3      # SQLite DB (Git 제외, volume mount)
├── mkblog-media/          # 업로드 파일 (Git 제외)
├── Blog/                  # Django 앱
├── docker/
├── docker-compose.local.yml
├── docker-compose.server.yml
├── docs/
│   └── ARCHITECTURE.md    # 전체 구조 문서
├── scripts/
│   ├── diagnose-crash.sh      # 메모리 vs 디스크 원인 판별
│   ├── watchdog.sh            # 임계치 초과 시 정리+재시작
│   ├── install-watchdog.sh    # systemd timer 설치
│   ├── setup-https.sh         # 호스트 HTTPS → Docker 8080
│   ├── lightsail-setup.sh
│   └── server-check.sh
└── .env.server            # 서버 비밀값 (Git 제외)

About

Minkyeom's Django base blog (2024.08 ~ Now) for hobby

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages