정적 파일 S3로 이동
django-storages, Amazon S3를 이용한다.
django-storages, Amazon S3
boto3를 사용하는 것을 강력히 추천한다.
$ pip install django-storages
# settings.py
DEBUG = os.environ.get('MODE') == 'DEBUG'
STORAGE_S3 = os.environ.get('STORAGE') == 'S3' or DEBUG is False
print('DEBUG: {}'.format(DEBUG))
print('STORAGE_S3 : {}'.format(STORAGE_S3))
# AWS
AWS_ACCESSS_KEY_ID = config['aws']['access_key_id']
AWS_SECRET_ACCESS_KEY = config['aws']['secret_access_key']
AWS_STORAGE_BUCKET_NAME = config['aws']['s3_storage_bucket_name']
AWS_S3_CUSTOM_DOMAIN = '{}.s3.amazonaws.com'.format(AWS_STORAGE_BUCKET_NAME)
# Static Setting
STATIC_DIR = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = (
STATIC_DIR,
)
if STORAGE_S3:
# To use boto3 set
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
# collectstatic to automatically put your static files
# in your s3 bucket
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATIC_URL = 's3.{region}.amazonaws.com/{bucket_name}/'.format(
region=config['aws']['s3_region'],
bucket_name=config['aws']['s3_storage_bucket_name']
)
else:
STATIC_ROOT = os.path.join(ROOT_DIR, 'static_root')
STATIC_URL = '/static/'
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'storages',
'member',
]
settings_common.json
파일에 설정 값을 추가한다.
"aws": {
"access_key_id": "YOUR_ID",
"secret_access_key": "YOUR_KEY",
"s3_storage_bucket_name": "YOUR_BUCKET_NAME"
}
키 값은 아래의 명령 혹은 AWS에 접속해 확인 할 수 있다.
$ cd ~/.aws
$ cat credentials
shell 스크립트 작성
$ vi ~/.scripts/manages3
#!/bin/zsh
MODE='DEBUG' STORAGE='S3' ./manage.py $*
# 작성 후 권한 변경
$ chmod 755 ~/.scripts/manages3
# 실행은 아래의 명령으로 한다.
$ manages3 collectstatic
# AWS S3에 접속해 정상적으로 업로드 된 것을 확인
# 아래와 같이 서버를 실행하면,
# local의 이미지 노출
$ manage runserver
DEBUG: True
STORAGE_S3 : False
# aws s3 이미지 노출
$ manages3 runserver
DEBUG: True
STORAGE_S3 : True
배포
$ scp
$ pip install -r requirements.txt
$ ./manage.py collectstatic
$ reset
서버 페이지에 들어가 이미지가 정상노출을 확인한다.
하지만 admin page에서 프로필 사진을 등록하면 에러가 발생한다.
에러 확인 하기
아래와 같이 등록해준다.
$ sudo vi /etc/uwsgi/sites/app.ini
logger = file:/tmp/uwsgi.log
logger = internalservererror file:/tmp/uwsgi500.log
또한, 아래와 같이 else
에 Media path
를 추가한다.
# settings.py
if STORAGE_S3:
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATIC_URL = 's3.{region}.amazonaws.com/{bucket_name}/'.format(
region=config['aws']['s3_region'],
bucket_name=config['aws']['s3_storage_bucket_name']
)
else:
STATIC_ROOT = os.path.join(ROOT_DIR, 'static_root')
STATIC_URL = '/static/'
# Media path
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(ROOT_DIR, 'media')
# urls.py
if settings.DEBUG and settings.STORAGE_S3 is False:
urlpatterns += static(
settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT
)
에러를 수정하기 위해 AWS_S3_SIGNATURE_VERSION
을 추가한다.
# settings.py
AWS_S3_HOST = 's3.{}.amazonaws.com'.format(config['aws']['s3_region'])
AWS_S3_SIGNATURE_VERSION = config['aws']['s3_signature_version']
AWS_S3_CUSTOM_DOMAIN = '{}.s3.amazonaws.com'.format(AWS_STORAGE_BUCKET_NAME)
서버에 다시 배포하여 확인한다.
$ scp
$ pip install -r requirements.txt
$ reset
admin page에서 프로필 사진이 정상적으로 등록된다.
static 경로로 올리기
# settings.py
if STORAGE_S3:
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
# Static files
# collectstatic 요청은 STATICFILES_STORAGE 처리
STATICFILES_STORAGE = 'deploy_ec2.storages.StaticStorage'
STATICFILES_LOCATION = 'static'
STATIC_URL = 'https://{custom_domain}/{staticfiles_location}/'.format(
custom_domain=AWS_S3_CUSTOM_DOMAIN,
staticfiles_location=STATICFILES_LOCATION,
)
storages.py
를 만들고 아래의 내용을 추가한다.
# storages.py
from django.conf import settings
from storages.backends.s3boto3 import S3Boto3Storage
class StaticStorage(S3Boto3Storage):
location = settings.STATICFILES_LOCATION
배포
# Local
$ MODE='DEBUG' STORAGE='S3' ./manage.py collectstatic
$ scp
# Server
$ ./manage.py collectstatic
$ reset
media 경로로 올리기
# settings.py
if STORAGE_S3:
# Static files
# collectstatic 요청은 STATICFILES_STORAGE 처리
# ...
# Media files
DEFAULT_FILE_STORAGE = 'deploy_ec2.storages.MediaStorage'
MEDIAFILES_LOCATION = 'media'
MEDIA_URL = 'https://{custom_domain}/{mediafiles_location}/'.format(
custom_domain=AWS_S3_CUSTOM_DOMAIN,
mediafiles_location=MEDIAFILES_LOCATION,
)
# storages.py
class MediaStorage(S3Boto3Storage):
location = settings.MEDIAFILES_LOCATION
같은 이름의 파일 오버라이트 문제 해결
# storages.py
from django.conf import settings
from storages.backends.s3boto3 import S3Boto3Storage
class StaticStorage(S3Boto3Storage):
location = settings.STATICFILES_LOCATION
file_overwrite = True
class MediaStorage(S3Boto3Storage):
location = settings.MEDIAFILES_LOCATION
file_overwrite = False
AWS RDS
데이터베이스 서버를 하나 만들어준다고 생각하자.
DB 생성
launch Instance > Postgresql 선택 > DEV/TEST > Next
- Only show options that are eligible for RDS Free Tier 체크
- Settings (입력)
- DB Instance Identifier
- Master Username
- Master Password
- Confirm Password
Next
- Database Options
- Database Name : deploy_ec2
Security Group 관리
- 이름과 설명만 적고 새로운 Security Group 추가한다.
DB생성이 되면, Instance Actions > Modify 로 이동한다.
- Network & Security > Security Group을 새로 생성한 것으로 변경한다.
- 그 후 기본으로 생생된 Security Group을 삭제한다.
생성한 Security Group에 Inbound 추가
- Type : PostgreSQL
- Protocol : TCP
- Port Range : 5432
- Source : MyIP
PgAdimin 연결
Servers > Create > Servers 클릭
- General
- Name : RDS - DeployEc2
- Connection
- Host : wps-deploy.cgzidgqkn5zw.ap-northeast-2.rds.amazonaws.com
- Maintanace database : deploy_ec2
- User name : hm
- Password : Your_Password
장고와 연결
settings_local.json
파일에 추가한다.
"db-rds": {
"engine": "django.db.backends.postgresql_psycopg2",
"name": "deploy_ec2",
"user": "hm",
"password": "YOUR_Password",
"host": "wps-deploy.cgzidgqkn5zw.ap-northeast-2.rds.amazonaws.com",
"port": "5432"
}
# settings.py
DB_RDS = os.environ.get('DB') == 'RDS'
print('DB_RDS : {}'.format(DB_RDS))
if DEBUG and DB_RDS:
# RDS DB로 접속해 테스트
config_db = config['db_rds']
else:
config_db = config['db']
DATABASES = {
'default': {
'ENGINE': config_db['engine'],
'NAME': config_db['name'],
'USER': config_db['user'],
'PASSWORD': config_db['password'],
'HOST': config_db['host'],
'PORT': config_db['port'],
}
}
$ MODE='DEBUG' DB='RDS' STORAGE='S3' ./manage.py migrate
$ MODE='DEBUG' DB='RDS' STORAGE='S3' ./manage.py runserver
배포
배포전에 데이터베이스 삭제
# Server
sudo apt-get remove postgresql
# Local
$ scp
admin 사이트에 접속하면 안된다. Security Group에 inbound를 추가해야하 한다.
wps-deploy-rds에 다음과 같이 추가한다.
- Type : PostgreSQL
- Protocol : TCP
- Port Range : 5432
- Source : sg라고 치면 Security Group 모두 나온다. 여기서 EC2의 Security Group을 추가한다.
Admin 페이지에 로그인하기 위해 슈퍼유저를 만든다.
# Local
$ MODE='DEBUG' DB='RDS' STORAGE='S3' ./manage.py createsuperuser
Elastic Beanstalk
Elastic Beanstalk가 용량 프로비저닝, 로드 밸런싱, Auto Scaling, 애플리케이션 상태 모니터링에 대한 배포 정보를 자동으로 처리합니다.
Elastic Beanstalk가 자동으로 해주는 것을 나중에 개별적으로 다 다뤄보는 것이 좋다. 로드 밸런싱은 쉬워서 금방할 수 있고, 모니터링은 어렵지만 공부하는게 좋다.
과제
- 초보를 위한 도커 안내서 해보기 (이미지 저장소 제외)