docker-compose
파일을 보면 나의 소중한 postgreSQL 아이디와 비밀번호가 적나라하게 적혀있다. .env.postgres
파일을 생성한다. 그리고 아래와 같이 docker-compose
파일에 있는 내용을 복사 붙여넣기 해준다.docker-compose
에 있는 내용은 없애준다.# .env 파일에 있는 부분과 동일한 내용이다. django와 postgres는 이 부분을 통해 통신한다.
POSTGRES_DB="turtle_drf_backend_db"
POSTGRES_USER="turtle_drf_backend_nikevapormax"
POSTGRES_PASSWORD="turtle_drf_backend_password"
.gitignore
에 파일 이름을 넣어주도록 하자. docker-compose
파일을 아래와 같이 변경하면 된다. version: "3.8"
services:
web:
# 현재 폴더에 있는 것들을 사용해 빌드하겠다.
build: .
command: python manage.py runserver 0.0.0.0:8000
ports:
- 8000:8000
working_dir: /usr/src/app/
volumes:
- ./:/usr/src/app/
env_file:
- ./.env
depends_on:
- db
db:
image: postgres:14.4-alpine
volumes:
- postgres_db:/var/lib/postgresql/data # named-volume
env_file:
- ./.env.postgres
ports:
- "5432:5432"
# named-volume을 사용하기 때문에 아래에서 선언해주어야 함
volumes:
postgres_db:
.env
파일과 .env.postgres
파일에서 아이디와 비밀번호를 모두 바꾸었다고 가정하자. 이러고 docker-compose를 빌드하고 실행하려하면 기존에 있던 값들과 충돌해 에러가 나게 된다. 기존의 정보로 만들었기 때문
이다.container를 삭제
해주어야 한다. 그리고 기존의 volume도 없애
주어야 한다. docker-compose.yaml
파일을 한 번 살펴보자. services:
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
gunicorn
이다. (Web Server Gateway Interface)배포용 docker-compose 파일
을 만들 것이다. docker-compose.prod.yaml
로 하고 기존에 사용하던 것을 복사 붙여넣기 했다. version: "3.8"
services:
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
ports:
- 8000:8000
working_dir: /usr/src/app/
volumes:
- ./:/usr/src/app/
env_file:
- ./.env
depends_on:
- db
db:
image: postgres:14.4-alpine
volumes:
- postgres_db:/var/lib/postgresql/data # named-volume
env_file:
- ./.env.postgres
ports:
- "5432:5432"
volumes:
postgres_db:
requirements.txt
에 넣어주도록 하자. $ pip install gunicorn
$ pip freeze > requirements.txt
docker-compose.prod.yaml
의 command: python manage.py runserver 0.0.0.0:8000
를 다음과 같이 변경해주도록 하자. command: gunicorn turtle_drf_backend.wsgi:application --bind 0.0.0.0:8000
wsgi.py
이다. -f
를 붙여주고 바로 뒤에 변경된 파일의 이름을 작성해주면 된다. $ docker-compose -f docker-compose.prod.yaml build
$ docker-compose -f docker-compose.prod.yaml up
psycopg2
가 실행되지 않는다는 에러가 또 났다. 그래서 requirements.txt를 확인했더니 없어 추가
해 주었고, 다시 위의 과정을 진행했고 실행이 잘 되는 것을 볼 수 있었다.localhost:8000
을 입력해 실행이 잘 되는지 보고, admin 페이지로 들어가보자.settings.py
로 이동해 아래와 같이 static 설정을 해주도록 하자.STATIC_ROOT = BASE_DIR / 'static'
STATIC_URL = '/static/'
그리고 전체 urls.py
폴더를 아래와 같이 변경해준다.
from xml.etree.ElementInclude import include
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('user/', include('user.urls')),
path('articles/', include('articles.urls')),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
그리고 다시 빌드를 진행하고 서버를 돌리도록 하자.
$ docker-compose -f docker-compose.prod.yaml up --build
$ python manage.py collectstatic
.env
와 배포에 사용하는 .env
를 구분지어 생성해보도록 하겠다. .env
에서 내용을 복사해와 새로 만든 .env.prod
에 붙여넣기 해준다. 새로운 SECRET_KEY
를 발급받도록 한다. $ python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'
.env.prod
SECRET_KEY = 'bdfy7i5#vxn39k$nk)u+4__v2fjd^@u^=km41sy&z*+0x+km$s'
SQL_ENGINE='django.db.backends.postgresql'
SQL_DATABASE='turtle_drf_backend_db'
SQL_USER='turtle_drf_backend_nikevapormax'
SQL_PASSWORD='turtle_drf_backend_password'
SQL_HOST='db'
SQL_PORT='5432'
.env.postgres.prod
POSTGRES_DB="turtle_drf_backend_db"
POSTGRES_USER="turtle_drf_backend_nikevapormax1"
POSTGRES_PASSWORD="turtle_drf_backend_password1"
.env.postgres.prod
의 USER와 PASSWORD를 바꾸었기 때문에 .env.prod
의 USER와 PASSWORD 또한 바꿔주어야 하는 것이다.SECRET_KEY = 'bdfy7i5#vxn39k$nk)u+4__v2fjd^@u^=km41sy&z*+0x+km$s'
SQL_ENGINE='django.db.backends.postgresql'
SQL_DATABASE='turtle_drf_backend_db'
SQL_USER='turtle_drf_backend_nikevapormax1'
SQL_PASSWORD='turtle_drf_backend_password1'
SQL_HOST='db'
SQL_PORT='5432'
.env
-> .env.dev
.env.postgres
-> .env.postgres.dev
manage.py
에서 env 파일을 읽어오는 부분을 삭제해준다.#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'turtle_drf.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == "__main__":
main()
settings.py
의 설정을 변경해주어야 한다. DATABASES
는 예전에 설정한 값이지만, 다시 한 번 작성하는 이유는 이곳에도 default 값이 적용되어 있고 이는 runserver를 실행할 때는 sqlite3를 사용할 수 있도록 하는 코드이다. # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ.get("SECRET_KEY", "somesecret")
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = int(os.environ.get("DEBUG", 1))
...
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'),
}
}
.env.dev
및 .env.prod
에도 아래와 같이 DEBUG를 추가해준다..env.dev
DEBUG = '1'
SECRET_KEY = 'django-insecure-5ofxcce2mfgazkn2w(o16j2i_rj6w^7%)xeilm$8go4qezt^ng'
SQL_ENGINE='django.db.backends.postgresql'
SQL_DATABASE='turtle_drf_backend_db'
SQL_USER='turtle_drf_backend_nikevapormax'
SQL_PASSWORD='turtle_drf_backend_password'
SQL_HOST='db'
SQL_PORT='5432'
.env.prod
DEBUG = '0'
SECRET_KEY = 'bdfy7i5#vxn39k$nk)u+4__v2fjd^@u^=km41sy&z*+0x+km$s'
SQL_ENGINE='django.db.backends.postgresql'
SQL_DATABASE='turtle_drf_backend_db'
SQL_USER='turtle_drf_backend_nikevapormax1'
SQL_PASSWORD='turtle_drf_backend_password1'
SQL_HOST='db'
SQL_PORT='5432'
settings.py
에서 DEBUG를 설정했다. .env.dev
와 .env.prod
에서 DEBUG를 문자열 1 또는 0으로 설정했는데개발
환경에서는 DEBUG가 int('1')이 되어 디버깅이 활성화
되고배포
에서는 DEBUG가 int('0')이 되어 디버깅이 실행되지 않는다.
gitignore
에도 아래와 같이 수정 또는 추가하도록 하자..env.dev
.env.prod
.env.postgres.dev
.env.postgres.prod
docker-compose.prod.yaml
또한 아래와 같이 현재 바뀐 파일 명으로 변경해준다.version: "3.8"
services:
web:
# 현재 폴더에 있는 것들을 사용해 빌드하겠다.
build: .
command: gunicorn turtle_drf.wsgi:application --bind 0.0.0.0:8000
ports:
- 8000:8000
working_dir: /usr/src/app/
volumes:
- ./:/usr/src/app/
env_file:
- ./.env.prod
depends_on:
- db
db:
image: postgres:14.4-alpine
volumes:
- postgres_db:/var/lib/postgresql/data # named-volume
env_file:
- ./.env.postgres.prod
ports:
- "5432:5432"
# named-volume을 사용하기 때문에 아래에서 선언해주어야 함
volumes:
postgres_db:
$ docker-compose down
docker-compose.prod.yaml
로 와 nginx
서비스를 작성해보도록 하겠다.version: "3.8"
services:
nginx:
build: ./nginx
volumes:
- static_volume:/usr/src/app/static
- media_volume:/usr/src/app/image
ports:
- 80:80
depends_on:
- web
web:
# 현재 폴더에 있는 것들을 사용해 빌드하겠다.
build: .
command: gunicorn turtle_drf.wsgi:application --bind 0.0.0.0:8000
ports:
- 8000:8000
working_dir: /usr/src/app/
volumes:
- ./:/usr/src/app/
- static_volume:/usr/src/app/static
- media_volume:/usr/src/app/image
expose:
- 8000
env_file:
- ./.env.prod
depends_on:
- db
db:
image: postgres:14.4-alpine
volumes:
- postgres_db:/var/lib/postgresql/data # named-volume
env_file:
- ./.env.postgres.prod
ports:
- "5432:5432"
# named-volume을 사용하기 때문에 아래에서 선언해주어야 함
volumes:
postgres_db:
static_volume:
media_volume:
nginx/
폴더 안에 아래의 파일들을 생성한다. nginx.conf
upstream turtle_drf_backend {
server web:8000; # docker-compose.prod.yaml의 web에 설정한 8000과 연결되게 된다.
} # nginx와 gunicorn이 통신할 때 여기로 함 (내부 통신)
server {
listen 80; # web의 80번 포트이자 default http의 포트를 그대로 사용한다. (외부 통신)
location / {
# nginx에서 제공하는 default setting
proxy_pass http://turtle_drf_backend;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /static/ {
alias /usr/src/app/static/;
}
location /image/ {
alias /usr/src/app/image/;
}
}
Dockerfile
FROM nginx:1.22.0-alpine
# 실행이 되면 nginx의 기본 설정파일들을 없앤다.
RUN rm /etc/nginx/conf.d/default.conf
# 없앤 기본 설정파일들 대신 내가 만든 nginx.conf를 복사해 넣어준다.
COPY nginx.conf /etc/nginx/conf.d
$ docker-compose -f docker-compose.prod.yaml up --build
브라우저에서 localhost
로 들어가려 하면 아래와 같이 에러가 나는 것을 볼 수 있다.
이유는 내가 DEBUG 모드를 끝냈기 때문이다.
해당 문제를 해결하기 위해서는 settings.py
를 수정해야 한다.
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = int(os.environ.get("DEBUG", 1))
if os.environ.get("DJANGO_ALLOWED_HOSTS"):
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ")
else:
ALLOWED_HOSTS = []
.env.prod
를 아래와 같이 변경해준다.
DEBUG = '0'
SECRET_KEY = 'bdfy7i5#vxn39k$nk)u+4__v2fjd^@u^=km41sy&z*+0x+km$s'
DJANGO_ALLOWED_HOSTS = localhost 127.0.0.1
SQL_ENGINE='django.db.backends.postgresql'
SQL_DATABASE='turtle_drf_backend_db'
SQL_USER='turtle_drf_backend_nikevapormax1'
SQL_PASSWORD='turtle_drf_backend_password1'
SQL_HOST='db'
SQL_PORT='5432'
변경된 코드들의 의미를 살펴보자.
DJANGO_ALLOWED_HOSTS = localhost 127.0.0.1
를 보면 localhost와 127.0.0.1은 띄어쓰기
를 기준으로 나뉘어져 있다. ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ")
에서는 띄어쓰기
를 통해 DJANGO_ALLOWED_HOSTS에 값들을 넣어준다. 따라서 우리는 위의 두 코드를 통해 두 가지의 호스트를 얻을 수 있다.localhost
127.0.0.1
.env.dev
에는 현재 DEBUG가 1이라 의미는 없지만 같이 넣어주도록 하겠다.
DEBUG = '1'
SECRET_KEY = 'django-insecure-5ofxcce2mfgazkn2w(o16j2i_rj6w^7%)xeilm$8go4qezt^ng'
# 현재 DEBUG가 1이라 쓰이지는 않지만 넣어둠
DJANGO_ALLOWED_HOSTS = localhost 127.0.0.1
SQL_ENGINE='django.db.backends.postgresql'
SQL_DATABASE='turtle_drf_backend_db'
SQL_USER='turtle_drf_backend_nikevapormax'
SQL_PASSWORD='turtle_drf_backend_password'
SQL_HOST='db'
SQL_PORT='5432'
$ docker-compose -f docker-compose.prod.yaml down
$ docker-compose -f docker-compose.prod.yaml up --build
브라우저를 통해 다시 localhost에 들어가면 에러가 나는데, 아까와는 다르게 현재는 보여줄 데이터가 없기 때문에 나는 에러이다.
이제 migration을 진행해주도록 하자.
하지만 아래와 같이 에러가 발생하며 css를 불러오지 못했다.
이유는 명확하지 않지만, 원인은 localhost:8000
이었다. localhost
만 사용하면 아래와 같이 css가 잘 적용되는 것을 볼 수 있다.
web-1
터미널에서 createsuperuser를 진행하였다. gunicorn
으로 가게 되고, 현재 gunicorn에는 css를 붙이는 것이 없기 때문에 위의 에러가 난 것일 것이다.nginx-1
은 nginx에 대한 로그를 자동으로 docker logs로 보내주고 있다. 해당 로그를 보는 법에 대해 작성하도록 하겠다. $ docker logs turtle_drf_backend-nginx-1
$ docker logs turtle_drf_backend-nginx-1 -f
>>> -f를 붙여 로그를 계속 확인할 수 있다.
docker logs nginx-1
은 보이는 것과 같이 정확한 이름이 아니다. docker ps
로 container를 확인하고 name을 가져와 입력하면 된다.turtle_drf_backend-nginx-1
이다.