데이터베이스 변경, Postgresql

  • postgresql 설치
  • pgAdmin4 설치

프로젝트 세팅

  • settings_deploy.json 추가
{
  "django": {
    "allowed_hosts": [
      ".devlim.net",
      ".ap-northeast-2.compute.amazonaws.com"
    ]
  }
}
  • settings_local.json에 내용 추가
{
  "django": {
    "allowed_hosts": [
      "*"
    ]
  },
  "db": {
    "engine": "django.db.backends.postgresql_psycopg2",
    "name": "",
    "user": "",
    "password": "",
    "host": "localhost",
    "port": "5432"
  }
}

Postgresql 데이터베이스 생성

Shell에서 postgresql 슈퍼유저를 생성 후, 데이터베이스 생성한다.

$ brew services start postgresql

# 유저 생성
# createuser -s hm
# 유저 삭제
# dropuser hm

# -s : 슈퍼 유저
# -P: 비밀번호 설정
$ createuser -s -P hm

# 데이터베이스 생성
# 데이터베이스 이름 : depoly_ec2
$ createdb depoly_ec2 --owner=hm

Pgadmin에서 다음과 같이 등록한다.

  • create-server > General
    • Name : Localhost
  • Connection
    • Host name/address : localhost
    • Port: 5432
    • User name: hm

Django와 postgresql 연결

# settings_local.json
  "db": {
    "engine": "django.db.backends.postgresql_psycopg2",
    "name": "deploy_ec2",
    "user": "hm",
    "password": "Your_Password",
    "host": "localhost",
    "port": "5432"
  }
# settings.py
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'],
    }
}
$ mig (makemigrations + migrate)
django.core.exceptions.ImproperlyConfigured: Error loading psycopg2 module: No module named 'psycopg2'

$ pip install psycopg2
$ mig (makemigrations + migrate)

DEBUG 환경

# settings.py
DEBUG = os.environ.get('MODE') == 'DEBUG'
print('DEBUG: {}'.format(DEBUG))
# 환경변수 확인
$ env

$ cd deploy_ec2/django_app
$ MODE='DEBUG' ./manage.py runserver

Shell 스크립트 작성

$ cd ~/
$ mkdir .scripts
$ cd .scripts
$ vi manage
// 파이썬 shell 스크립트를 만들고 싶으면
// 아래의 경로를 파이썬으로 바꾼다.
#!/usr/local/bin/zsh

// $1 : 키워드 인자, 첫번째 인자를 여기에 받는다.
// MODE='DEBUG' ./manage.py $1

// $* : 모든 인자를 받도록 변경
MODE='DEBUG' ./manage.py $*
# 모든 사람이 파일을 읽고 실행 가능
# 쓰기는 불가
chmod 755 ~/.scripts/manage

path 설정을 한다.

$ vi ~/.zshrc

# My Scripts
export SCRIPTS_PATH="/Users/limhm/.scripts"
export PATH="$PATH:$SCRIPTS_PATH"

# 작동 확인
$ source ~/.zshrc
$ manage
/Users/limhm/.scripts/manage:2: no such file or directory: ./manage.py

배포

# settings.py
# 조건문 추가
CONFIG_FILE = os.path.join(CONF_DIR, 'settings_local.json' if DEBUG else 'settings_deploy.json')
# Local
$ deploy_ec2
$ con-ec2
# Server
$ cd /srv/app/django_app
$ ./manage.py makemigrations
$ pip install -r requirements.txt

# Postgresql 설치
$ sudo apt-get update
$ sudo apt-get install postgresql postgresql-contrib

$ sudo -u postgres createuser -s -P hm
$ sudo -u postgres createdb depoly_ec2 --owner=hm

Static 파일 배포

프로젝트 수정

static, templates 폴더 생성

# settings.py
TEMPLATES_DIR = os.path.join(BASE_DIR, 'templates')

STATIC_DIR = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
    STATIC_DIR,
)

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            TEMPLATES_DIR
        ],
        # ...
    }
]
# views.py
from django.shortcuts import render


def index(reqeust):
    return render(reqeust, 'index.html')
# 스크립트를 작성했으므로 아래와 같이 실행
$ manage runserver

배포

# Local
$ deploy_ec2
$ con-ec2

서버 사이트, admin 사이트 접속하면, 이미지나 css가 작동하지 않는다.

현재는 static 파일을 동적으로 연결하고 있는 상태이다.

Nginx를 이용해 static 파일들을 따로 처리

다음과 같은 구조로 돌아갈 수있도록 변경한다.

- Nginx > URL ~/static > folder
or
- Nginx > URL ~/other > uWSGI

folder에 모으기

하나의 폴더로 모아주는 명령어 ./manage.py collectstatic를 이용한다.

우선 로컬에서 작업한다. (모든 작업은 로컬에서 먼저 수행)

$ manage collectstatic
DEBUG: True

You have requested to collect static files at the destination
location as specified in your settings.

This will overwrite existing files!
Are you sure you want to do this?

Type 'yes' to continue, or 'no' to cancel: yes

raise ImproperlyConfigured("You're using the staticfiles app "
django.core.exceptions.ImproperlyConfigured: You're using the staticfiles app without having set the STATIC_ROOT setting to a filesystem path.

static_root를 추가한다.

# settings.py
STATIC_ROOT = os.path.join(ROOT_DIR, 'static_root')

다시 명령어를 수행하면 잘 되는 것을 볼 수 있다.

$ manage collectstatic

# git에 관리할 때, static_root 폴더는 제외해야 한다.
$ vi .gitignore
static_root/

서버에 다시 배포한다.

# Local
$ deploy_ec2
$ con-ec2

Nginx static 설정

# 서버에서도 다시 한번 실행한다.
$ ./manage.py collectstatic

0 static files copied to '/srv/app/static_root', 64 unmodified.
$ sudo systemctl restart uwsgi.service

nginx 설정 파일로 이동해 추가한다.

$ sudo vi /etc/nginx/sites-available/app
# root URL로 요청올 때 설정
location / {
uwsgi_pass      unix:///tmp/app.sock;
include         uwsgi_params;
}

# /static/ URL로 요청올 때 설정
location /static/ {
alias /srv/app/static_root/;
}
# nginx 재시작
$ sudo systemctl restart nginx.service

정리

서버 구조

데이터베이스 명령 정리

# macOS에서는 sudo -u postgres 입력 불필요

# 유저생성
$ sudo -u postgres createuser -s -P <username>

# 유저삭제
$ sudo -u postgres dropuser <username>

# 데이터베이스 삭제
$ sudo -u postgres dropdb <db name>

# 데이터베이스 생성
$ sudo -u postgres createdb <db name> owner=<owner name>

Media 배포

데이터베이스

마이그레이션 에러가 발생하니, 데이터베이스를 삭제 후 다시 생성한다.

$ dropdb depoly_ec2
$ createdb deploy_ec2 --owner=hm
$ pip install pillow

프로젝트 member app 추가

$ manage startapp member
# member/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models


class MyUser(AbstractUser):
    img_profile = models.ImageField(upload_to='user', blank=True)
# admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import ugettext, ugettext_lazy as _

from member.models import MyUser


class MyUserAdmin(UserAdmin):
    # UserAdmin에서 복사 후, img_profile 추가
    fieldsets = (
        (None, {'fields': ('username', 'password', 'img_profile')}),
        (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
        (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
                                       'groups', 'user_permissions')}),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )


admin.site.register(MyUser, MyUserAdmin)
# settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'member',
]

AUTH_USER_MODEL = 'member.MyUser'
$ ./manage.py makemigrations
$ ./manage.py migrate
$ ./manage.py createsuperuser
$ manage runserver

Media 설정 추가

# settins.py
# Media path
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(ROOT_DIR, 'media')

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            TEMPLATES_DIR
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                # MEDIA_URL 변수 사용
                'django.template.context_processors.media',
                # ...
            ],
        },
    },
]
# urls.py
if settings.DEBUG:
    urlpatterns += static(
        settings.MEDIA_URL,
        document_root=settings.MEDIA_ROOT
    )

Admin 사이트접속 후 사진을 올리고, 정상 출력 확인

배포

# Local
$ deploy_ec2
$ con-ec2
# Server
$ cd /srv/app
$ ip install -r requirements.txt

$ sudo -u postgres dropdb depoly_ec2
$ sudo -u postgres createdb deploy_ec2 owner=hm
$ ./manage.py makemigrations
$ ./manage.py createsuperuser

# reset alias 설정
$ sudo systemctl restart nginx.service uwsgi.service

서버 사이트접속하여 로그인은 되지만, 이미지가 업로드 되지 않는다.

하지만 에러메시지가 뜨지 않고 500 에러만 나오므로, settings.py에 DEBUG=True로 설정한다. 그러면 자세한 에러 메시지를 출력할 수 있다.

에러 메시지를 보면, 권한이 없는 문제이므로 아래와 같이 진행한다.

$ l
drwxr-xr-x 3 ubuntu ubuntu 4.0K Mar  8 07:34 media

$ sudo rm -rf media
$ mkdir media
$ sudo chmod 777 media

이제 정상적으로 업로드가 되나, 이미지 파일이 보이지 않는다.

Nginx 설정 추가

$ sudo vi /etc/nginx/sites-available/app
location /media/ {
	alias /srv/app/media/;
}

이미지가 정상적으로 출력되는 것을 확인 할 수 있다.

정적 파일관리, S3

버킷 = 저장소

IAM 유저에 권한을 부여해 shell 명령을 통해 생성할 수 있다.

  • IAM > Users 클릭 > Add permission > Attach existing policies directly > s3 검색 > AmazonS3FullAccess 체크

boto3

파이썬에서 AWS S3 및 EC2를 사용할수있는 라이브러리

$ cd deploy_ec2
$ pip install boto3
$ python
>>> import boto3
>>> session = boto3.Session(profile_name='default')
>>> client = session.client('s3')
>>> client.create_bucket(Bucket='wps-deploy', CreateBucketConfiguration={'LocationConstraint': 'ap-northeast-2'})
{'ResponseMetadata': {'HTTPStatusCode': 200, 'HostId': '...', 'HTTPHeaders': {'x-amz-id-2': '...', 'location': 'http://wps-deploy.s3.amazonaws.com/', 'server': 'AmazonS3', 'content-length': '0', 'x-amz-request-id': '...', 'date': 'Wed, 08 Mar 2017 08:49:36 GMT'}, 'RetryAttempts': 0, 'RequestId': '...'}, 'Location': 'http://wps-deploy.s3.amazonaws.com/'}

생성된 버킷은 S3 페이지에서 확인할 수 있다.

# profile_name 확인법
$ cd ~/.aws
$ l
$ cat credentials
[default]
...