[CI/CD] 1단계: 도커로 깡통 장고 띄워 배포하기

Saemi An·2025년 4월 26일

🧚🏻 목표

우분투가 깔린 노트북에서 도커 컨테이너를 통해 초기화 상태의 장고를 띄우고 브라우저를 통해 외부접속을 가능하게 한다.

  • 조건 1: DB / Django + Gunicorn / Nginx 각각 컨테이너를 띄운다. (총 3개의 컨테이너)
  • 조건 2: Docker-Compose를 사용하지 않는다.

1️⃣ Step1: 도커 네트워크 생성

docker network create mynetwork

컨테이너간 통신을 위해 도커 네트워크를 설정해 준다.
생성된 'mynetwork'를 통해 컨테이너의 이름 + 포트로 통신이 이루어진다.

+) 도커 네트워크 개념 상세 공부 필요, 참고자료

2️⃣ Step2: 데이터베이스 컨테이너 실행

docker run -d \
  --name mypostgres \
  --network mynetwork \
  -e POSTGRES_DB=[데이터베이스 이름] \
  -e POSTGRES_USER=[데이터베이스 사용자 이름] \
  -e POSTGRES_PASSWORD=[데이터베이스 비밀번호] \
  postgres:16

-d 데몬 옵션으로
mynetwork로 네트워크를 설정하여
postgres:16 이미지를 실행시킨다.
--name mypostgres는 앞으로 장고가 DB에 접근시(내부 접속) 사용하는 호스트의 이름이다.
-e는 명령 실행 시에 사용자의 환경을 구성하는 환경변수 옵션이다.

3️⃣ Step3: 장고 이미지 빌드

A) (배포용) settings.py 수정

  • (선택사항) 배포용 / 개발용 세팅 파일을 분리시켜 준다 (참고자료)
  • SECRET_KEY, DATABASE 정보는 환경변수로 대체 (편의를 위해 아래 코드에서 DATABASE는 하드코딩해 넣음)
  • DEBUG = False
  • ALLOWED_HOSTS에는 구매한 도메인명만 추가
  • (선택사항) TIME_ZONE = 'Asia/Seoul', USE_TZ = False (타임존 설정 참고자료)

B) Dockerfile 작성
장고 앱 디렉토리가 있는 위치에 Dockerfile을 작성해준다.

# 베이스 이미지
FROM python:3.12-slim

# 환경 변수 설정
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

# 작업 디렉토리 생성
WORKDIR /app

# 필요 패키지 설치
RUN apt-get update && apt-get install -y \
    build-essential \
    libpq-dev \
    netcat-openbsd \
    && rm -rf /var/lib/apt/lists/*

# requirements.txt 복사 및 설치
COPY requirements.txt /app/
RUN pip install --upgrade pip && pip install -r requirements.txt

# 프로젝트 소스 복사
COPY . /app/

# 포트 오픈
EXPOSE 8080

# Gunicorn 포트 바인딩 후 앱 실행
CMD ["gunicorn", "server.wsgi:application", "--bind", "0.0.0.0:8080"]

(알아봐야할 내용)
+) 환경 변수 설정 부분 의미?
+) build-essencial, libpq-deb, netcat-openbsd 패키지 용도? 패키지 설치 후 다 지우는 이유?
+) 8080 포트 오픈 되었는데 외부노출(접속 허용)은 안한다는게 설정 어디에 있는건지?

C) 장고 이미지 빌드

docker build . -t mydjango:latest

. 현재 디렉토리의 Dockerfile을
-t latest 태그를 붙여
이미지로 빌드한다.

4️⃣ Step4: 장고 컨테이너 실행

docker run -d \
--name mydjango \
--network mynetwork \
-e PIPELINE=production \
-e SECRET_KEY=[내 장고 프로젝트 시크릿키] \
mydjango:latest   (이미지 이름)

데몬으로 컨테이너를 실행시키고
mydjango로 컨테이너 이름을 설정하고
mynetwork로 도커 네트워크를 설정하고
배포용 settings.py를 사용하기 위해 환경변수를 설정해주고
배포용이기 때문에 SECRET_KEY는 환경변수로 제공해줘서
mydjango:latest 이미지를 실행시킨다

장고 컨테이너 실행과 동시에 데몬이 종료되고 Exited(3)가 뜨는 시행착오를 겪었는데,

docker logs [컨테이너ID]

위 명령어로 해당 컨테이너 실행시 발생한 오류를 확인할 수 있다.

5️⃣ Step5: nginx 설정파일 작성

Nginx 컨테이너를 띄우기 위해 conf 파일을 작성했다.
장고앱 디렉토리가 있는 위치에 작성해준다.

server {
    listen 80;
    server_name [내 도메인명];

    location / {
        proxy_pass http://[장고 컨테이너명]:8080;
        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;
    }
}

깡통 장고이기 때문에 static이나 media 설정은 없다.
+) proxy_ 의미들?

6️⃣ Step6: nginx 컨테이너 실행

docker run -d \
  --name mynginx \
  --network mynetwork \
  -p 80:80 \
  -v $(pwd)/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro \
  nginx:latest

데몬으로 컨테이너를 실행시키고
mynginx 컨테이너 이름을 설정하고
mynetwork로 도커 네트워크를 설정하여
nginx 이미지를 실행시킨다.
+) -v 옵션 의미? :ro 의미?

7️⃣ Step7: 브라우저에서 도메인 치고 들어가서 확인


실패처럼 보이는 성공!

초기화 상태의 장고 앱이기 때문에 루트(/) URL에 대한 설정이 없다.
또한 운영서버를 가정하고 DEBUG = False 설정을 했기 때문에 장고의 로켓 이미지도 없다.

🧚🏻 컨테이너 기반 아키텍처

  • mypostgres - DB 담당
  • mydjango - 비즈니스 로직 담당
  • mynginx - 프록시, (정적파일 서빙), (로드밸런싱) 담당

mynetwork를 통해 총 3개의 컨테이너 사이의 통신을 가능하게 했다.

그렇다면 왜 컨테이너를 분리해서 띄울까?
1. 독립적인 배포가 가능하다.

  • 장고 앱에서 버그가 생겼을 때 오류 수정 후 장고 컨테이너만 갈아끼면 된다.
  • 컨테이너 단위로 로그관리가 가능하다
  • 즉 유지보수가 쉬워진다.

2. 책임 분리가 가능하다

3. 보안이 강화된다.

  • DB와 Django의 경우 외부 포트를 열어두지 않았기 때문에 보안 측면에서 우수하다.

+) 기존 포레포레와 비교했을 때 컨테이너 분리 장점 ? 특히 책임분리 측면에서
+) 컨테이너 분리 == 포트분리 라고 볼 수 있는지 ?

🧚🏻 추후 계획

    본문 노란색 하이라이트 부분 체크
    메인 노트북에서 작업한 뒤 Docker Hub에서 내려받아 우분투 서버에서 RUN 할 수 있도록 설정
    환경변수 파일로 관리
    settings.py 배포용 / 개발용 설정 재확인
    간단한 장고 앱 작성 후 PostgreSQL DB 업데이트 확인
    Nginx에서 정적파일 서빙하도록 conf 설정 추가


끝!
profile
하나씩 차근차근 천천히

0개의 댓글