docker를 사용해서 프로젝트를 배포하는 방법에 대해 리뷰해보겠습니다.
크게 django, nginx, postgresql 컨테이너를 생성하여 튜토리얼을 진행해보겠습니다.
1. django 컨테이너
서버 컨테이너의 경우, docker hub의 오피셜한것이 아닌 직접 빌드를 해야하기 때문에 Dockerfile 작성이 선행되어야합니다.
dockerfile에서는 프로젝트 copy, 패키지 설치 및 collectstatic만 진행합니다.
# /Dockerfile
FROM python:3.11.4
RUN apt-get -y update
RUN apt-get -y install vim
RUN pip install --upgrade pip
COPY . /server
WORKDIR /server
RUN pip install -r requirements.txt
RUN echo yes | poetry run python manage.py collectstatic
EXPOSE 8000
기존에 만약에 static 디렉터리가 존재할경우, django에서는 overwrite할지의 여부를 묻기 때문에 echo yes를 붙여주게 되었습니다.
--> 보통, aws s3를 사용하기 때문에 대부분 존재할 경우가 있을것입니다.
docker-compose.yml
version: '3'
services:
server:
build:
context: .
command: >
bash -c "python3 manage.py makemigrations --settings=config.settings.deploy
&& gunicorn --bind 0.0.0.0:8000 config.wsgi.local:application"
ports:
- "8000:8000"
volumes:
- ./server:/server
migration 과정을 dockerfile이 아닌 docker-compose에서 빌드를 하는 이유는 현재의 경우, postgresql 컨테이너가 뜨기전 미리 docker image 생성 -> postgresql up -> server up의 과정을 거치게 됩니다. 때문에 순서상의 이유로 db가 올라오지 않은 상태로 migration을 진행하게 되어 제대로 빌드가 되질 않습니다.
2. postgresql 컨테이너
postgres - Official Image | Docker Hub
Note: the description for this image is longer than the Hub length limit of 25000, so has been trimmed. The full description can be found at https://github.com/docker-library/docs/tree/master/postgres/README.md. See also docker/hub-feedback#238 and docker/
hub.docker.com
postgresql의 경우, dockerhub에 있는 이미지를 가져와 컨테이너로 활용하기 때문에 별도의 dockerfile은 필요없이 compose에 업데이트 후 django의 세팅만 수정해주신 후 의존성만 명시해주면 쉽게 해결가능합니다.
- docker-compose 파일 수정
version: '3'
services:
postgres:
image: postgres
hostname: postgres
restart: always
ports:
- "5432:5432"
environment:
POSTGRES_DB: "postgres"
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "postgres"
server:
build:
context: .
command: >
bash -c "python3 manage.py makemigrations --settings=config.settings.deploy
&& gunicorn --bind 0.0.0.0:8000 config.wsgi.local:application"
ports:
- "8000:8000"
volumes:
- ./server:/server
depends_on:
- postgres
environment 값의 경우, 만약 실제로 사용하신다면 시스템 환경변수를 이용해 설정해주시기 바랍니다.
- django settings.py 변경
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "postgres",
"HOST": "postgres",
"USER": "postgres",
"PASSWORD": "postgres",
"PORT": 5432,
}
}
docker-compose파일에 명시해준 내용과 매칭을 하게 된다면 POSTGRES_DB=NAME, POSTGRES_USER=USER, POSTGRES_PASSWORD=PASSWORD, hostname=HOST가 됩니다. 기본적으로 django에서 postgresql을 사용하기 위해선 psycopg2 설치가 선행되어야합니다.
docker에서는 기본적으로 service명=host 입니다. 위의 docker-compose에서 명시적으로 hostname을 명시하기는 했지만 만약 안했어도 기본적으로 postgres로 설정 되게 됩니다.
3. nginx 컨테이너
- docker-compose 수정
version: '3'
services:
postgres:
image: postgres
hostname: postgres
restart: always
ports:
- "5432:5432"
environment:
POSTGRES_DB: "postgres"
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "postgres"
server:
build:
context: .
command: >
bash -c "python3 manage.py makemigrations --settings=config.settings.deploy
&& gunicorn --bind 0.0.0.0:8000 config.wsgi.local:application"
ports:
- "8000:8000"
volumes:
- ./server:/server
depends_on:
- postgres
nginx:
image: nginx
depends_on:
- server
volumes:
- ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
ports:
- "80:80"
- ./nginx/conf.d/default.conf
server {
listen 80;
server_name 본인 서버 호스트;
charset utf-8;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
proxy_pass http://server:80/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static/ {
autoindex on;
alias /static/;
}
}
nginx의 기본 설정을 바라보는 경로인 /etc/nginx/conf.d/default.conf와 로컬 경로를 docker volume을 활용하여 공유 하기 때문에 미리 위와같은 default.conf 파일이 작업된상태로 존재해야합니다.
nginx의 경우, 서버가 정상적으로 실행된 이후 마지막에 웹서버가 떠있어야하므로 의존성을 server로 설정해주었고 위에서 말했듯이 docker에서는 서비스명 = 호스트가 되므로 proxy_pass를 http://server:80으로 설정해주었습니다.
이후엔 이전 과정의 설정이 문제없었다면 아래 명령어를 통해 배포를 진행해주시면 됩니다.
docker compose up -d --build
사실 db의 경우, 실제 배포시엔 따로 데이터베이스 호스트가 이미 존재해있을것이기 때문에 요구사항에 맞춰 참고용으로 봐주시면 감사드리겠습니다 :)
도커를 활용하면서 느끼는점이 물론 배포시에도 큰 이점이 있지만 초기 세팅할때 정말 편하게 활용 가능하다는점이 있다고 생각합니다.
최근, 회사에 신규 입사자가 들어오시면서 도커로 빌드가 안되어있던 프로젝트와 되어 있던 프로젝트 세팅을 하며 확실히 그차이를 느낄수 있었습니다. 초기 환경 설정에 있어서 귀찮고 힘들수도 있지만 이것이 나중을 생각했을때 불러올 스노우볼을 생각해보면 정말 좋은 오픈소스 프로젝트라고 생각합니다!!
'기술 > Django' 카테고리의 다른 글
Django orm 성능 개선 해보기(bulk method, n+1 problem) (0) | 2023.09.02 |
---|---|
처음부터 끝까지 kakao 소셜로그인 구현하기(feat. django) (1) | 2023.07.17 |
django 배포 환경 구축하기(1) 환경 분리 (1) | 2023.05.20 |
two scoops of django - 쿼리와 데이터베이스 레이어(트랜잭션은 언제 사용하는가?) (0) | 2022.09.03 |
two scoops of django - django에서 모델이란? (0) | 2022.09.01 |