개요
django(drf) 에서 환경별로 환경변수를 다르게 할 필요가 있었다.
하지막 막상 구글링을 해보니 단일환경에서 .env 파일 하나만 쓰는 글들만 많이 있었고, 그게 아니면 settings.py 만 분리하는 글들이 대부분이였다.
환경 별로 .env 를 나누고, 각 환경마다 django settings 파일까지 분리하는 글은 아직은 찾지 못했다.
약간의 삽질을 통해서 원하는 개발/배포 환경분리 세팅을 완료하였다.
내가 구축하려고 하는 환경분리는 아래와 같다
프로젝트의 환경은 세 개의 환경으로 나뉘어져 있다.
백엔드(drf) | DB(postgreSQL) | |
local 환경 | 로컬 | 로컬 |
dev 환경 | docker(로컬) | 로컬 |
prod 환경 | docker(EC2) | AWS RDS |
지금 같은 상황에서 dev 환경은 로컬에서 docker 로만 백엔드를 띄울뿐이여서 사실 local 환경이랑 크게 다를 바가 없다.
dev환경에서 개발용 백엔드 서버와 개발용 DB서버 를 구축하는 것이 베스트였겠으나 우선은 저렇게 세팅을 했다
.env 파일 작성
python 에서 .env 파일을 읽기 위해 python-dotenv 패키지를 설치한다.
패키지를 설치했다면 .env 파일을 작성해주면 된다.
환경변수의 종류가 하나만 필요하다면 파일명을 그냥 .env 로만 작성해주는 것이 편하다.
파일명이 .env 이면 python-dotenv 에서 파일을 불러올 때 파일명을 명시안해줘도 알아서 인식을 하기 때문이다.
하지만 지금은 dev, local, prod 로 환경이 나뉘어져 있으므로 .env.local, .env.dev, .env.prod 로 파일명을 설정했다.
.env 파일은 key=value 형식으로 작성한다.
예시)
NAME=DB_test
HOST=localhost
PORT=5432
...
Plain Text
복사
docker 설정
dev 환경과 prod 환경에서만 docker, docker-compose 를 사용한다.
dockerfile
dockerfile 은 dev, prod 환경 공통으로 사용한다.
FROM python:3.9-slim
# python 출력 내용을 버퍼에 넣지 않고 바로 출력 => 로그 바로바로 보임
ENV PYTHONUNBUFFERED 1
COPY ./requirements.txt /tmp/requirements.txt
COPY ./ /app
WORKDIR /app
EXPOSE 8000
RUN python -m venv /py && \
/py/bin/pip install --upgrade pip && \
/py/bin/pip install -r /tmp/requirements.txt && \
rm -rf /tmp && \
mkdir logs
ENV PATH="/py/bin:$PATH"
Docker
복사
docker-compose.dev.yml
dev 환경에서 사용할 docker-compose 파일
version: '3.9'
services:
app:
build:
context: . # dockerfile 이 있는 경로
ports:
- '8000:8000'
volumes:
- ./:/app
command: >
sh -c "python manage.py makemigrations &&
python manage.py migrate &&
python manage.py runserver --insecure 0.0.0.0:8000 --settings=config.settings.dev"
env_file:
- .env.dev
environment:
- ENV=dev
YAML
복사
env_file 로 .env.dev 파일을 설정한다.
environment 변수로 ENV=dev 를 설정한다.
docker-compose.prod.yml
prod 환경에서 사용할 docker-compose 파일
version: '3.9'
services:
app:
build:
context: . # dockerfile 이 있는 경로
ports:
- '8000:8000'
volumes:
- ./:/app
command: >
sh -c "python manage.py makemigrations &&
python manage.py migrate &&
python manage.py runserver --insecure 0.0.0.0:8000 --settings=config.settings.prod"
env_file:
- .env.prod
environment:
- ENV=prod
YAML
복사
env_file 로 .env.prod 파일을 설정한다.
environment 변수로 ENV=prod 를 설정한다.
settings.py 분리
settings.py 에 관한 상세한 설명은 아래 글에 잘 나와있다.
settings 폴더 밑에 공통파일인 base.py 가 있고 dev.py, local.py, prod.py 는 base.py 를 상속받는다.
base.py
config/settings/base.py
import os
from dotenv import load_dotenv
# 생략 ..
ENV = os.getenv("ENV", "local")
if ENV == "local":
load_dotenv(verbose=True, dotenv_path=f"{BASE_DIR}/.env.local")
# local 환경에서만 .env 파일 직접 매핑시켜줌
# dev, prod 환경의 .env 파일은 docker-compose 가 주입해준다.
Python
복사
dev 환경과 prod 환경에서는 docker-compose 를 사용하므로 compose yaml 파일에서 설정한 .env 파일이 주입되는데, local 환경은 docker 를 사용하지 않으므로 직접 설정해줘야 한다.
또한 local 환경인지 파악하기 위해서 ENV 환경변수의 값이 local 인지 확인을 할건데, 이는 뒤에 나오는 쉘 스크립트에서 export 문으로 설정해줄 것이다.
local.py, dev.py, prod.py
from .base import *
# 환경별로 세팅 값 추가할 사항 있으면 추가하기
Python
복사
(선택) shell script 생성
매번 직접 커맨드를 치기 귀찮으므로 shell script 를 만들어준다.
물론 터미널에 직접 커맨드를 쳐도 무방하다.
runserver.local.sh
export ENV=local
python manage.py makemigrations
python manage.py migrate
python manage.py runserver --insecure 0.0.0.0:8000 --settings=config.settings.local
Shell
복사
export ENV=local : 환경변수 설정
runserver 를 돌리기 전에 DB migration 을 한다.
--settings=config.settings.local : setting 파일 매핑
runserver.dev.sh
docker-compose -f docker-compose.dev.yml build
docker-compose -f docker-compose.dev.yml
Shell
복사
runserver.prod.sh
docker-compose -f docker-compose.prod.yml build
docker-compose -f docker-compose.prod.yml up
Shell
복사
실행
local 환경 : sh runserver.local.sh
dev 환경 : sh runserver.dev.sh
prod 환경 : sh runserver.prod.sh
TODO
prod 환경에서 runserver 대신 nginx 와 gunicorn 을 적용하고 DEBUG=False 로 바꾸기