본문 바로가기
IT & 데이터 사이언스/개인 프로젝트

[프로젝트] Django로 포트폴리오 사이트 만들기(3) - 운영 서버 환경 설정 및 사이트 배포하기

by 바른 호랑이 2024. 7. 11.
728x90
반응형

안녕하세요. 바른호랑이입니다.

나만의 포트폴리오 사이트 만들기를 목표로 지난번까지 개발환경에서 Django 프로젝트를 생성하고 Bootstrap을 적용한 후 커스터마이징하는 것까지 완료했습니다. 커스터마이징 부분은 개인적으로 수정해야 하는 부분이기에 크게 다루지 않고, 커스터마이징이 완료된 개발환경의 페이지를 실제로 VM을 생성하여 서비스하는 것까지 진행해 볼 예정입니다.

 

※ Django로 포트폴리오 사이트 만들기(2) - Django 프로젝트 생성 및 Bootstrap 적용하기

 

[프로젝트] Django로 포트폴리오 사이트 만들기(2) - Django 프로젝트 생성 및 Bootstrap 적용하기

안녕하세요. 바른호랑이입니다.나만의 포트폴리오 사이트 만들기를 목표로 지난 번까지 기본적인 Ubuntu설치 및 환경설정을 완료했었습니다. 기본적인 환경설정을 완료했기에 본격적으로 Django

data-is-power.tistory.com

 

개발 환경에서 서버의 개발이 완료했기에 개발 환경에서 사용한 패키지들을 동일 버전으로 맞춰서 설치를 해주는 과정을 진행했습니다. 추가적으로 생성한 Django 프로젝트의 settings에 개발환경과 운영환경을 구분하여 사용해 주기 위한 조치를 해줬었기에 가상환경 진입 시 사용할 명령어 코드집합을 작성하는 것도 필요하여 아래와 같이 필요한 코드들을 가진 파일들을 작성해 주었습니다.

# 현재 가상환경의 설치된 패키지들 정보 저장
pip freeze > requirements.txt

# 아래 코드로 enter_prod.sh 파일 생성(운영환경에서 가상환경 접속목적)

# load .bashrc
. ~/.bashrc

# activate virtual python environment
pyenv activate venv_portfolio

# add server execute file path
export DJANGO_SETTINGS_MODULE=config.settings.prod

위의 파일들을 생성한 후에는 운영 서버로 사용할 VM을 생성하고 작업을 위해 VS Code로 ssh를 활용하여 접속해 주었습니다. VS Code와 ssh를 활용하여 VM에 접속하는 방법은 아래 게시글과 같이 진행하였습니다.

 

※ VSCode Remote SSH 사용법

 

[환경설정] VSCode Remote SSH 사용법

안녕하세요. 바른호랑이입니다.이번 게시글에서는 VS Code를 기반으로 SSH를 사용하여 Linux 서버에 접근하는 방법에 대해서 알아볼 예정입니다.Linux가 설치된 가상머신(VM)이나 외부 컴퓨터를 접속

data-is-power.tistory.com

VM 생성 및 접속이 완료된 후에는 아래의 코드를 통해 운영 서버의 기본적인 환경설정을 진행해 주었습니다.

# Install git
sudo apt-get install git

# Install curl
sudo apt-get install curl

# Install pyenv
curl https://pyenv.run | bash

# Install packages
sudo apt-get update;
sudo apt-get install make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget llvm liblzma-dev \
libncurses-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev \
libffi-dev python3-tk

# Change time zone
sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
# PATH 등록(~/.bashrc 또는 ~/.bash_profile에 등록) - 등록 후 터미널 재실행
# pyenv path add
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

# pyenv-virtualenv add
eval "$(pyenv virtualenv-init -)"
# Install python on pyenv
pyenv install 3.12.4

# Create virtual env
pyenv virtualenv 3.12.4 venv_portfolio

필요한 패키지를 설치를 한 후에는 github에 올려놓은 코드들과 파일들을 서버환경에 가져와 설치해 주었습니다. github에 올려져 있는 필요한 코드 및 파일들을 가져온 후에는 "enter_prod.sh"파일로 가상환경에 접속한 이후 "requirements.txt"를 활용하여 개발환경과 동기화해주었습니다.

# Load git code and files
git clone https://github.com/Jeong-Beom/Portfolio.git
# Move portfolio folder
cd Portfolio

# Enter virtual environment
. enter_prod.sh
# Install packages
pip install -r requirements.txt

github에서 코드와 파일들을 가져와주었지만, 중요정보들을 저장한 .env와 같이 gitignore에 등록하여 원격 저장소에 올라와 있지 않은 파일들은 재작성해주어야 했습니다. ".env"파일을 아래와 같은 내용으로 생성해 주었습니다. 

# .env 파일 내용
SECRET_KEY={Django Secret Key}
IP={운영서버의 IP 주소}
DEBUG=False
DOMAIN={사용할 도메인}
DJANGO_SETTINGS_MODULE=config.settings.prod

다만 개발환경에 대한 settings관련 파일(local.py)은 작성을 완료했지만 운영환경에 대한 settings관련 파일(prod.py)은 작성을 하지 않았었기에 우선 개발 환경에서 사용할 settings 관련 파일을 아래와 같이 작성해 준 후 개발환경에서는 push를 운영환경에서는 pull 명령어를 통해 동기화를 해주었습니다.

from .base import *
from pathlib import Path

# Add for using .env info
import environ
import os

env = environ.Env(
    DEBUG=(bool, False)
)

environ.Env.read_env(os.path.join(BASE_DIR, '.env'))

ALLOWED_HOSTS = [os.environ.get('IP'), os.environ.get('DOMAIN')]
STATIC_ROOT = BASE_DIR / 'static/'
STATICFILES_DIRS = []
DEBUG = env('DEBUG', default=False)

동기화를 해준 후에 DB파일과 같이 Django를 사용하기 위해 필수적으로 필요하지만 gitignore에 등록되어 가져오지 못한 항목들을 서버환경에서 생성하기 위해 가상환경 진입 후 migrate 명령어를 사용해 주었습니다.

# 가상환경에 진입되어 있지 않은 상태라면 기존에 정해둔 가상환경 진입 파일을 실행
. enter_prod.sh

# 버전관리 툴에 적용된 Django의 필수 패키지들의 예외사항들 설치 및 적용
python manage.py migrate

migrate를 실행한 후에는 Django의 내장서버가 아닌 웹서버와 WSGI서버로 해당 사이트를 구동하기 위해서 웹서버(Nginx)와  WSGI서버(Gunicorn)를 설치해 주었습니다. 다만 웹서버와 WSGI서버는 개발환경에서는 필요하지 않기 때문에 운영환경에만 설치해주었습니다.

# Install web server
sudo apt install nginx
# Install web application server
pip install gunicorn

설치가 완료된 후에는 아래의 명령어를 통해 gunicorn이 정상적으로 설치가 되었는지 확인한 후 운영환경의 IP로 접속이 되는지 확인해 보았습니다. 속도와 효율성을 위해서 Unix Socket을 이용한 방식을 사용할 예정이었지만 Unix Socket 방식은 반드시 nginx와 같은 웹서버와 연동해서 사용해야 하기에 gunicorn의 정상작동여부를 확인하기 위해 8000번 포트를 임시적으로 열어 포트방식으로 우선 테스트를 진행해 보았습니다.

# gunicorn 구동 테스트
gunicorn --bind 0:8000 config.wsgi:application

아직 static 폴더의 사항들이 적용되지 않은 상태이기에 원하는 사이트가 원하는 모습으로 구동되고 있지는 않았지만, 정상적으로 접근도 되고, gunicorn이 정상적으로 작동하고 있는 것을 확인했기에 gunicorn을 종료해 주었습니다. 포트방식으로 정상 작동하는 것을 확인한 후에는 Unix Socket 방식도 정상 실행이 되는지는 확인을 해보기 위해 아래의 코드로 테스트를 진행해 보았습니다.

gunicorn --bind unix:/tmp/gunicorn.sock config.wsgi:application

Unix Socket 방식도 정상적으로 작동하는 것을 확인한 후에는 실제로 서비스할 때 사용할 파일을 만들기 위해 "/etc/systemd/system" 경로로 이동하여 관리자 권한으로 서비스 파일을 아래와 같이 작성해 주었습니다. gunicorn으로 서비스를 실행할 경우 Django의 settings를 prod.py로 적용하기 위해서 .env파일에 해당 경로를 지정해 주는 것이 필요한데, 이미 .env파일을 최초생성할 당시 "DJANGO_SETTINGS_MODULE=config.settings.prod" 코드를 넣어주었기에 추가적인 조치는 하지 않았습니다.

[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=imadmin
Group=imadmin
WorkingDirectory=/home/imadmin/Portfolio
EnvironmentFile=/home/imadmin/Portfolio/.env
ExecStart=/home/imadmin/.pyenv/versions/venv_portfolio/bin/gunicorn \
        --workers 2 \
        --bind unix:/tmp/gunicorn.sock \
        config.wsgi:application

[Install]
WantedBy=multi-user.target

서비스 파일을 작성한 후에는 해당 서비스 파일이 정상적으로 작동하는지 확인하기 위해 아래의 코드를 통해 확인하였습니다.

# Reload daemon
sudo systemctl daemon-reload

# Execute service file
sudo systemctl start portfolio.service

# Check service status
sudo systemctl status portfolio.service

정상적으로 서비스 파일까지 등록된 것을 확인한 후에는 운영 서버 환경이 재부팅되더라도 자동으로 재실행될 수 있게 아래의 코드를 실행해 주었습니다.

sudo systemctl enable mysite.service

gunicorn 서버 생성 및 실행까지 이상 없이 진행한 후에는 gunicorn 서버와 연동할 웹 서버인 nginx의 설정을 작성해 주었습니다. nginx 설정파일들이 위치한 "/etc/nginx/sites-available"로 이동한 후 "sudo nano portfolio" 명령어로 설정 파일을 생성 후 아래의 코드들을 입력하여 작성해 주었습니다.

server {
        listen 80;
        server_name {운영 서버의 IP 주소};

        location = /favicon.ico { access_log off; log_not_found off; }

        location /static {
                alias /home/imadmin/Portfolio/static;
        }

        location / {
                include proxy_params;
                proxy_pass http://unix:/tmp/gunicorn.sock;
        }
}

설정 파일을 생성 및 작성을 완료한 이후에는 설정 파일을 활성화하기 위해 "/etc/nginx/sites-enabled/"로 이동한 후 기존에 기본 값으로 설정되어 있는 "default"파일을 삭제하고 새로 생성한 "portfolio"파일을 아래의 명령어로 생성해 주었습니다.

sudo ln -s /etc/nginx/sites-available/portfolio

설정을 완료한 이후에는 아래의 코드로 nginx를 재시작하여 변경된 사항을 적용해 주었고, 적용완료 후 80번 포트(http 통신 시에 일반적으로 사용하는 포트로 별도로 입력을 안 해줘도 기본 값으로 적용됨.)를 열어준 후 서버 IP 주소로 접속하여 사이트가 정상적으로 작동하는지 확인해 보았습니다.

sudo systemctl restart nginx

nginx설정 및 재시작까지 완료하니 개발 환경과 동일하게 웹사이트가 작동하는 것을 확인할 수 있었습니다. 일반적인 페이지들은 정상적으로 작동하는 것을 확인했지만, Django의 내장된 개발 서버가 아닌 nginx로 구동 시 admin 페이지의 경우 별도의 처리를 해주지 않으면 static 관련 파일들을 읽지 못하기 때문에 해당 부분과 관련된 사항들을 처리해 주었습니다. 기본적으로 운영 서버 환경의 settings 파일인 prod.py에 아래와 같은 내용을 추가해 주는 것이 필요한데, 이는 이미 prod.py파일을 최초 작성할 당시 적용을 해주었기에 해당 부분은 생략하고 아래의 명령어를 실행하여 admin 페이지와 관련된 static 파일들을 nginx에서 참조하는 static 경로에 복사해 주었습니다.

# Nginx에 등록한 정적 파일 위치 디렉터리로 STATIC_ROOT도 동일하게 설정
STATIC_ROOT = BASE_DIR / 'static/'

# base.py 파일에 등록된 STATICFILES_DIRS 항목과의 충돌을 피하기 위해 설정
STATICFILES_DIRS = []
# admin 페이지에 사용할 static 파일들 복사
python manage.py collectstatic

설정 전후

admin 페이지까지 static이 적용되게끔 작성을 완료한 후에는 항상 IP를 통해 접속하게 하고 싶지 않았기 때문에 사전에 구매해 둔 도메인을 운영 서버 환경에 적용시켜 주었습니다. 적용 방법은 아래 게시물과 동일한 과정을 거쳐 진행해 주었습니다.

 

※ Azure에서 Custom Domain 등록하기 

 

[환경설정] Azure에서 Custom Domain 등록하기

안녕하세요. 바른호랑이입니다.이번 게시글에서는 Azure에서 Custom Domain을 등록해 보는 방법에 대해 알아볼 예정입니다.DNS란 Domain Name System의 약어로 호스트의 Domain Name(www.example.com)을 네트워크

data-is-power.tistory.com

도메인 서버까지 적용한 후에는 최종적으로 SSL을 적용해 주었으며, 무료로 이용할 수 있는 Let's Encrypt 서비스를 이용하였습니다. (Let's Encrypt의 경우 90일 동안 유효하므로 일정 주기마다 인증서를 갱신해줘야 합니다.) 아래의 명령어를 통해 certbot을 설치해 주었으며, 설치를 완료한 후에는 인증서를 등록해 주었습니다. 등록을 완료한 후에는 "/etc/letsencrypt/live/" 경로에 정상적으로 인증서가 생성이 되었는지 확인해 주었습니다.(조회를 위해서는 해당 폴더에 조회 권한 부여가 필요해서 "sudo chmod 777 /etc/letsencrypt/live/" 명령어를 사용했습니다.)

# Install certbot
sudo apt install certbot
sudo apt install python3-certbot-nginx

# Register certbot certification
sudo certbot certonly --nginx
# 폴더 및 파일 권한 확인
ls -al

# 권한부여 예시(소유자, 그룹, 게스트에게 읽기, 쓰기, 실행 권한 전부 부여) 
sudo chmod 777 {파일경로}

인증서가 자동으로 생성된 것을 확인한 후에는 nginx에 해당 인증서를 적용해 주기 위해 nginx 파일을 아래와 같이 수정해 주었습니다. 변경 사항을 적용하기 위해 "sudo systemctl restart nginx.service" 명령어를 실행한 후 443번 포트를 오픈하고, 사이트에 정상적으로 접속이 되는지 확인했습니다.

server {
        listen 80;
        server_name introducemyself.me;
        rewrite        ^ https://$server_name$request_uri? permanent;
}

server {
        listen 443 ssl;
        server_name introducemyself.me;

        ssl_certificate /etc/letsencrypt/live/introducemyself.me/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/introducemyself.me/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot

        location = /favicon.ico { access_log off; log_not_found off; }

        location /static {
                alias /home/imadmin/Portfolio/static;
        }

        location / {
                include proxy_params;
                proxy_pass http://unix:/tmp/gunicorn.sock;
        }
}

위와 같이 SSL까지 적용하는 것으로 나만의 Portfolio를 만들어 보았습니다. 

 

※ 나만의 Portfolio 사이트

 

Portfolio

Loading Your message has been sent. Thank you! Send Message

introducemyself.me

 

※ Github

 

GitHub - Jeong-Beom/Portfolio: This is repository for making portfolio.

This is repository for making portfolio. Contribute to Jeong-Beom/Portfolio development by creating an account on GitHub.

github.com

 

728x90
반응형

댓글