do it! 장고+부트스트랩 파이썬 웹 개발의 정석 책을 참고하며 작성한 포스팅입니다.
도커는 다른 하드웨어와 운영체제에서 작업하더라도 동일한 환경을 갖출 수 있도록 도와주는 기술입니다.
도커 설정 파일에는 웹 사이트 배포에 필요한 환경설정 정보를 모두 지정합니다.
예를 들자면 운영체제, 파이썬 버전, 라이브러리, 소스 코드, 이미지 파일 등이 있습니다.
도커를 실행하면, 도커 설정 파일에서 지정한 대로 서버 전체를 온전히 복제한 컨테이너 이미지가 생성됩니다.
그리고, 컨테이너 이미지를 작동시키면 컨테이너가 실행되면서 기존과 동일한 상태로 웹사이트 서버를 실행합니다.
도커 설정 -> 도커 실행 -> 컨테이너 이미지 생성 -> 컨테이너 이미지 실행 -> 컨테이너 실행 -> 웹 사이트 서버 실행
컨테이너 이미지에는 서버 전체가 온전히 담기기 때문에, 다른 컴퓨터에서 도커를 설치하고 이미지를 복제해서 작동하기만 하면, 기존과 동일한 상태로 웹사이트 서버 실행이 가능합니다.
윈도우 기준 설명입니다.
컴퓨터가 가상화 기능을 지원하는지 확인합니다.
Ctrl+Alt+Del를 누르고 작업 관리자 창을 연 후, [성능] 탭의 CPU에서 가상화가 사용으로 되어있는지 확인합니다.
도커 사이트(https://www.docker.com/)에 들어갑니다.
도커를 설치합니다.
설치후 파란버튼을 눌러 윈도우를 재시작합니다.
도커가 잘 설치되었지 확인하기위해, 도커 버전을 확인해줍니다.
pip freeze > requirements.txt
명령어로 가상환경에 설치한 라이브러리들을 리스트로 만들어 저장합니다.
프로젝트 폴더 안에 Dockerfile
파일 생성하기
도커 설정 파일의 파일명은 기본적으로 Dockerfile
로 약속되어 있습니다.
저는 편집하기 쉽게, VS Code에서 Docker 익스텐션을 설치했습니다.
아래와 같이 코드를 작성해줍니다.
# pull official base image
FROM python:3.12.0-alpine
# set work directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
RUN apk update
RUN apk add postgresql-dev gcc python3-dev musl-dev zlib-dev jpeg-dev
COPY . /usr/src/app/
# install dependencies
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
/usr/src/app
으로 지정합니다.PYTHONDONTWRITEBYTECODE 1
을 설정해서 .pyc 파일이 생성하지 않도록 합니다.PYTHONUNBUFFERED 1
을 설정해서 파이썬 로그가 버퍼링 없이 즉각적으로 출력하게 만듭니다.COPY {복사하고 싶은 폴더위치} {복사될 폴더 위치}
로 로컬 컴퓨터에서 Dockerfile이 있는 위치에 있는 파일을 모두 작업 폴더(WORKDIR)로 복사합니다. 그러면 장고 프로젝트는 도커 이미지에 담깁니다.RUN pip install -r requirements.txt
로 requirements.txt
에 나열된 라이브러리를 설치합니다.프로젝트 폴더 안에 docker-compose.yml
파일 생성하기
도커 컴포즈 파일을 사용하면 컨테이너 여러 개를 한 번에 실행시킬 수 있고, 컨테이너를 실행시킬 때 옵션도 줄 수 있습니다.
도커 컴포즈 파일의 파일명은 기본적으로 docker-compose.yml
로 약속되어 있습니다.
아래와 같이 코드를 작성해줍니다. (개발 환경 버전)
version: '3'
services:
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- ./:/usr/src/app/
ports:
- 8000:8000
env_file:
- ./.env.dev
version
에는 도커 컴포즈 파일 포맷 버전을 넣어줍니다.web
이라는 서비스 하나가 실행됩니다.build: .
는 현재 폴더를 빌드한다는 뜻입니다. Dockerfile이 있는 위치를 지정하여 컨테이너 이미지를 만듭니다.volumes
로 로컬 컴퓨터의 폴더와 도커 폴더를 연결합니다. 여기서는 현재 폴더를 /usr/src/app
폴더와 연결하고 있습니다.env_file
을 따로 명시함으로써 오류 페이지가 다른 사람에게 보이지 않도록 개발환경(.env.dev
)과 배포환경(.env.prod
)로 나누어 관리합니다. 현재 배포용이 없으므로 개발환경 파일(.env.dev
)만 지정했습니다.settings.py 수정 후, 개발환경 파일 생성하기
.env.dev
)을 활용할 수 있도록 settings.py
를 수정합니다. 로컬과 배포환경에서 settings.py
를 다르게 적용하기 위해 수정하는 것입니다.os.environ.get()
으로 개발환경 파일에서 값을 읽어올 수 있을 때는 그 값을 사용하고, 없을 때는 두 번째 매개변수 값을 활용합니다.import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = os.environ.get(
"SECRET_KEY", "*****장고시크릿키******"
)
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.environ.get("DJANGO_DEBUG", "") != "False"
if os.environ.get("DJANGO_ALLOWED_HOSTS"):
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ")
else:
ALLOWED_HOSTS = []
# Set CSRF trusted origins to allow any app on Railway and the local testing URL
CSRF_TRUSTED_ORIGINS = ["https://*.railway.app", "https://*.pythonanywhere.com"]
# 생략...
SECRET_KEY
: '*****'
에는 프로젝트에서 적혀진 부분을 그대로 사용합니다.DEBUG
ALLOWED_HOSTS
127.0.0.1
이나 localhost
로 장고에 접근할 수 있어야 합니다. 그래서 env 파일에서 DJANGO_ALLOWED_HOSTS
를 읽어올 수 있으면 그 값을 사용하고, 없다면 이전과 동일하게 되도록 설정합니다.# 개발환경 파일 생성
SECRET_KEY="*****장고시크릿키*******"
DJANGO_DEBUG=True
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
DJANGO_ALLOWED_HOSTS
에는 개발할 때 활용할 주소를 적었습니다.도커 컨테이너 실행
터미널에서 docker-compose build
명령어로 이미지를 만들고, docker-compose up
으로 컨테이너를 실행합니다.
(venv) $ docker-compose build
(venv) $ docker-compose up
docker-compose up
을 했을때 잘 실행 되는 것을 확인했고, 127.0.0.1:8000
에도 잘 접속되는 것을 확인했습니다.
서비스를 멈출 때는 Ctrl+c를 눌러줍니다.
docker-compose up -d
명령어를 입력하면, 로그없이도 웹 접속이 가능한 것을 확인할 수 있습니다.
추가로, Vs Code 익스텐션을 통해 이미지 생성과 콘테이너가 실행되는 것을 확인할 수 있습니다.
잘 실행되는 것을 확인했으니, docker-compose down
명령어로 컨테이너 중단을 해줍니다. 그러면 실행중인 컨테이너가 삭제된 것을 확인할 수 있습니다.
장고는 기본적으로 sqlite3로 데이터베이스를 제공합니다.
파일을 이용한 데이터베이스이기 때문에 특별한 설정 없이도 간편하게 사용할 수 있다는 장점이 있습니다.
하지만, 프로젝트 규모가 커지거나 사용자가 많을 경우 충분한 성능을 기대하기 어렵다는 단점이 있습니다.
그래서, 따로 데이터베이스를 두어 웹사이트를 실행해보겠습니다.
이번에 사용할 데이터베이스는 PostgreSQL입니다.
만약 도커를 사용하지 않는다면 로컬 컴퓨터에서 PostgreSQL을 설치하고, 서버에서도 또 한 번 설치/설정 작업을 해야합니다. 도커가 있기에 이 작업을 단순화 할 수 있습니다. 도커 짱👍
기존 docker-compose.yml
에 데이터베이스만 담당하는 컨테이너 추가하기
docker-compose.yml
을 이용하면 여러 개의 컨테이너를 한 번에 실행 시킬 수 있는데요, 장고는 web
이라는 컨테이너에서 실행하고, 데이터베이스를 담당하는 부분은 db
라는 이름의 컨테이너에서 실행하도록 설정하겠습니다.
# 생략
services:
web:
# 생략
depends_on:
- db
db:
image: postgres:12.0-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=eatwell_db_user
- POSTGRES_PASSWORD=eatwell_db_pwd
- POSTGRES_DB=eatwell_dev
volumes:
postgres_data:
depends_on
을 db
로 설정합니다.postgres:12.0-alpine
로 사용했습니다.eatwell_dev
로 구분했습니다.settings.py
에 있는 DB 연결 수정하기
DB를 Sqlite3로 사용할지, PostgreSQL로 사용할지는 settings.py에 정의되어 있습니다. 장고는 프로젝트를 생성할때 자동으로 데이터베이스에 대한 내용을 설정합니다.
# settings.py
DATABASES = {
"default": {
"ENGINE": os.environ.get("SQL_ENGINE", "django.db.backends.sqlite3"),
"NAME": os.environ.get("SQL_DATABASE", BASE_DIR / "db.sqlite3"),
"USER": os.environ.get("SQL_USER",'user'),
"PASSWORD": os.environ.get("SQL_PASSWORD",'password'),
"HOST": os.environ.get("SQL_HOST",'localhost'),
"PORT": os.environ.get("SQL_PORT",'5432'),
}
}
USER, PASSWORD, HOST, PORT는 PostgreSQL을 관리하는데 필요한 내용입니다.
.env.dev
파일 업데이트하기
# 생략
SQL_ENGINE=django.db.backends.postgresql
SQL_DATABASE=eatwell_dev
SQL_USER=eatwell_db_user
SQL_PASSWORD=eatwell_db_pwd
SQL_HOST=db
SQL_PORT=5432
PostgreSQL을 프로젝트의 settings.py
에서 활용할 수 있도록 .env.dev
파일을 업데이트 합니다.
psycopg2 모듈 설치하기
psycopg2 모듈은 파이썬에서 PostgreSQL을 사용할 수 있게 해줍니다.
그리고 pip freeze로 requirements.txt에 psycopg2가 반영된 결과를 반영합니다.
도커 이미지를 만들어서 활용해야 하므로, requirements.txt에 필요한 모듈을 추가하고 도커 이미지에 반영합니다.
(venv) $ pip install psycopg2
(venv) $ pip freeze > requirements.txt
이미지 빌드하고 실행하기
docker-compose build
로 이미지를 빌드하고, docker-compose up
으로 실행합니다.
web 컨테이너에 접속해서 데이터베이스 마이그레이션하기
도커 컨테이너가 실행되는 상태에서 다른 새로운 터미널을 열어 docker-compose exec web python manage.py migrate
을 입력합니다. 도커로 만든 web 컨테이너에 접속해서 python manange.py migrate
을 실행하라는 뜻입니다.
새로운 관리자 계정과 포스트 만들기
새로 데이터베이스를 만들었기 때문에 데이터들이 존재하지 않습니다.
그래서 관리자 계정을 먼저 만든 다음 admin 사이트에 들어가서 글 하나를 만들겠습니다.
docker-compose 명령을 이용해서 현재 실행 중인 web 컨테이너에 접속해서 superuser을 만들어 줍니다.
(venv) $ docker-compose exec web python manage.py createsuperuser
admin 사이트에 들어가서 글 하나를 등록해줍니다.
상세 페이지에 들어가면 작성한 글이 보이는 것을 확인할 수 있습니다.
Ctrl+c
를 눌러 컨테이너 실행을 중단시키고 다시 컨테이너를 실행해도 데이터베이스에 저장했던 내용은 사라지지 않고 보존되는 것을 확인할 수 있습니다.