TIL 67) 2022.07.26 (화) | 최종프로젝트 14일차
거북이반 강의 정리 및 EC2 배포를 위한 사전지식 정리
백엔드 배포를 위해서 여러 공식문서와 구글링을 통해서 개발블로그들을 찾아보았지만 내가 원하는 개발환경과 맞지 않아서 어려움을 겪고 있었는데 거북이반 강의에서 docker 배포를 다뤄주셔서 내가 추가로 찾아보면서 공부한 내용과 함께 정리해보았다.
Docker - Nginx - Gunicorn - Django - Postgres
거북이반 강의 : (권기현 튜터) https://www.youtube.com/channel/UC85XI2fiPooiLKtAVAjSvwQ/playlists
dotenv
CI를할 때 dotenv로 환경변수를 관리하면 환경변수를 불러올 수 없어서 에러가 발생
git action에서 secret 설정
.env에 있는 내용은 깃허브에 업로드하지 않기 때문에 [git hub] - [setting] - [secret action] - [secret 추가]
yml파일에 env: SECRET_KEY: ${{secret.SECRET_KEY}}
로 불러오기
새로운 장고시크릿키 발급하기
이미 settings.py 를 깃허브에 올렸을 때 시크릿키가 노출됬다면 새로 발급받을 수 있음
터미널에 아래 명령어 입력시 새로운 시크릿 키 발급 가능
python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'
발급받은 키를 .env 파일에 붙여넣어주고 .gitignore에 .env파일 추가해주기
Docker
Dockerfile 설정해주기
FROM python 3.7 # 기본환경 설정
ENV PYTHONDONTWRITEBYTECODE=1 # 파이썬이 소스코드가 컴파일 과정을 거칠 때 .pyc파일을 생성하게 되는데 docker에서는 필요없기 때문에 이 파일을 생성하지 않도록 하는 설정
ENV PYTHONUNBUFFERED=1 # 파이썬 로그가 버퍼링없이 즉각적으로 출력하는 설정
RUN apk update
RUN apk add build-base python3-dev py-pip jpeg-dev zlib-dev # 패키지 업데이트
COPY requirements.txt /usr/src/app/ # 이 디렉토리에 복사 (여기에 프로젝트를 두도록 함)
WORKDIR /usr/src/app # 작업폴더를 프로젝트를 두기로 한 디렉토리로 설정해주기
RUN pip install -r requirements.txt # docker container에 패키지 설치해주기
COPY . /usr/src/app # 프로젝트의 모든 내용을 이 디렉토리에 복사
build
Dockerfile build
- docker build -t <tag_name> . # . 경로에 있는 dockerfile을이용해서 build하고, 태그이름은 <tag_name>으로 함
- 에러메세지가 뜬다면 혹시 패키지를 추가로 설치해줘야하는 지 확인할 것
빌드한 이미지를 바탕으로 서버 돌려보기
docker run -dp 8000:8000 /
# -dp : detached mode(background), port forwarding (특정한 포트로 들어오는 데이터를 다른포트로 바꿔서 다시 전송하는 것)-w /usr/src/app -v "(pwd):/usr/src/app" /
# -w : workdirectory 작업폴더 설정 / -v : 호스트와 컨테이너의 디렉토리를 연결(마운트)<image_tag_name>
# 빌드할 때 설정해준 docker image tag 이름sh -c "python manage.py runserver 0.0.0.0:8000"
# shell에서 입력할 command 설정
docker-compose.yml
version: "3.8" # 사용할 docker-compose 문법 버전
service:
web:
build:
command: python manage.py runserver 0.0.0.0:8000 # web service 를 시작할 때 입력할 명령어
ports:
- 8000:8000
working_dir: usr/src/app/
volume:
- ./:/usr/src/app/ # bind mount
env_file:
- ./.env # 현재폴더에 있는 .env를 설정
docker-compose build
docker-compose up
브라우저에서 서버가 켜져있는지 확인
postgres
# settings.py
DATABASES = {
'ENGINE' : os.environ.get('SQL_ENGINE', 'django.db.backends.sqlite3'), # 환경변수로 설정해주고 설정해준 db가 안보일 경우 디폴트로 sqlite3 사용
'NAME' : os.environ.get('SQL_DATABASE', BASE_DIR / 'db.sqlite3'), # 사용할 db 이름
'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'),
}
# .env
SECRET_KEY = 'django secret key 입력'
SQL_ENGINE='django.db.backends.postgresql'
SQL_DATABASE='db name'
SQL_USER='db username'
SQL_PASSWORD='db password'
SQL_HOST='db'
docker-compose에 postgres 추가하기
version: "3.8" # 사용할 docker-compose 문법 버전
service:
web:
build:
command: python manage.py runserver 0.0.0.0:8000 # web service 를 시작할 때 입력할 명령어
ports:
- 8000:8000
working_dir: usr/src/app/
volume:
- ./:/usr/src/app/ # bind mount
env_file:
- ./.env # 현재폴더에 있는 .env를 설정
depends_on:
- db # db를 먼저 실행시켜주기 위해서 설정
db:
image: postgres:14.4-alpine # 버전 지정
volume:
- postgres_db:/var/lib/postgresql/data
environment: # django settings.py 에 들어간 설정과 동일하게 작성
- POSTGRES_DB=
- POSTGRES_USER=
-POSTGRES_PASSWORD=
posts:
- '5432:5432' # 써줘도 되지만 나중에 pgadmin 같은 워크벤치로 db를 조회하기 위해 필요
volumes:
postgres_db: # named volume은 선언해줘야함
Dockerfile에 libpq-dev
추가 (postgres 빌드를 위해 필요한 라이브러리)
- psycopg2 : django-postgres 송신을 할 수 있게 해주는 모듈 ex) MySQL client
pip install psycopg2
pip freeze > requirements.txt
설치되어야 하는 곳이 docker container 안이므로 psycopg2가 설치 안된다면 그냥 requirements.txt에 psycopg2==2.9.3
이런식으로 직접 추가해줘도 된다. (가상환경이나 컴퓨터에 직접 설치할 필요 없음)
이 상태에서 서버를 실행시키면 admin 페이지에 들어갔을 때 데이터가 없는 상태라 에러가 난다.
에러를 해결해 주려면 마이그레이션을 해줘야한다.
db 연결 후 migration
[docker desktop]
container 두개 중 web container terminal 에서 python manage.py migrate
, python manage.py createsuperuser
admin 페이지에서 작성한 데이터는 container 두개중 postgres container에 저장되고 volume이 연결되어 있기 때문에 동시에 volume에도 저장이 된다.
container를 지우더라도 volume이 있다면 docker-compose up
을 했을 때 데이터가 계속 유지가 되고 있음
pgAdim
add newserver - connection - host: localhost / port: 5432 / username: username / password: password
위에서 작성했던 유저 정보 입력
schema - public - table 들어가면 container에 들어있는 데이터를 쉽게 확인할 수 있음
dotenv
위에서 docker-compose.yml에 입력했던 db 정보를 dotenv를 통해 관리
.gitignore 에 꼭 추가시켜줘야함!!!
# .env.postgres
POSTGRES_DB='db name'
POSTGRES_USER='db username'
POSTGRES_PASSWORD='db password'
docker-compose에도 새로 추가한 환경변수 파일경로 추가해주기
# docker-compose.yml
- db:
- env_file:
- ./.env.postgres
설정값을 바꾸고 나면 build를 해서 변경된 내용을 새로 이미지를 만들어줘야함
추가로 이미 docker-compose에 한번 노출된 정보를 변경하기 위해서 db 정보를 변경하더라도 volume에 계속 db 정보가 유지되고 있기 때문에 변경하려면 volume을 삭제해야함 (그 안에 있던 데이터도 같이 날아감..!ㅠㅠ)
다시 빌드를 하게 되면 새로운 db 정보로 로그인이 됨
WSGI
WSGI (Web Server Gateway Interface)
web server와 web application 의 인터페이스를 위한 파이썬 프레임워크
web server
사용자가 브라우저에 URL을 입력하면, 브라우저는 웹서버에 웹페이지를 보내달라는 요청을 한다.
웹 서버는 HTTP 요청을 파싱한 후, 정적 컨텐츠(HTML, CSS, image ...)를 저장하고 있다가 브라우저에게 보내준다. ex) Apache, Nginx
- 브라우저와 웹서버는 HTTP로 통신하는데, 기본적으로 클라이언트와 서버 간에 요청과 응답이 1:! 구조를 가지고 있어 한 화면을 구성하는 컨텐츠가 100개 라면 요청과 응답도 100번 이뤄지게 됨
web application
웹 어플리케이션 서버(WAS)는 웹서버에서 처리하지 못하는 동적 컨텐츠를 처리해 웹 서버에게 응답한다. 주로 비지니스 로직을 수행한다. ex) Django, Flask
web server, web application server 는 왜 나눠지게 되었나?
두 서버가 나눠기 전까지는 웹서버에서 동적 컨텐츠를 처리하기 위해서 자체적으로 process를 pork 해서 어플리케이션 코드를 수행했다. 그런데 매 요청마다 이걸 반복하게 되면 요청에 대한 응답이 느려지기 때문에 이를 방지하기 위해서 동적인 요청과 정적인 요청을 서버를 분리해서 처리하게 되었다.
그런데 서버를 나누게 되니 두 서버 사이에 통신 규칙이 필요하게 되었고, 여러 종류의 웹서버와 여러 종류의 웹 어플리케이션이 모두 통신 가능하도록 하기 위해서 WSGI가 등장하게 되었다.
REFERENCE
- docker : https://codecamper.me/blog/26/
- docker volume / bind mount : https://velog.io/@haeny01/Docker-데이터-관리1-Volume-과-Bind-mounts
- WSGI : https://june-coder.tistory.com/53