웹사이트 검색

Debian 11에서 Postgres, Nginx 및 Gunicorn으로 Django를 설정하는 방법


소개

Django는 Python 애플리케이션이나 웹 사이트를 시작하는 데 도움이 되는 강력한 웹 프레임워크입니다. Django에는 로컬에서 코드를 테스트하기 위한 개발 서버가 포함되어 있지만 생산과 관련된 약간의 작업이라도 더 안전하고 강력한 웹 서버가 필요합니다.

이 가이드에서는 Django 애플리케이션을 지원하고 제공하기 위해 Debian 11에 일부 구성 요소를 설치하고 구성합니다. 기본 SQLite 데이터베이스를 사용하는 대신 PostgreSQL 데이터베이스를 설정하게 됩니다. 애플리케이션과 인터페이스하도록 Gunicorn 애플리케이션 서버를 구성합니다. 그런 다음 Nginx가 Gunicorn에 대한 역방향 프록시를 설정하여 앱을 제공하기 위한 보안 및 성능 기능에 액세스할 수 있습니다.

전제 조건 및 목표

이 가이드를 완료하려면 기본 방화벽이 있는 새로운 Debian 11 서버 인스턴스와 구성된 sudo 권한이 있는 루트가 아닌 사용자가 있어야 합니다. 초기 서버 설정 가이드를 실행하여 이를 설정하는 방법을 배울 수 있습니다.

가상 환경에서 Django를 설치하게 됩니다. 프로젝트에 특정한 환경에 Django를 설치하면 프로젝트와 해당 요구 사항을 별도로 처리할 수 있습니다.

데이터베이스와 애플리케이션을 가동하고 실행하면 Gunicorn 애플리케이션 서버를 설치하고 구성합니다. 이는 애플리케이션에 대한 인터페이스 역할을 하여 HTTP의 클라이언트 요청을 애플리케이션이 처리할 수 있는 Python 호출로 변환합니다. 그런 다음 고성능 연결 처리 메커니즘과 보안 기능을 활용하기 위해 Gunicorn 앞에 Nginx를 설정합니다.

시작하자.

데비안 리포지토리에서 패키지 설치

프로세스를 시작하려면 Debian 리포지토리에서 필요한 모든 항목을 다운로드하여 설치합니다. 나중에 Python 패키지 관리자 pip를 사용하여 추가 구성 요소를 설치합니다.

먼저 로컬 apt 패키지 인덱스를 업데이트한 다음 패키지를 다운로드하고 설치해야 합니다.

  1. sudo apt update
  2. sudo apt install python3-venv python3-dev libpq-dev postgresql postgresql-contrib nginx curl

이 명령은 Python 프로젝트를 위한 가상 환경을 만드는 도구, 나중에 Gunicorn을 빌드하는 데 필요한 Python 개발 파일, Postgres 데이터베이스 시스템과 상호 작용하는 데 필요한 라이브러리, Nginx 웹 서버를 설치합니다.

PostgreSQL 데이터베이스 및 사용자 생성

이제 Django 애플리케이션을 위한 데이터베이스 및 데이터베이스 사용자를 바로 생성할 수 있습니다.

기본적으로 Postgres는 로컬 연결에 "피어 인증\이라는 인증 체계를 사용합니다. 기본적으로 이는 사용자의 운영 체제 사용자 이름이 유효한 Postgres 사용자 이름과 일치하는 경우 해당 사용자가 추가 인증 없이 로그인할 수 있음을 의미합니다.

Postgres 설치 중에 postgres라는 운영 체제 사용자가 postgres PostgreSQL 관리 사용자에 해당하도록 생성되었습니다. 관리 작업을 수행하려면 이 사용자를 사용해야 합니다. sudo를 사용하고 -u 옵션과 함께 사용자 이름을 전달할 수 있습니다.

다음을 입력하여 대화형 Postgres 세션에 로그인합니다.

  1. sudo -u postgres psql

요구 사항을 설정할 수 있는 PostgreSQL 프롬프트가 표시됩니다.

먼저 프로젝트용 데이터베이스를 생성합니다.

  1. CREATE DATABASE myproject;

참고: 모든 Postgres 문은 세미콜론으로 끝나야 하므로 문제가 발생하는 경우 명령이 세미콜론으로 끝나야 합니다.

다음으로 프로젝트에 대한 데이터베이스 사용자를 생성합니다. 보안 암호를 선택했는지 확인하십시오.

  1. CREATE USER myprojectuser WITH PASSWORD 'password';

그런 다음 방금 생성한 사용자에 대한 몇 가지 연결 매개변수를 수정합니다. 이렇게 하면 연결이 설정될 때마다 올바른 값을 쿼리하고 설정할 필요가 없도록 데이터베이스 작업 속도가 빨라집니다.

기본 문자 인코딩을 Django가 예상하는 UTF-8로 설정합니다. 또한 기본 트랜잭션 격리 체계를 커밋되지 않은 트랜잭션에서 읽기를 차단하는 "커밋된 읽기\로 설정합니다. 마지막으로 시간대를 설정합니다. 기본적으로 Django 프로젝트는 UTC를 사용하도록 설정됩니다. 다음은 모두 Django 프로젝트 자체의 권장 사항입니다.

  1. ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
  2. ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
  3. ALTER ROLE myprojectuser SET timezone TO 'UTC';

이제 새 사용자에게 새 데이터베이스를 관리할 수 있는 액세스 권한을 부여할 수 있습니다.

  1. GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

완료되면 다음을 입력하여 PostgreSQL 프롬프트를 종료합니다.

  1. \q

Postgres는 이제 Django가 데이터베이스 정보에 연결하고 관리할 수 있도록 설정되었습니다.

프로젝트를 위한 Python 가상 환경 만들기

이제 데이터베이스가 준비되었으므로 나머지 프로젝트 요구 사항을 가져올 수 있습니다. 가상 환경 내에 Python 요구 사항을 설치합니다.

먼저 프로젝트 파일을 보관할 수 있는 디렉터리를 만들고 변경합니다.

  1. mkdir ~/myprojectdir
  2. cd ~/myprojectdir

프로젝트 디렉터리 내에서 다음을 입력하여 Python 가상 환경을 만듭니다.

  1. python3 -m venv myprojectenv

이렇게 하면 myprojectdir 디렉토리 내에 myprojectenv라는 디렉토리가 생성됩니다. 내부에는 패키지를 관리하기 위해 로컬 버전의 Python과 로컬 버전의 pip가 설치됩니다. 이 가상 환경 구조를 사용하여 생성하려는 모든 프로젝트에 대해 격리된 Python 환경을 설치하고 구성할 수 있습니다.

프로젝트의 Python 요구 사항을 설치하기 전에 가상 환경을 활성화해야 합니다. 다음을 입력하면 됩니다.

  1. source myprojectenv/bin/activate

이제 Python 가상 환경 내에서 작업 중임을 나타내도록 프롬프트가 변경되어야 합니다. 다음과 같이 표시됩니다. (myprojectenv)user@host:~/myprojectdir$.

가상 환경이 활성화된 상태에서 pip의 로컬 인스턴스와 함께 Django, Gunicorn 및 psycopg2 PostgreSQL 어댑터를 설치합니다.

참고: 가상 환경이 활성화되면(프롬프트 앞에 (myprojectenv)가 있는 경우) pip3 대신 pip를 사용하십시오. Python 3을 사용하고 있습니다. 가상 환경의 도구 사본 이름은 Python 버전에 관계없이 항상 pip입니다.

  1. pip install django gunicorn psycopg2-binary

이제 Django 프로젝트를 시작하는 데 필요한 모든 소프트웨어가 있어야 합니다.

새 Django 프로젝트 생성 및 구성

Python 구성 요소가 설치되면 이제 실제 Django 프로젝트 파일을 만들 수 있습니다.

장고 프로젝트 생성

이미 프로젝트 디렉토리가 있으므로 여기에 파일을 설치하도록 Django에 지시합니다. 실제 코드가 포함된 두 번째 수준의 디렉터리를 생성하고 이 디렉터리에 관리 스크립트를 배치합니다. 이것의 핵심은 Django가 현재 디렉토리에 상대적인 결정을 내리도록 허용하는 대신 디렉토리를 명시적으로 정의한다는 것입니다.

  1. django-admin startproject myproject ~/myprojectdir

이 시점에서 프로젝트 디렉터리(이 예제에서는 ~/myprojectdir)에 다음 콘텐츠가 있어야 합니다.

  • ~/myprojectdir/manage.py: Django 프로젝트 관리 스크립트.
  • ~/myprojectdir/myproject/: Django 프로젝트 패키지. 여기에는 __init__.py, settings.py, urls.py, asgi.pywsgi.py 파일.
  • ~/myprojectdir/myprojectenv/: 이전에 만든 가상 환경 디렉터리입니다.

프로젝트 설정 조정

새로 만든 프로젝트 파일로 가장 먼저 해야 할 일은 설정을 조정하는 것입니다. nano 또는 선호하는 텍스트 편집기를 사용하여 설정 파일을 엽니다.

  1. nano ~/myprojectdir/myproject/settings.py

ALLOWED_HOSTS 지시문을 찾아서 시작하십시오. Django 인스턴스에 연결하는 데 사용할 수 있는 서버 주소 또는 도메인 이름 목록을 정의합니다. 이 목록에 없는 호스트 헤더가 있는 수신 요청은 예외를 발생시킵니다. Django는 특정 클래스의 보안 취약성을 방지하기 위해 이를 설정하도록 요구합니다.

대괄호 안에 Django 서버와 연결된 IP 주소 또는 도메인 이름을 나열합니다. 각 항목은 쉼표로 구분된 항목과 함께 인용 부호 안에 나열되어야 합니다. 전체 도메인 및 하위 도메인에 대한 요청을 원하는 경우 항목 시작 부분에 마침표를 추가하십시오. 아래 스니펫에는 시연에 사용되는 몇 가지 주석 처리된 예가 있습니다.

참고: 로컬 Nginx 인스턴스를 통해 연결을 프록시할 것이므로 localhost를 옵션 중 하나로 포함해야 합니다.

. . .
ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . ., 'localhost']

그런 다음 데이터베이스 액세스를 구성하는 섹션을 찾습니다. DATABASES로 시작합니다. 파일의 구성은 SQLite 데이터베이스용입니다. 우리 프로젝트를 위한 PostgreSQL 데이터베이스를 이미 생성했으므로 설정을 조정해야 합니다.

PostgreSQL 데이터베이스 정보로 설정을 변경하십시오. pip와 함께 설치한 psycopg2 어댑터를 사용하도록 Django에 지시합니다. 데이터베이스 이름, 데이터베이스 사용자 이름, 데이터베이스 사용자 암호를 제공한 다음 데이터베이스가 로컬 컴퓨터에 있음을 지정해야 합니다. PORT 설정을 빈 문자열로 둘 수 있습니다.

. . .

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'myproject',
        'USER': 'myprojectuser',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '',
    }
}

. . .

그런 다음 파일 맨 아래로 이동하여 정적 파일을 배치해야 하는 위치를 나타내는 설정을 추가합니다. 이는 Nginx가 이러한 항목에 대한 요청을 처리할 수 있도록 하기 위해 필요합니다. 다음 줄은 Django가 기본 프로젝트 디렉토리의 static이라는 디렉토리에 배치하도록 지시합니다.

. . .
STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

import os
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')

완료되면 파일을 저장하고 닫습니다. nano를 사용하는 경우 Ctrl+X를 누른 다음 메시지가 표시되면 Y를 누르고 Enter를 누릅니다.

초기 프로젝트 설정 완료

이제 관리 스크립트를 사용하여 초기 데이터베이스 스키마를 PostgreSQL 데이터베이스로 마이그레이션할 수 있습니다.

  1. ~/myprojectdir/manage.py makemigrations
  2. ~/myprojectdir/manage.py migrate

다음을 입력하여 프로젝트의 관리 사용자를 만듭니다.

  1. ~/myprojectdir/manage.py createsuperuser

사용자 이름을 선택하고 이메일 주소를 제공하고 암호를 선택하고 확인해야 합니다.

다음을 입력하여 구성한 디렉터리 위치에 모든 정적 콘텐츠를 수집할 수 있습니다.

  1. ~/myprojectdir/manage.py collectstatic

작업을 확인해야 합니다. 그러면 정적 파일이 프로젝트 디렉토리 내의 static 디렉토리에 배치됩니다.

초기 서버 설정 가이드를 따랐다면 서버를 보호하는 UFW 방화벽이 있어야 합니다. 개발 서버를 테스트하려면 사용할 포트에 대한 액세스를 허용해야 합니다.

다음을 입력하여 포트 8000에 대한 예외를 만듭니다.

  1. sudo ufw allow 8000

마지막으로 다음 명령으로 Django 개발 서버를 시작하여 프로젝트를 테스트할 수 있습니다.

  1. ~/myprojectdir/manage.py runserver 0.0.0.0:8000

웹 브라우저에서 서버의 도메인 이름 또는 IP 주소를 방문하고 :8000:

http://server_domain_or_IP:8000

기본 Django 인덱스 페이지를 받아야 합니다.

주소 표시줄의 URL 끝에 /admin을 추가하면 createsuperuser 명령으로 생성한 관리 사용자 이름과 비밀번호를 입력하라는 메시지가 표시됩니다.

인증 후 기본 Django 관리 인터페이스에 액세스할 수 있습니다.

탐색이 끝나면 터미널 창에서 CTRL-C를 눌러 개발 서버를 종료합니다.

Gunicorn의 프로젝트 수행 능력 테스트

가상 환경을 떠나기 전에 마지막으로 해야 할 일은 Gunicorn을 테스트하여 애플리케이션을 제공할 수 있는지 확인하는 것입니다. 프로젝트 디렉토리에 들어가 gunicorn을 사용하여 프로젝트의 WSGI 모듈을 로드하면 됩니다.

  1. cd ~/myprojectdir
  2. gunicorn --bind 0.0.0.0:8000 myproject.wsgi

이렇게 하면 Django 개발 서버가 실행 중인 동일한 인터페이스에서 Gunicorn이 시작됩니다. 돌아가서 브라우저에서 앱을 다시 테스트할 수 있습니다.

참고: 관리 인터페이스에는 Gunicorn이 이를 담당하는 정적 CSS 콘텐츠를 찾는 방법을 모르기 때문에 스타일이 적용되지 않습니다.

Python의 모듈 구문을 사용하여 애플리케이션의 진입점인 Django의 wsgi.py 파일에 대한 상대 디렉토리 경로를 지정하여 Gunicorn에 모듈을 전달했습니다. 이 파일 안에는 application이라는 함수가 정의되어 있는데, 이 함수는 응용 프로그램과 통신하는 데 사용됩니다. WSGI 사양에 대해 자세히 알아보려면 여기를 클릭하십시오.

테스트가 끝나면 터미널 창에서 CTRL-C를 눌러 Gunicorn을 중지합니다.

이제 Django 애플리케이션 구성이 완료되었습니다. 다음을 입력하여 가상 환경에서 나갈 수 있습니다.

  1. deactivate

프롬프트의 가상 환경 표시기가 제거됩니다.

Gunicorn용 시스템 소켓 및 서비스 파일 생성

Gunicorn이 Django 애플리케이션과 상호 작용할 수 있는지 테스트했지만 이제 애플리케이션 서버를 시작하고 중지하는 보다 강력한 방법을 구현해야 합니다. 이를 달성하기 위해 systemd 서비스 및 소켓 파일을 만듭니다.

Gunicorn 소켓은 부팅 시 생성되며 연결을 수신 대기합니다. 연결이 발생하면 systemd는 Gunicorn 프로세스를 자동으로 시작하여 연결을 처리합니다.

sudo 권한으로 Gunicorn용 시스템 소켓 파일을 생성하고 여는 것으로 시작합니다.

  1. sudo nano /etc/systemd/system/gunicorn.socket

내부에서 소켓을 설명하는 [Unit] 섹션, 소켓 위치를 정의하는 [Socket] 섹션 및 [Install] 섹션을 사용하여 소켓이 적시에 생성되었는지 확인하십시오.

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

완료되면 파일을 저장하고 닫습니다.

다음으로 텍스트 편집기에서 sudo 권한으로 Gunicorn용 시스템 서비스 파일을 생성하고 엽니다. 서비스 파일 이름은 다음 확장자를 제외하고 소켓 파일 이름과 일치해야 합니다.

  1. sudo nano /etc/systemd/system/gunicorn.service

메타데이터 및 종속성을 지정하는 데 사용되는 [Unit] 섹션으로 시작합니다. 여기에 서비스에 대한 설명을 입력하고 네트워킹 대상에 도달한 후에만 서비스를 시작하도록 초기화 시스템에 지시합니다. 서비스가 소켓 파일의 소켓에 의존하기 때문에 해당 관계를 나타내기 위해 Requires 지시문을 포함해야 합니다.

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

다음으로 [Service] 섹션을 작성합니다. 실행할 처리할 사용자 및 그룹을 지정하십시오. 모든 관련 파일을 소유하고 있으므로 프로세스의 일반 사용자 계정 소유권을 부여합니다. Nginx가 Gunicorn과 통신할 수 있도록 www-data 그룹에 그룹 소유권을 부여합니다.

그런 다음 작업 디렉터리를 매핑하고 서비스를 시작하는 데 사용할 명령을 지정합니다. 이 경우 가상 환경 내에 설치되는 Gunicorn 실행 파일의 전체 경로를 지정해야 합니다. 그런 다음 프로세스가 Nginx와 통신할 수 있도록 /run 디렉토리 내에 생성한 Unix 소켓에 프로세스를 바인딩합니다. journald 프로세스가 Gunicorn 로그를 수집할 수 있도록 모든 데이터를 표준 출력에 기록합니다. 여기에서 선택적 Gunicorn 조정을 지정할 수도 있습니다. 예를 들어 이 경우 3개의 작업자 프로세스를 지정했습니다.

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

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myprojectdir
ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          myproject.wsgi:application

마지막으로 [Install] 섹션을 추가합니다. 이것은 부팅 시 시작하도록 활성화한 경우 이 서비스를 연결할 항목을 systemd에 알려줍니다. 일반 다중 사용자 시스템이 실행 중일 때 이 서비스를 시작하려고 합니다.

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

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myprojectdir
ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          myproject.wsgi:application

[Install]
WantedBy=multi-user.target

이것으로 systemd 서비스 파일이 완성되었습니다. 지금 저장하고 닫습니다.

이제 Gunicorn 소켓을 시작하고 활성화할 수 있습니다. 이렇게 하면 지금과 부팅 시 /run/gunicorn.sock에 소켓 파일이 생성됩니다. 해당 소켓에 연결되면 systemd는 자동으로 gunicorn.service를 시작하여 이를 처리합니다.

  1. sudo systemctl start gunicorn.socket
  2. sudo systemctl enable gunicorn.socket

소켓 파일을 확인하여 작업이 성공했는지 확인할 수 있습니다.

Gunicorn 소켓 파일 확인

프로세스의 상태를 확인하여 시작할 수 있는지 확인하십시오.

  1. sudo systemctl status gunicorn.socket

다음과 같은 출력을 받아야 합니다.

Output
● gunicorn.socket - gunicorn socket Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor preset: enabled) Active: active (listening) since Thu 2022-08-04 19:02:54 UTC; 5s ago Triggers: ● gunicorn.service Listen: /run/gunicorn.sock (Stream) CGroup: /system.slice/gunicorn.socket Apr 18 17:53:25 django systemd[1]: Listening on gunicorn socket.

다음으로 /run 디렉토리 내에 gunicorn.sock 파일이 있는지 확인합니다.

  1. file /run/gunicorn.sock
Output
/run/gunicorn.sock: socket

systemctl status 명령이 오류가 발생했음을 나타내거나 디렉토리에서 gunicorn.sock 파일을 찾을 수 없다면 Gunicorn 소켓이 올바르게 생성됩니다. 다음을 입력하여 Gunicorn 소켓의 로그를 확인하십시오.

  1. sudo journalctl -u gunicorn.socket

계속하기 전에 /etc/systemd/system/gunicorn.socket 파일을 다시 살펴보고 문제를 수정하십시오.

소켓 활성화 테스트

현재 gunicorn.socket 유닛만 시작한 경우 gunicorn.service는 소켓이 아직 연결을 수신하지 않았기 때문에 아직 활성화되지 않습니다. 다음을 입력하여 확인할 수 있습니다.

  1. sudo systemctl status gunicorn
Output
○ gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: inactive (dead) TriggeredBy: ● gunicorn.socket

소켓 활성화 메커니즘을 테스트하려면 다음을 입력하여 curl을 통해 소켓에 대한 연결을 보낼 수 있습니다.

  1. curl --unix-socket /run/gunicorn.sock localhost

터미널에서 애플리케이션의 HTML 출력을 수신해야 합니다. 이는 Gunicorn이 시작되었고 Django 애플리케이션을 제공할 수 있었음을 나타냅니다. 다음을 입력하여 Gunicorn 서비스가 실행 중인지 확인할 수 있습니다.

  1. sudo systemctl status gunicorn
Output
● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: active (running) since Thu 2022-08-04 19:03:51 UTC; 5s ago TriggeredBy: ● gunicorn.socket Main PID: 102674 (gunicorn) Tasks: 4 (limit: 4665) Memory: 94.2M CPU: 885ms CGroup: /system.slice/gunicorn.service ├─102674 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application ├─102675 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application ├─102676 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application └─102677 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application Apr 18 17:54:49 django systemd[1]: Started gunicorn daemon. Apr 18 17:54:49 django gunicorn[102674]: [2022-04-18 17:54:49 +0000] [102674] [INFO] Starting gunicorn 20.1.0 Apr 18 17:54:49 django gunicorn[102674]: [2022-04-18 17:54:49 +0000] [102674] [INFO] Listening at: unix:/run/gunicorn.sock (102674) Apr 18 17:54:49 django gunicorn[102674]: [2022-04-18 17:54:49 +0000] [102674] [INFO] Using worker: sync Apr 18 17:54:49 django gunicorn[102675]: [2022-04-18 17:54:49 +0000] [102675] [INFO] Booting worker with pid: 102675 Apr 18 17:54:49 django gunicorn[102676]: [2022-04-18 17:54:49 +0000] [102676] [INFO] Booting worker with pid: 102676 Apr 18 17:54:50 django gunicorn[102677]: [2022-04-18 17:54:50 +0000] [102677] [INFO] Booting worker with pid: 102677 Apr 18 17:54:50 django gunicorn[102675]: - - [18/Apr/2022:17:54:50 +0000] "GET / HTTP/1.1" 200 10697 "-" "curl/7.81.0"

curl의 출력 또는 systemctl status의 출력이 문제가 발생했음을 나타내면 로그에서 추가 세부 정보를 확인하십시오.

  1. sudo journalctl -u gunicorn

/etc/systemd/system/gunicorn.service 파일에 문제가 있는지 확인하십시오. /etc/systemd/system/gunicorn.service 파일을 변경하는 경우 데몬을 다시 로드하여 서비스 정의를 다시 읽고 다음을 입력하여 Gunicorn 프로세스를 다시 시작하십시오.

  1. sudo systemctl daemon-reload
  2. sudo systemctl restart gunicorn

계속하기 전에 위의 문제를 해결했는지 확인하십시오.

Nginx를 Gunicorn에 대한 프록시 패스로 구성

이제 Gunicorn이 설정되었으므로 트래픽을 프로세스로 전달하도록 Nginx를 구성해야 합니다.

Nginx의 sites-available 디렉토리에서 새 서버 블록을 생성하고 여는 것으로 시작합니다.

  1. sudo nano /etc/nginx/sites-available/myproject

내부에서 새 서버 블록을 엽니다. 이 블록이 일반 포트 80에서 수신 대기하고 서버의 도메인 이름 또는 IP 주소에 응답하도록 지정하여 시작합니다.

server {
    listen 80;
    server_name server_domain_or_IP;
}

다음으로 Nginx에게 파비콘을 찾는 문제를 무시하도록 지시합니다. 또한 ~/myprojectdir/static 디렉터리에서 수집한 정적 자산을 찾을 위치를 알려줍니다. 이러한 모든 파일에는 "/static”이라는 표준 URI 접두사가 있으므로 해당 요청과 일치하는 위치 블록을 만들 수 있습니다.

server {
    listen 80;
    server_name server_domain_or_IP;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/sammy/myprojectdir;
    }
}

마지막으로, 다른 모든 요청과 일치하도록 location/{} 블록을 생성합니다. 이 위치 안에 Nginx 설치에 포함된 표준 proxy_params 파일을 포함하고 트래픽을 Gunicorn 소켓으로 직접 전달합니다.

server {
    listen 80;
    server_name server_domain_or_IP;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/sammy/myprojectdir;
    }

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

완료되면 파일을 저장하고 닫습니다. 이제 파일을 sites-enabled 디렉터리에 연결하여 활성화할 수 있습니다.

  1. sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

다음을 입력하여 구문 오류에 대한 Nginx 구성을 테스트합니다.

  1. sudo nginx -t

오류가 보고되지 않으면 다음을 입력하여 Nginx를 다시 시작하십시오.

  1. sudo systemctl restart nginx

마지막으로 포트 80에서 일반 트래픽에 대해 방화벽을 열어야 합니다. 더 이상 개발 서버에 액세스할 필요가 없으므로 포트 8000을 여는 규칙도 제거할 수 있습니다.

  1. sudo ufw delete allow 8000
  2. sudo ufw allow 'Nginx Full'

이제 서버의 도메인 또는 IP 주소로 이동하여 애플리케이션을 볼 수 있습니다.

참고: Nginx를 구성한 후 다음 단계는 SSL/TLS를 사용하여 서버에 대한 트래픽을 보호하는 것입니다. 이것이 없으면 암호를 포함한 모든 정보가 일반 텍스트로 네트워크를 통해 전송되기 때문에 이것은 중요합니다.

도메인 이름이 있는 경우 트래픽을 보호하기 위해 SSL 인증서를 얻는 가장 간단한 방법은 Let’s Encrypt를 사용하는 것입니다. 이 가이드에 따라 Debian 11에서 Let's Encrypt with Nginx를 설정하세요. 이 가이드에서 생성한 Nginx 서버 블록을 사용하여 절차를 따르세요.

Nginx 및 Gunicorn 문제 해결

이 마지막 단계에서 애플리케이션이 표시되지 않으면 설치 문제를 해결해야 합니다.

Nginx가 Django 애플리케이션 대신 기본 페이지를 표시함

Nginx가 애플리케이션에 프록시하는 대신 기본 페이지를 표시하는 경우 일반적으로 /etc/nginx/sites-available/myproject 내에서 server_name을 조정해야 함을 의미합니다. mark> 파일이 서버의 IP 주소 또는 도메인 이름을 가리키도록 합니다.

Nginx는 server_name을 사용하여 요청에 응답하는 데 사용할 서버 블록을 결정합니다. 기본 Nginx 페이지를 수신하면 Nginx가 서버 블록에 대한 요청을 명시적으로 일치시킬 수 없다는 신호이므로 /etc/nginx/sites-available/에 정의된 기본 블록으로 돌아갑니다. 기본값.

프로젝트의 서버 블록에 있는 server_name은 선택할 기본 서버 블록에 있는 것보다 더 구체적이어야 합니다.

Nginx가 Django 애플리케이션 대신 502 잘못된 게이트웨이 오류를 표시함

502 오류는 Nginx가 요청을 성공적으로 프록시할 수 없음을 나타냅니다. 다양한 구성 문제가 502 오류로 나타나므로 제대로 문제를 해결하려면 더 많은 정보가 필요합니다.

자세한 정보를 찾는 기본 위치는 Nginx의 오류 로그입니다. 일반적으로 이것은 프록시 이벤트 중에 문제를 일으킨 조건을 알려줍니다. 다음을 입력하여 Nginx 오류 로그를 따르십시오.

  1. sudo tail -F /var/log/nginx/error.log

이제 브라우저에서 새로운 오류를 생성하도록 다른 요청을 하십시오(페이지 새로고침 시도). 로그에 기록된 새로운 오류 메시지를 받아야 합니다. 메시지를 보면 문제의 범위를 좁히는 데 도움이 됩니다.

다음 메시지를 수신할 수 있습니다.

unix:/run/gunicorn.sock에 대한 connect() 실패(2: 해당 파일 또는 디렉토리 없음)

이는 Nginx가 주어진 위치에서 gunicorn.sock 파일을 찾을 수 없음을 나타냅니다. /etc/nginx/sites-available/myproject 파일 내에 정의된 proxy_pass 위치를 gunicorn.sock 파일의 실제 위치와 비교해야 합니다. gunicorn.socket 시스템 단위에 의해 생성됩니다.

/run 디렉토리 내에서 gunicorn.sock 파일을 찾을 수 없다면 일반적으로 시스템 소켓 파일이 파일을 생성할 수 없다는 의미입니다. Gunicorn 소켓 파일 확인 섹션으로 돌아가서 Gunicorn의 문제 해결 단계를 진행하십시오.

unix:/run/gunicorn.sock에 대한 connect() 실패(13: 권한 거부)

이는 권한 문제로 인해 Nginx가 Gunicorn 소켓에 연결할 수 없음을 나타냅니다. 이는 sudo 사용자 대신 루트 사용자를 사용하여 절차를 따를 때 발생할 수 있습니다. systemd는 Gunicorn 소켓 파일을 생성할 수 있지만 Nginx는 액세스할 수 없습니다.

이는 루트 디렉터리(/)와 gunicorn.sock 파일 사이에 제한된 권한이 있는 경우 발생할 수 있습니다. 소켓 파일의 절대 경로를 namei 명령에 전달하여 소켓 파일과 각 상위 디렉토리의 권한 및 소유권 값을 검토할 수 있습니다.

  1. namei -l /run/gunicorn.sock
Output
f: /run/gunicorn.sock drwxr-xr-x root root / drwxr-xr-x root root run srw-rw-rw- root root gunicorn.sock

출력에는 각 디렉터리 구성 요소의 권한이 표시됩니다. 권한(첫 번째 열), 소유자(두 번째 열) 및 그룹 소유자(세 번째 열)를 보면 소켓 파일에 어떤 유형의 액세스가 허용되는지 파악할 수 있습니다.

위의 예에서 소켓 파일과 소켓 파일로 연결되는 각 디렉토리에는 전체 읽기 및 실행 권한이 있습니다(디렉토리에 대한 권한 열은 --- 대신 r-x로 끝납니다. ). Nginx 프로세스는 소켓에 성공적으로 액세스할 수 있어야 합니다.

소켓으로 이어지는 디렉토리 중 하나라도 전체 읽기 및 실행 권한이 없는 경우 Nginx는 전체 읽기 및 실행 권한을 허용하지 않거나 그룹 소유권이 Nginx가 속한 그룹에 부여되지 않으면 소켓에 액세스할 수 없습니다. 의.

Django가 표시됨: \서버에 연결할 수 없음: 연결이 거부되었습니다.\

웹 브라우저에서 애플리케이션의 일부에 액세스하려고 할 때 Django에서 받을 수 있는 한 가지 메시지는 다음과 같습니다.

OperationalError at /admin/login/
could not connect to server: Connection refused
    Is the server running on host "localhost" (127.0.0.1) and accepting
    TCP/IP connections on port 5432?

이는 Django가 Postgres 데이터베이스에 연결할 수 없음을 나타냅니다. 다음을 입력하여 Postgres 인스턴스가 실행 중인지 확인합니다.

  1. sudo systemctl status postgresql

그렇지 않은 경우 다음을 입력하여 시작하고 부팅 시 자동으로 시작하도록 설정할 수 있습니다(아직 구성되지 않은 경우).

  1. sudo systemctl start postgresql
  2. sudo systemctl enable postgresql

여전히 문제가 있는 경우 ~/myprojectdir/myproject/settings.py 파일에 정의된 데이터베이스 설정이 올바른지 확인하십시오.

추가 문제 해결

추가적인 문제 해결을 위해 로그는 근본 원인을 좁히는 데 도움이 될 수 있습니다. 각각을 차례로 확인하고 문제 영역을 나타내는 메시지를 찾으십시오.

다음 로그가 도움이 될 수 있습니다.

  • sudo journalctl -u nginx
  • 를 입력하여 Nginx 프로세스 로그를 확인합니다.\n
  • 다음을 입력하여 Nginx 액세스 로그를 확인합니다. sudo less /var/log/nginx/access.log
  • 다음을 입력하여 Nginx 오류 로그를 확인합니다. sudo less /var/log/nginx/error.log
  • sudo journalctl -u gunicorn
  • 을 입력하여 Gunicorn 애플리케이션 로그를 확인합니다.\n
  • sudo journalctl -u gunicorn.socket
  • 을 입력하여 Gunicorn 소켓 로그를 확인합니다.\n

구성 또는 애플리케이션을 업데이트할 때 변경 사항을 적용하기 위해 프로세스를 다시 시작해야 할 수 있습니다.

Django 애플리케이션을 업데이트하는 경우 다음을 입력하여 Gunicorn 프로세스를 다시 시작하여 변경 사항을 적용할 수 있습니다.

  1. sudo systemctl restart gunicorn

Gunicorn 소켓 또는 서비스 파일을 변경하는 경우 데몬을 다시 로드하고 다음을 입력하여 프로세스를 다시 시작합니다.

  1. sudo systemctl daemon-reload
  2. sudo systemctl restart gunicorn.socket gunicorn.service

Nginx 서버 블록 구성을 변경하는 경우 구성을 테스트한 다음 다음을 입력하여 Nginx를 테스트합니다.

  1. sudo nginx -t && sudo systemctl restart nginx

이러한 명령은 구성을 조정할 때 변경 사항을 선택하는 데 유용합니다.

결론

이 가이드에서는 자체 가상 환경에서 Django 프로젝트를 설정합니다. Django가 클라이언트 요청을 처리할 수 있도록 Gunicorn이 클라이언트 요청을 번역하도록 구성했습니다. 그런 다음 클라이언트 연결을 처리하고 클라이언트 요청에 따라 올바른 프로젝트를 제공하는 리버스 프록시 역할을 하도록 Nginx를 설정합니다.

Django는 고유한 요소에 집중할 수 있도록 많은 공통 부분을 제공하여 프로젝트 및 애플리케이션을 만드는 데 도움을 줍니다. 이 문서에서 설명하는 일반 도구 체인을 활용하면 단일 서버에서 생성한 애플리케이션을 제공할 수 있습니다.