블로그로 돌아가기

Ubuntu에서 Docker로 Django 및 Gunicorn 애플리케이션 구축하기

Ubuntu에서 Docker로 Django 및 Gunicorn 애플리케이션 구축하기

Django는 고수준 오픈 소스 Python 웹 프레임워크로, Python 애플리케이션을 신속하게 구축할 수 있도록 도와줍니다. 모델-템플릿-뷰(model–template–views) 아키텍처 패턴을 따름으로써 빠른 개발과 깔끔하고 실용적인 디자인을 장려합니다. 기본적으로 이 프레임워크는 사용자 인증, 캐싱 프레임워크, 객체 관계 매퍼, URL 디스패처, 템플릿 시스템, 그리고 사용자 정의 가능한 관리 인터페이스와 같은 필요한 현대적인 애플리케이션 구성 요소를 제공합니다.

Gunicorn ‘Green Unicorn’은 UNIX 시스템용 Python WSGI HTTP 서버입니다. Gunicorn 서버는 다양한 웹 프레임워크와 호환되며, 뛰어난 성능을 제공하고, 서버 리소스를 적게 소모합니다. Docker는 오랫동안 사용되어 온 오픈 소스 컨테이너 플랫폼으로, 애플리케이션 개발을 빠르고 효율적이며 예측 가능하게 만들어 줍니다.

이 튜토리얼에서 여러분은 확장 가능한 컨테이너화된 Django 웹 앱을 개발하고 배포하는 기술을 습득하게 됩니다. 우리는 Django 시작하기 안내서를 따라 생성된 Django Polls 앱을 사용할 것입니다. 이 튜토리얼을 작성할 당시, 우리는 Django 3.2 및 이를 지원하는 Python 3.6 이상을 기준으로 삼았습니다. 우리는 Docker를 사용하여 앱을 컨테이너로 배포하고 Gunicorn 서버로 서비스를 제공할 것입니다. 물론 Django 앱을 컨테이너에 배포하기 전에, 표준 출력 스트림으로의 로깅이나 환경 변수 작업 등을 처리하기 위해 프로젝트 코드를 일부 수정해야 합니다. CSS 및 JavaScript 이미지와 같은 정적 파일은 멀티 컨테이너 환경에서 한 곳에서 파일을 쉽게 관리할 수 있도록 오브젝트 스토리지 서비스로 오프로드할 수 있습니다.

확장 가능한 웹 애플리케이션을 구축하기 위해 잘 정리된 12요소(twelve-factor) 방법론을 기반으로 이러한 수정을 구현하는 방법을 보여드리겠습니다. 수정을 완료하면 애플리케이션의 Docker 이미지를 빌드하고 Docker로 컨테이너화된 앱을 배포하게 됩니다. 튜토리얼을 완전히 이해하기 위해 여기에 설명된 단계를 따라 진행하는 것을 권장합니다.

사전 요구 사항

이 튜토리얼은 실습 위주이므로, 원활한 진행을 위해 아래와 같이 설정하는 것을 권장합니다:

이러한 사전 요구 사항에 따라 두 개의 Ubuntu 서버 인스턴스가 있어야 합니다. 한 인스턴스에서는 Docker 컨테이너가 실행되고, 다른 인스턴스에서는 PostgreSQL 인스턴스가 실행됩니다. 시작해 봅시다!

1단계: PostgreSQL 데이터베이스 인스턴스 구성

이 섹션에서는 Postgres 인스턴스가 실행 중인 Ubuntu 서버에서 Postgres 구성을 수정합니다. 이를 통해 외부 IP 주소에서의 연결을 허용할 수 있습니다. 연결이 완료되면 배포하려는 Django Polls 앱에 특화된 데이터베이스와 사용자 역할을 생성할 수 있습니다.

먼저, 필수 조건에 따라 환경을 설정했다면, sudo 사용자를 위한 PostgreSQL 데이터베이스 역할이 있어야 합니다. 다음으로, 이 역할에 대한 비밀번호를 설정해야 합니다. PostgreSQL이 실행 중인 서버에서 다음 명령어로 Postgres 터미널에 로그인합니다:

Postgres 터미널에 접속하면, 다음 명령을 실행하여 \password 명령을 실행하여 사용자의 비밀번호를 변경합니다. \password 명령의 구문은 \password <username> 입니다. 우리의 경우, 명령어는 다음과 같습니다:

비밀번호를 입력하고 확인합니다. 나중에 다른 Ubuntu 서버에서 인증하는 데 사용되므로 이 비밀번호를 안전한 곳에 저장해 두세요. 그 후, exit를 입력하고 Enter를 눌러 Postgres 터미널을 종료합니다.

PostgreSQL 서버 인스턴스에서 방화벽(ufw)을 활성화한 경우, Postgres 기본 포트인 5432로의 트래픽을 허용해야 합니다. Docker 컨테이너를 실행할 다른 Ubuntu 서버의 특정 IP 주소에서만 트래픽이 발생하도록 제한할 수 있습니다. 강조 표시된 부분에 귀하의 IP 주소를 입력하여 ufw 규칙을 추가하는 다음 명령을 실행합니다:

이렇게 하면 귀하의 서버만 PostgreSQL 인스턴스에 연결할 수 있습니다. 방화벽을 통해 트래픽을 허용하는 동안, 원격 IP 주소에서의 연결을 허용하도록 PostgreSQL 구성 파일도 수정해야 합니다. 기본적으로 구성은 localhost에서의 연결만 허용합니다. PostgreSQL의 구성 파일은 /etc/postgresql/12/main 디렉터리에 있습니다. 12은(는) 이 경우 이 튜토리얼을 위해 설치한 PostgreSQL 버전입니다. 다른 버전을 설치했을 수도 있습니다. 따라서, /etc/postgresql/ 디렉터리로 이동하여 콘텐츠를 나열해 설치된 PostgreSQL의 버전 번호를 확인할 수 있습니다.

nano를 사용하여 구성 파일을 수정합니다:

아래 줄을 찾아 주석을 해제하고, 모든 IP에서의 연결을 허용하도록 설정합니다:

파일을 저장하고 닫습니다. 그런 다음, pg_hba.conf 파일도 편집해야 합니다. 이 파일은 postgresql.conf와(과) 같은 디렉터리에 있습니다. pg_hba.conf 파일을 사용하면 PostgreSQL 인스턴스에 연결할 수 있는 컴퓨터와 인증 방법을 정의할 수 있습니다. nano로 파일을 엽니다:

키워드를 이해하려면 이 파일의 주석을 읽어보세요. 우리가 찾는 섹션은 다음과 같습니다:

Building a Django and Gunicorn Application with Docker on Ubuntu 1

우리는 두 번째 줄에 집중할 것입니다. 주석을 해제한 후 아래 줄과 같이 보이게 설정합니다:

PostgreSQL 인스턴스에 연결할 수 있도록 강조 표시된 부분을 Ubuntu 서버 IP 주소로 바꾸십시오. 준비가 되면 파일을 저장합니다. 변경 사항을 적용하려면 PostgreSQL 데이터베이스를 다시 시작합니다:

지정된 IP 주소를 가진 다른 Ubuntu 서버가 Postgres 인스턴스에 연결할 수 있어야 합니다.

2단계: PostgreSQL 서버 인스턴스에 연결하고 데이터베이스 및 사용자 생성

이 단계에서는 Ubuntu 인스턴스가 Docker 컨테이너를 서비스하면서 PostgreSQL 인스턴스가 실행 중인 다른 서버에 연결할 수 있도록 하려고 합니다. Docker가 있는 Ubuntu 인스턴스에 로그인하고 Ubuntu 호스트 머신 내부에 postgresql-client 패키지를 설치합니다(아직 컨테이너 내부가 아님).

일반적으로 먼저 apt 패키지를 업데이트한 후 다음 명령어로 패키지를 설치합니다:

위에서 설치한 패키지는 애플리케이션을 위한 데이터베이스와 사용자를 생성하는 데 도움이 됩니다. 다음으로, PostgreSQL 클라이언트에 연결 매개변수를 전달하여 PostgreSQL 인스턴스에 연결해야 합니다.

연결 매개변수는 다음 구문을 따릅니다.

이 명령에서 username은(는) PostgreSQL 데이터베이스에 추가한 사용자/역할입니다. host은(는) PostgreSQL 데이터베이스를 실행 중인 Ubuntu 인스턴스의 IP 주소입니다. port은(는) Postgres가 들어오는 연결을 수신 대기하는 기본 포트입니다. 즉, 5432입니다. database 자리에는 PostgreSQL 설치 시 기본으로 제공되는 postgres라는 기본 데이터베이스를 사용합니다. 강조 표시된 부분의 값을 적절하게 변경하고 Enter 키를 누릅니다. 메시지가 표시되면 설정한 비밀번호를 입력합니다. 이렇게 하면 데이터베이스를 관리할 수 있는 Postgres 프롬프트에 로그인됩니다.

PostgreSQL 인스턴스에 성공적으로 연결되었습니다. 이제 Django polls 앱을 위한 데이터베이스를 생성할 수 있습니다. 이름을 django_polls:

오류가 발생하지 않도록 문장 끝에 세미콜론이 있는지 확인하세요. 그런 다음, 다음 명령을 사용하여 django_polls 데이터베이스로 전환합니다.

다음으로, 이 프로젝트 전용 데이터베이스 사용자를 생성합니다. 사용자의 이름을 django_user:

사용자를 위한 안전한 비밀번호를 선택하세요. 완료되면 방금 생성한 사용자의 연결 매개변수를 수정해야 합니다. 이렇게 하면 연결이 설정될 때마다 올바른 값을 쿼리하고 설정하지 않도록 하여 데이터베이스 작업 속도를 높이는 데 도움이 됩니다.

Django가 예상하는 기본 인코딩을 UTF-8로 설정합니다.

다음으로, 기본 트랜잭션 격리 수준을 “ read committed”로 설정하여 커밋되지 않은 트랜잭션의 읽기를 차단합니다.

시간대를 설정합니다. 튜토리얼의 범용성을 유지하기 위해 UTC:

마지막으로, 새 사용자에게 데이터베이스의 관리 권한을 부여합니다.

준비가 되면 PostgreSQL 프롬프트를 종료합니다.

이 단계는 이것으로 끝입니다. Django 앱을 올바르게 구성하면 데이터베이스를 관리할 수 있게 됩니다.

3단계: Git 저장소에서 앱 가져오기 및 종속성 정의

이 단계에서는 Django-polls 앱 저장소를 복제합니다. 이 저장소에는 Django의 첫 번째 Django 앱 작성하기 튜토리얼.

Docker를 실행 중인 Ubuntu 서버에 로그인하고, django_project 디렉터리를 생성한 후 해당 디렉터리로 이동합니다.

그런 다음, 다음 명령을 사용하여 저장소를 디렉터리로 복제합니다.

디렉터리로 이동하여 콘텐츠를 나열합니다.

디렉터리의 콘텐츠를 나열합니다.

Building a Django and Gunicorn Application with Docker on Ubuntu 2

다음 항목을 확인하세요.

  • manage.py: 이 파일은 Django가 앱을 관리하기 위해 제공하는 명령줄 유틸리티의 진입점입니다.

  • mysite: Django 프로젝트 범위 및 코드 설정이 포함된 디렉터리입니다.

  • polls: polls 애플리케이션 코드가 포함된 디렉터리입니다.

  • templates: 관리자 페이지용 사용자 정의 템플릿 파일이 포함되어 있습니다.

프로젝트를 실제로 생성한 방법에 대해 자세히 알아보려면 공식 문서의 Writing your first Django app를 참조하세요. django-polls 디렉터리에서 Python 의존성을 텍스트 파일에 정의하고자 합니다. 이 파일의 이름을 requirements.txt라고 하겠습니다. 선호하는 편집기로 파일을 엽니다:

의존성을 선언하기 위해 파일 내부에 다음 줄을 붙여넣습니다:

이 파일에는 앱을 빌드할 때 설치해야 하는 정확한 버전의 Python 의존성을 정의했습니다. 이 중 일부에는 Django, django-storages 오브젝트 스토리지 버킷과 상호 작용하기 위한 psycopg2 PostgreSQL용 어댑터, gunicorn WSGI 서버 및 기타 추가 의존성이 포함됩니다. 완료되면 파일을 저장하고 닫습니다.

단계 4: Django 앱을 위한 환경 변수 구성

The twelve-factor app 방법론에서는 애플리케이션의 코드베이스에서 하드코딩된 구성을 추출할 것을 권장합니다. 그렇게 함으로써 코드베이스를 건드리지 않고 환경 변수를 수정하여 런타임에 애플리케이션의 동작을 자유롭게 변경할 수 있습니다. Docker는 이 설정과 함께 작동하므로 환경 변수와 함께 작동하도록 설정 파일을 수정할 것입니다. Kubernetes 또한 이 구성 설정과 함께 작동합니다. 저희는 Kubernetes를 사용한 배포에 대한 또 다른 튜토리얼을 다음 블로그에 공유할 예정입니다: CloudSigma blog.

The settings.py는 Django 프로젝트의 메인 설정 파일입니다. 이는 애플리케이션을 구성하기 위해 네이티브 데이터 구조를 사용하는 Python 모듈입니다. 우리 애플리케이션의 경우 파일 위치는 django-polls/mysite/settings.py입니다. 대부분의 값은 하드코딩되어 있습니다. 이로 인해 애플리케이션 동작을 변경하는 경우 코드베이스의 구성 파일을 수정해야 합니다. 우리는 그것을 바꾸고자 합니다. 다행히 Python은 getenv 함수를 os 모듈에서 제공합니다. 이를 사용하여 Django가 로컬 환경 변수에서 구성 매개변수를 대신 읽도록 구성할 수 있습니다.

계속해서 django-polls/mysite/settings.py 파일을 수정하여 변수의 하드코딩된 값을 대체해 보겠습니다. 런타임에 os.getenv 호출을 통해 업데이트하고자 할 수 있습니다. 이 함수는 제공된 환경 변수 이름에 설정된 값을 읽습니다. 선택적으로 환경 변수가 설정되지 않은 경우 사용될 기본값인 두 번째 매개변수를 제공할 수 있습니다.

예시는 다음과 같습니다:

위의 줄에서 우리는 Django에게 환경 변수에서 비밀 키를 검색하도록 지시합니다. 키를 외부에서 제공할 것이므로 대체(fallback) 값을 제공하지 않습니다. 키가 존재하지 않으면 애플리케이션 실행이 실패해야 합니다. 비밀 키를 외부에서 제공하는 동안, 다양한 서버에서 앱의 모든 컨테이너화된 복사본이 동일한 키를 사용하도록 보장하고자 합니다. 이렇게 하면 앱의 다양한 복사본이 서로 다른 키를 사용할 때 발생하는 잠재적인 문제를 방지할 수 있습니다.

기본 옵션이 있는 또 다른 예시는 다음과 같습니다:

이 줄에서는 읽어야 할 환경 변수 DEBUG를 정의합니다. 그러나 설정되지 않은 경우 DEBUG 설정 변수에 전달될 두 번째 매개변수를 제공했습니다. DEBUGFalse로 설정되어 애플리케이션에 문제가 발생할 경우 민감한 정보가 프론트엔드로 전달되지 않도록 합니다. 그러나 개발 모드에 있는 경우 오류를 쉽게 수정할 수 있도록 오류 정보를 볼 수 있도록 True로 설정하고자 합니다.

이제 환경 변수의 중요성을 알았으므로 편집기에서 django_project/django-polls/settings.py를 엽니다. 먼저 os 모듈을 settings.py 파일 상단에 다음 줄을 추가하여 가져옵니다:

그런 다음, 이 변수들을 찾아 다음과 같이 업데이트합니다:

In the ALLOWED_HOSTS 설정에서는, DJANGO_ALLOWED_HOSTS 환경 변수에서 값을 가져와 Python 리스트로 분할하도록 지정하며, 이때 쉼표( ,)를 구분 기호로 사용합니다. 해당 변수가 누락된 경우, ALLOWED_HOSTS127.0.0.1.

다음으로, 파일을 스크롤하여 DATABASES 섹션을 찾고, 환경 변수에서도 읽을 수 있도록 다음과 같이 구성합니다:

여기서 json.loads 모듈이 추가된 것을 확인할 수 있습니다. 또한 settings.py 파일의 맨 위에 이 모듈의 import 문을 추가해야 합니다:

The json.loads 함수는 DATABASES['default']['OPTIONS']에 전달되는 JSON 객체를 DB_OPTIONS 환경 변수로부터 역직렬화합니다. 이 옵션을 지정하면 데이터베이스 구성을 정의하기 위해 임의의 데이터 구조를 전달할 수 있습니다. 데이터베이스 엔진에는 적용 가능한 유효한 옵션 세트가 포함되어 있습니다. JSON 옵션을 사용하면 당시 사용 중인 데이터베이스 엔진에 적합한 매개변수로 JSON 객체를 인코딩할 수 있는 유연성을 얻을 수 있습니다.

The DATABASES['default']['NAME']은 우리가 설정한 관계형 데이터베이스 관리 시스템의 데이터베이스 이름을 지정합니다. SQLite 데이터베이스를 사용하는 경우에는 데이터베이스 파일의 경로를 지정해야 합니다.

Python은 외부 환경 변수를 읽는 여러 가지 방법을 제공합니다. 여기서는 그 중 하나만 사용했습니다. 다른 방법을 자유롭게 조사하고 사용해 보셔도 좋습니다. 이 단계에서는 외부 환경 변수를 다루는 방법을 배웠습니다. 이를 통해 변수를 변경하고 컨테이너에서 실행 중인 앱의 동작을 바꿀 수 있는 유연성을 얻을 수 있습니다. 다음 단계에서는 객체 스토리지 서비스를 다루는 방법을 배우게 됩니다.

5단계: 외부 객체 스토리지 서비스 작업하기

애플리케이션을 컨테이너화하는 것의 주요 장점은 이식성을 높여 트래픽이 증가할 때 앱의 여러 복사본을 쉽게 배포할 수 있다는 것입니다. 따라서 확장할 수 있는 여지를 제공합니다. 그러나 이로 인해 여러 컨테이너에 걸쳐 정적 파일 및 에셋의 버전을 유지해야 하는 문제가 발생합니다. 클라우드 기술의 발전 덕분에 이러한 공유 정적 요소를 외부 스토리지로 오프로드할 수 있습니다. 그런 다음 실행 중인 모든 컨테이너가 네트워크를 통해 파일에 액세스할 수 있도록 설정할 수 있습니다. 실행 중인 여러 컨테이너 간에 파일을 동기화하려고 시도하는 대신, 이를 관리할 하나의 중앙 집중식 공간을 갖게 됩니다.

위에서 설명한 개념은 클라우드 객체 스토리지 서비스, 즉 Simple Storage Service(S3)를 사용하는 것입니다. Django에는 django-storages 원격 스토리지 백엔드를 사용할 수 있게 해주는 Django-storages 은 FTP, SFTP, Amazon의 AWS S3, Google Cloud Storage, Dropbox, Azure Storage 등을 포함한 대부분의 S3 호환 객체 스토리지 서비스와 연동됩니다. 이 튜토리얼에서는 다음을 사용합니다: MinIO. 다른 S3 호환 객체 스토리지 서비스를 자유롭게 사용하셔도 좋습니다.. MinIOMinIO는 고성능 S3 호환 객체 스토리지를 제공합니다. MinIO를 사용하면 모든 클라우드에서 S3 호환 데이터 인프라를 구축할 수 있습니다.

CloudSigma 플랫폼에서 MinIO 스토리지 서비스를 설정하는 방법을 보여드리겠습니다. 다음 단계를 따르세요:

  • 먼저 CloudSigma에서 계정을 생성하세요. MinIO 스토리지를 생성하는 동안 문제가 발생하면 CloudSigma’의 연중무휴 24시간 무료 라이브 채팅 지원에 문의해 주세요. 기꺼이 도와드릴 것입니다.

  • 결제 정보를 추가하세요.

  • 다음으로, 여기에서 공개적으로 액세스 가능한 버킷을 요청하세요: https://blog.cloudsigma.com/xxxx. 계정 액세스 자격 증명을 받으려면 라이브 채팅 지원에 문의해야 합니다.

  • MinIO 객체 스토리지 환경이 생성되면 액세스 자격 증명 및 기타 액세스 지침이 제공됩니다. 자격 증명에는 다음이 포함되어야 합니다: MINI_ACCESS_KEY, MINIO_SECRET_KEY, 그리고 MINIO_URL. 아래 지침에서 이 키들을 사용하게 됩니다.

이전 단계에서 수정하던 mysite/settings.py 파일에 몇 가지 변경 사항을 더 적용해 보겠습니다. 파일에서 storages 앱을 Django의 INSTALLED_APPS:

INSTALLED_APPS

The storages 앱은 django-storages를 통해 설치되며, 이는 requirements.txt에 정의되어 있습니다. 파일의 맨 아래로 스크롤하여 STATIC_URL 변수를 다음 코드 스니펫으로 교체합니다:

일부 구성 변수가 하드코딩되어 있음에 유의하세요:

  • STATICFILES_STORAGE: Django가 정적 파일을 처리하는 데 사용할 스토리지 백엔드를 정의합니다. 이 가이드에서는 MinIO 스토리지를 사용하지만, Django Storages 문서에 설명된 대로 임의의 S3 호환 백엔드를 사용할 수 있습니다..

  • AWS_S3_OBJECT_PARAMETERS: 캐시 제어(cache-control) 헤더를 정의합니다.

  • AWS_LOCATION: 모든 정적 파일이 저장될 스토리지 버킷 내의 디렉터리를 설정하는 데 사용됩니다. 다른 이름을 자유롭게 선택하셔도 됩니다.

  • AWS_DEFAULT_ACL: 정적 파일에 대한 액세스 제어 목록(ACL)을 설정합니다. 값을 ‘ public-Read’(으)로 설정하면 모든 일반 사용자가 파일에 액세스할 수 있게 됩니다.

  • STATIC_URL: Django는 정적 파일의 URL을 생성하기 위해 이 변수에 설정된 기본 URL을 사용합니다. 이 경우 기본 URL은 엔드포인트 URL과 정적 파일 하위 디렉터리를 결합하여 파생됩니다.

  • STATIC_ROOT: 원격 객체 스토리지로 복사하기 전에 로컬에서 정적 파일을 수집할 위치를 정의합니다.

유연성과 이식성을 유지하기 위해 외부에서 정의된 몇 가지 환경 변수도 있습니다:

  • AWS_STORAGE_BUCKET_NAME: Django가 에셋을 업로드할 스토리지 버킷의 이름을 정의합니다.

  • AWS_S3_ENDPOINT_URL: 오브젝트 스토리지 서비스에 액세스하는 데 사용되는 엔드포인트 URL을 정의합니다. 이는 MinIO 서비스를 호스팅하는 서버에 매핑된 URL이 됩니다.

편집을 마쳤으면 파일을 저장하고 닫습니다.

이러한 설정을 완료하고 선언된 Python 종속성을 설치한 후에는 언제든지 Django 명령인 manage.py collectstatic를 실행하여 프로젝트의 정적 파일을 수집하고 원격 오브젝트 스토리지 백엔드에 업로드할 수 있습니다:

하지만 아직 env 파일에 구성을 설정하지 않았으므로 실패할 가능성이 높습니다.

명령을 실행하면 에셋의 크기와 인터넷 속도에 따라 에셋을 MinIO 클라우드 스토리지로 복사하는 데 시간이 조금 걸립니다.

이 단계는 여기까지입니다. 다음 단계에서 docker logs 명령을 사용하여 볼 수 있도록 Django 로그를 Docker 엔진으로 푸시하는 방법을 알아보겠습니다.

6단계: Django 앱에서 로깅 설정하기

디버그 모드에서 DEBUG 옵션이 True로 설정되어 있으면 Django는 표준 출력 및 표준 오류에 정보를 기록합니다. 로그 정보는 일반적으로 개발 HTTP 서버를 실행한 터미널에 표시됩니다.

프로덕션 환경에서는 다른 HTTP 서버를 사용할 가능성이 높으며, DEBUG 옵션이 False로 설정됩니다. 이 경우 Django는 다른 로깅 방법을 사용합니다. Django는 우선순위가 ERROR 또는 CRITICAL인 로그를 사용자가 정의한 관리자 이메일 계정으로 보냅니다. 이는 많은 상황에서 매우 유용합니다.

컨테이너화 및 Kubernetes 설정에서는 표준 출력 및 표준 오류로 로깅하는 것이 적극 권장됩니다. 로그 메시지는 노드의 파일 시스템에 있는 단일 디렉터리에 수집되며, kubectldocker 명령을 사용하여 쉽게 액세스할 수 있습니다. 노드의 파일 시스템에 중앙 집중식 로깅 지점이 있으면 운영 팀은 각 노드에서 프로세스를 쉽게 실행하여 로그를 모니터링하고 전달할 수 있습니다. 따라서 이 표준 설정에 로그를 기록하도록 애플리케이션을 구성해야 합니다.

Django가 Python 표준 라이브러리의 고도로 사용자 정의 가능한 logging 모듈을 활용한다는 사실을 알게 되면 기쁠 것입니다. 이를 통해 logging.config.dictConfig에 전달되는 딕셔너리를 정의하여 원하는 출력과 형식을 정의할 수 있습니다. Django 로깅 기술을 마스터하는 데 도움이 되는 Django Logging, The Right Way에 대한 좋은 기사가 있습니다.

에디터에서 django-polls/mysite/settings.py  파일을 엽니다. 파일 상단에 Python logging.config 라이브러리에 대한 import를 추가합니다:

지금까지 추가한 모든 import를 포함하여 settings.py의 import 섹션은 다음과 같아야 합니다:

Building a Django and Gunicorn Application with Docker on Ubuntu 3

The logging.config 라이브러리는 Django의 기본 로깅 동작을 재정의하기 위해 dictConfig 함수를 통해 새로운 로깅 구성의 딕셔너리를 허용합니다.

파일 하단으로 스크롤하여 다음 로깅 구성 코드 스니펫을 추가합니다:

LOGGING_CONFIG 은(는) None(으)로 설정되어 Django가 정의하는 기본 로깅 설정을 비활성화하거나 지웁니다. LOGLEVEL 은(는) DJANGO_LOGLEVEL 환경 변수에 의해 설정됩니다. 하지만 해당 변수가 존재하지 않는 경우, ‘ info’.

’로 설정되기를 원합니다. 상단에서 가져온 logging.config 모듈은 dictConfig 함수를 제공하며, 이 함수는 새로운 설정 딕셔너리를 설정하는 데 사용됩니다. 이 딕셔너리는 formatters 키를 사용하여 텍스트 형식을 정의합니다. 출력은 handlers 키로 설정되며, 마지막으로 loggers 키는 어떤 메시지가 어떤 핸들러로 전달되어야 하는지 정의합니다.

이러한 설정이 정의되면, Docker은(는) docker logs 명령어를 통해 로그를 노출합니다. 마찬가지로, Kubernetes를 위해 진행할 다른 튜토리얼에서는 kubectl logs 명령어로 로그를 볼 수 있습니다. 이제 다음 단계에서 컨테이너화 프로세스를 시작하겠습니다.

7단계: 애플리케이션 Dockerfile 정의하기

이 단계에서는 Gunicorn WSGI 서버가 제공하는 Django 앱을 실행할 컨테이너 이미지를 구동하기 위한 설정을 정의합니다. 컨테이너 이미지를 빌드하기 위한 런타임 환경을 정의하고, 애플리케이션과 그 종속성을 설치하며, 몇 가지 최종 설정을 수행합니다.

  • Django 앱을 위한 부모 이미지

컨테이너의 기반이 될 기초 이미지를 결정하는 것은 컨테이너화된 배포를 다룰 때 가장 먼저 내려야 하는 결정입니다. 물론 SCRATCH(즉, 빈 파일 시스템)에서 컨테이너 이미지를 빌드하거나 기존 컨테이너 이미지를 기반으로 빌드할 수도 있습니다. 바퀴를 다시 발명하고 싶지 않으므로, 우리는 베이스 이미지로부터 이미지를 빌드할 것입니다. 사용할 수 있는 오픈 소스 컨테이너 이미지는 Docker의 공식 컨테이너 이미지 저장소에 많이 있습니다. 이미지를 처음부터(scratch) 빌드하는 것이 아니라면, Docker의 공식 허브에 있는 이미지를 사용하는 것을 강력히 권장합니다. Docker가 이미지가 모범 사례를 따르는지 검증하고, 정기적인 업데이트와 보안 패치가 적용되도록 보장하기 때문입니다.

Django는 Python 프레임워크이므로, 필요한 도구와 라이브러리가 이미 설치되어 있는 표준 Python 환경의 이미지를 활용할 것입니다. Docker 허브의 Python 이미지 공식 페이지에서 다양한 버전의 Python용 Python 기반 이미지를 찾을 수 있습니다.

우리의 다양한 Docker 기반 튜토리얼을 통해 우리가 Alpine Linux 기반의 이미지를 사용하는 것을 보실 수 있습니다. Alpine Linux는 컨테이너화된 애플리케이션을 실행하기 위한 강력하면서도 슬림한 운영체제 환경을 제공합니다. 파일 시스템은 작지만 확장 가능하며, 기능을 추가할 수 있는 완전한 패키지 관리 시스템이 함께 제공됩니다.

Docker 허브에서 베이스 이미지를 선택할 때 각 이미지에 대해 여러 태그를 사용할 수 있음을 알 수 있습니다. Python의 경우, 3-alpine가 있으며, 이는 최신 Alpine 버전의 최신 Python 3 버전 이미지를 가리킵니다. 즉, 프로젝트가 이전 이미지 버전에서 작동하는 경우 Docker 이미지 관리자가 업데이트를 수행할 때 작동이 중단될 수 있습니다. 향후 이러한 시나리오를 방지하려면 사용하려는 이미지에 대해 가장 구체적인 태그를 선택하는 것이 항상 권장됩니다.

이 튜토리얼에서는 3.8.12-alpine3.15 이미지를 Django 애플리케이션의 베이스 이미지로 사용합니다. 이 특정 태그는 Dockerfile에서 FROM 지시어를 사용하여 지정됩니다. Dockerfile은 메인 프로젝트 디렉터리에 위치하게 됩니다: django_project.

먼저 Django-polls 디렉터리에서 나와 다시 django_project 디렉터리로 이동합니다:

디렉터리에 진입한 후, 선호하는 에디터를 사용하여 다음 파일을 엽니다. Dockerfile :

다음으로, 이미지의 베이스를 설정하기 위해 아래 줄을 붙여넣습니다:

The FROM 키워드는 사용자 정의 Docker 이미지의 시작점을 정의합니다. 이것이 정의되면 애플리케이션을 설정하기 위한 지시어를 계속 추가할 수 있습니다. 이 지시어들은 필요한 의존성을 설치하고, 애플리케이션 파일을 복사하며, 런타임 환경을 설정합니다.

Dockerfile 내부에 다음 코드 스니펫을 추가합니다:

이 코드 스니펫에서는 Docker에게 requirements.txt 파일을 /app/requirements.txt로 복사하도록 지시하여 애플리케이션의 의존성이 이미지의 파일 시스템에서 사용 가능하도록 보장합니다. 요구 사항에는 애플리케이션을 실행하는 데 필요한 모든 Python 패키지가 포함됩니다. Docker가 이미지 레이어를 캐시할 수 있도록 의존성이 먼저 복사됩니다. 이는 Docker가 Dockerfile of 모든 단계를 캐시하기 때문입니다. 이미지의 첫 번째 빌드는 일반적으로 더 오래 걸립니다. Docker는 의존성을 다운로드한 다음 캐시합니다. 만약 requirements.txt 파일이 변경되지 않으면 Docker는 캐시에서 빌드하므로 이후 빌드가 더 빨라집니다.

다음 단계에는 RUN 지시어가 있으며, 이는 Linux && 연산자로 연결된 Linux 명령 목록을 실행합니다. 이 명령들은 다음을 수행합니다:

  • Alpine의 apk 패키지 관리자 도구를 사용하여 PostgreSQL 개발 파일 및 기본 빌드 의존성을 설치합니다.

  • Python 가상 환경을 생성합니다.

  • Install the Python dependencies as defined in the requirements.txt 파일에 정의된 Python 의존성을 다음을 사용하여 설치합니다: pip.

  • 설치된 Python 패키지의 요구 사항을 분석하여 필요한 런타임 패키지를 컴파일합니다.

  • 더 이상 필요하지 않은 빌드 의존성을 제거합니다.

단계에서 명령을 연결하는 이유는 RUN 이미지 레이어를 줄이기 위해서입니다. Docker는 ADD, COPY, 또는 RUN을 만날 때마다 기존 파일 시스템 위에 새로운 이미지 레이어를 생성합니다. 지시어입니다. 가능한 경우 명령을 압축하면 생성되는 이미지 레이어 수가 최소화됩니다.

이미지 레이어에 추가된 항목은 후속 레이어에서 제거할 수 없습니다. 다음 지시어로 이동하기 전에 원하지 않는 항목을 삭제하는 지시어를 선언해야 합니다. 이는 이미지 크기를 줄이기 위해 필요합니다. 우리가 apk del 명령을 RUN 명령의 끝에 추가한 것을 보셨을 것입니다. 이는 앱의 패키지를 빌드하는 데 사용한 후 빌드 종속성을 제거하기 위해 수행되었습니다.

다음으로, 또 다른 ADD 지시어가 있으며, 이를 사용하여 애플리케이션 코드를 /app 디렉터리로 복사합니다. 그런 다음, WORKDIR 지시어를 사용하여 이미지의 작업 디렉터리를 /app 디렉터리로 설정합니다. 이 디렉터리에는 이제 애플리케이션의 코드가 있습니다.

다음으로, 이미지가 실행 중인 컨테이너에서 사용할 수 있도록 두 개의 환경 변수를 설정하는 데 사용하는 ENV 지시어가 있습니다. 먼저, VIRTUAL_ENV 변수를 /env로 설정합니다. 둘째, PATH 변수가 /env/bin 디렉터리를 포함하도록 설정합니다. 이 두 줄에서 우리는 /env/bin/activate 스크립트를 소싱하고 있으며, 이는 Linux 환경에서 가상 환경을 활성화하는 방법입니다. 다른 운영 체제에서 Python 가상 환경을 사용하는 방법에 대해 자세히 알아볼 수 있습니다. 마지막 지시어는 EXPOSE 명령으로, 컨테이너가 런타임에 수신 대기할 포트 8000를 설정합니다.

이제 컨테이너를 시작할 때 실행될 기본 명령을 제외하고 Dockerfile이 거의 완성되었습니다. 다음 섹션에서 이를 정의해 보겠습니다.

  • 기본 Docker 이미지 명령 이해하기

Docker 컨테이너를 시작할 때 실행할 명령을 제공할 수 있습니다. 하지만 명령을 제공하지 않으면 Docker 이미지의 기본 명령이 컨테이너가 시작될 때 수행할 작업을 결정합니다. Dockerfile 내에서 기본 명령을 정의하기 위해 ENTRYPOINT 또는 CMD 지시어를 개별적으로 또는 함께 사용합니다.

만약 ENTRYPOINTCMD를 모두 정의하기로 선택한 경우, ENTRYPOINT 지시어에서는 컨테이너가 실행할 실행 파일을 정의합니다. CMD 지시어에서는 실행 명령에 대한 기본 인수 목록을 정의합니다. 컨테이너를 시작할 때 명령줄에 다음과 같은 형식으로 대체 인수를 추가하여 기본 인수 목록을 재정의할 수 있습니다.

이 형식은 개발자가 ENTRYPOINT 명령을 쉽게 재정의하지 못하도록 방지합니다. ENTRYPOINT 명령은 환경을 설정하고 제공된 인수 목록에 따라 다른 작업을 수행하는 스크립트를 호출하도록 정의됩니다.

컨테이너의 실행 파일을 구성하기 위해 ENTRYPOINT 지시어만 사용할 수도 있습니다. 하지만 이 형식은 기본 인수 목록을 정의할 수 없습니다. docker run 명령으로 컨테이너를 실행할 때 인수를 제공할 수 있습니다.

만약 CMD만 단독으로 사용하기로 선택하면, Docker는 이를 기본 명령 및 인수 목록으로 해석하며, 이는 런타임에 재정의할 수 있습니다. 자세한 내용은 공식 Dockerfile 참조 문서.

에서 확인할 수 있습니다. 기본 명령에 대해 배운 정보를 컨테이너 예제에 어떻게 적용할 수 있는지 살펴보겠습니다. 기본적으로 gunicorn 서버를 사용하여 애플리케이션을 서비스하려고 합니다. gunicorn 서버에 전달되는 인수 목록을 런타임에 구성할 필요는 없지만, 디버깅이나 구성 관리(데이터베이스 초기화, 정적 자산 수집 등)와 같은 목적으로 다른 명령을 실행할 수 있는 유연성을 원합니다. 보시다시피, CMD를 사용하여 기본 명령을 정의하는 것이 가장 좋습니다.

다음은 CMD 명령을 정의하는 데 사용할 수 있는 몇 가지 구문입니다.

  • CMD ["command", "argument 1", "argument 2", . . . ,"argument n"]: exec 형식(권장 형식)은 명령과 인수 목록을 취합니다. 셸 처리 없이 명령을 직접 실행합니다.
  • CMD command "argument 1" "argument 2" . . . "인자 n": 셸 형식은 명령과 인자 목록을 정의합니다. 처리할 명령 목록을 셸에 전달합니다. 명령에서 환경 변수를 대체하려는 경우 이 형식이 유용할 수 있지만, 완전히 예측 가능하지는 않습니다.
  • CMD ["인자 1", "인자 2", . . . ,"인자 n"]: 인자 목록 형식은 기본 인자 목록만 정의하며, 다음과 함께 사용됩니다. ENTRYPOINT 지시어.

우리는 다음을 사용할 것입니다. exec 형식을 사용하여 최종 지시어를 정의합니다. Dockerfile. 다음 줄을 마지막에 추가하세요. Dockerfile:

이제 다음을 저장하고 닫을 수 있습니다. Dockerfile.

이 이미지를 사용하여 컨테이너를 실행하면 다음이 실행됩니다. gunicorn (localhost 포트에 바인딩됨) 8000 (3개의 워커 사용), 그리고 다음을 호출합니다. application 함수 (다음 파일에 위치) wsgi.py 파일 (다음 디렉토리에 위치) mysite 디렉토리. 런타임에 기본 명령을 재정의하고 gunicorn 대신 다른 프로세스를 실행하기 위해 다른 명령을 제공하도록 선택할 수 있습니다. 다음에 대해 더 자세히 알아보고 싶을 수 있습니다: Gunicorn 워커.

이제 Dockerfile이 준비되었으며, 다음을 사용할 수 있습니다. docker build (앱 이미지를 빌드하기 위해). 다음을 사용할 수 있습니다. docker run (로컬 개발 머신에서 컨테이너를 실행하기 위해).

  • Docker 이미지 빌드하기

기본적으로 docker build 명령은 빌드 지시어를 찾기 위해 현재 디렉토리에서 다음을 찾습니다. Dockerfile. 또한 빌드 "컨텍스트(context)"를 Docker 데몬으로 보냅니다. 빌드 컨텍스트는 빌드 프로세스 중에 사용할 수 있어야 하는 파일 집합입니다. 기본적으로 다음 명령을 실행 중인 현재 디렉토리가 docker build 명령의 빌드 컨텍스트로 설정됩니다.

Dockerfile이 포함된 동일한 디렉토리에서 다음 명령을 실행합니다. docker build. 다음 플래그를 사용하여 이미지와 태그를 제공하고, -t 명령 끝에 있는 ( .) 점을 사용하여 현재 디렉토리를 빌드 컨텍스트로 설정합니다:

이 명령에서 이미지 이름을 다음으로 지정하고 django-polls 및 태그를 v1. 명령 끝에 있는 점에 유의하세요. 이 점은 현재 디렉토리를 빌드 컨텍스트로 나타내기 위해 사용됩니다.

다음이 완료되면 docker build 다음과 유사한 출력이 표시됩니다:

Building a Django and Gunicorn Application with Docker on Ubuntu 4

이제 Docker 이미지가 준비되었습니다. 일부 구성을 외부 환경 변수로 분리하지 않았다면, 다음 명령으로 컨테이너를 쉽게 실행할 수 있었을 것입니다. docker run 명령. 하지만 다음 파일에 설정한 외부 환경 변수를 구성하지 않았기 때문에 settings.py 파일의 실행이 실패합니다. 다음 단계에서 이를 마무리하겠습니다.

8단계: 런타임 환경 설정 및 앱 테스트

이 튜토리얼의 끝에 가까워지고 있습니다. 이 단계에서는 다음 파일의 환경 변수를 구성합니다. env 파일. 다음 파일의 env 파일 변수가 준비되면 데이터베이스 스키마를 생성하고, 정적 파일을 생성하여 외부 오브젝트 스토리지 서비스에 업로드한 다음, 마지막으로 앱을 테스트할 수 있습니다.

Docker에는 다음과 같은 여러 방법이 제공됩니다. 환경 변수 제공 (컨테이너에). 우리의 경우, 파일을 통해 환경 변수 목록을 제공하고자 합니다. 따라서 다음 방법을 사용할 것입니다. --env-file 방법.

선호하는 편집기를 사용하여 이름이 다음과 같은 파일을 생성합니다. env (다음 디렉토리에 위치): django_project 디렉토리:

다음 변수 목록을 붙여넣습니다:

목록의 변수들은 이전 단계에서 정의한 변수들입니다:

  • DJANGO_SECRET_KEY: 다음에서 설명하는 대로 고유하고 예측할 수 없는 값을 생성합니다: Django 문서. 이 명령을 사용하여 무작위 문자열을 생성하고 변수에 설정할 수 있습니다:

  • DEBUG: 이 값을 다음과 같이 설정했습니다. True, 하지만 프로덕션 배포의 경우 다음과 같이 설정해야 합니다. False (비워 둠으로써).

  • DJANGO_LOGLEVEL: 이 값을 다음과 같이 설정했습니다. info, 원하는 수준으로 자유롭게 조정하십시오.

  • DJANGO_ALLOWED_HOSTS: 이 값을 Docker 컨테이너를 실행하는 Ubuntu 서버의 IP 주소로 설정합니다. 선택적으로 다음과 같이 설정할 수 있습니다. *, 개발 모드인 경우 모든 호스트와 일치하는 와일드카드입니다.

  • DB_DATABASE: 다른 데이터베이스 이름을 사용한 경우 여기에 적절하게 설정하십시오.

  • DB_USERNAME: 이를 데이터베이스에 대해 선택한 사용자 이름으로 설정합니다.

  • DB_PASSWORD: 이를 데이터베이스에 대해 선택한 비밀번호로 설정합니다.

  • DB_HOST: 이를 다음에서 설정한 대로 데이터베이스 인스턴스를 실행하는 호스트로 설정합니다. 1단계.

  • DB_PORT: 이를 데이터베이스의 포트로 설정합니다.

  • STATIC_MINIO_BUCKET_NAME: 이를 MinIO 클라우드 스토리지 계정에서 생성한 버킷 이름으로 설정합니다.

편집을 마치면 파일을 저장하고 닫습니다.

이제 환경 구성이 준비되었습니다. 기본 CMD 명령을 재정의하는 인수를 전달하여 컨테이너를 실행하고, 다음 명령을 사용하여 데이터베이스 스키마를 생성해야 합니다. manage.py makemigrationsmanage.py migrate 명령.

명령은 다음과 같습니다:

이 명령에서는 django-polls:v1 컨테이너 이미지를 실행하고 있으며, env-file 플래그를 사용하여 환경 변수 파일을 전달합니다. 또한 기본 CMD 명령을 다음과 같이 재정의합니다. sh -c "python manage.py makemigrations && python manage.py migrate" 컨테이너를 시작하기 위해 이 명령을 실행하면 애플리케이션 코드에 정의된 대로 데이터베이스 스키마가 생성됩니다.

성공하면 다음과 유사한 출력이 표시됩니다.

Building a Django and Gunicorn Application with Docker on Ubuntu 4

출력은 데이터베이스 스키마가 성공적으로 생성되었음을 나타냅니다.

다음 단계는 Django 앱의 관리 사용자를 생성하는 것입니다. 다음 명령을 사용하여 컨테이너를 가동하고 내부에서 대화형 셸을 시작합니다:

이 명령은 Python 셸과 상호 작용하는 데 사용할 수 있는 셸 프롬프트와 함께 컨테이너를 시작합니다. 사용자를 생성해 보겠습니다:

프롬프트에 따라 사용자 이름, 이메일 주소, 비밀번호를 입력하고 비밀번호를 다시 입력한 후 엔터를 눌러 사용자를 생성합니다. 다음을 눌러 셸을 종료하고 컨테이너를 종료합니다. CTRL+D.

다음으로, 기본 명령을 다음으로 재정의하여 컨테이너를 다시 실행해야 합니다. collectstatic Django 명령을 사용하여 앱의 정적 파일을 생성하고 MinIO 클라우드 스토리지 서비스에 업로드합니다:

완료되면 아래와 유사한 출력이 표시되며, 이는 컨테이너가 MinIO 스토리지 서비스에 성공적으로 연결되어 정적 파일을 업로드했음을 나타냅니다:

static files

이제 스토리지 버킷은 Django가 생성한 디렉터리와 함께 다음과 같이 보입니다:

Building a Django and Gunicorn Application with Docker on Ubuntu 5

마지막으로, 이제 다음 명령어로 앱을 실행할 수 있습니다:

출력 결과는 다음과 같습니다:

output

위 명령어를 실행하면 이미지의 기본 CMD 명령어가 실행되고 정의된 대로 포트 8000가 노출됩니다. 이제 포트의 Ubuntu가 80 포트로 매핑되며, 이는 8000 port of the django-polls:v1 컨테이너의 포트입니다.

이제 브라우저에서 애플리케이션을 테스트할 수 있습니다. 브라우저에서 서버의 퍼블릭 IP 주소로 이동하세요: http://your_server_public_ip.

404 Page Not Found 에러가 발생할 것입니다. Django 튜토리얼에 따르면, 다음 경로에 대한 라우트를 정의하지 않았기 때문입니다: / 경로:

page not found

현재 DEBUG 변수가 True로 설정되어 있기 때문에 중요한 정보가 많이 포함된 이 에러 페이지가 표시됩니다. DEBUG 변수 설정을 해제해 보겠습니다. 먼저 실행 중인 컨테이너를 CTRL+C로 중지해야 합니다. 그런 다음 env 파일을 엽니다:

다음으로 DEBUG 변수를 찾아 설정을 해제하거나 비워 둡니다. getenv 함수는 False를 문자열로 해석하여 true를 반환하기 때문에 비워 두는 것입니다:

파일을 저장하고 다음 명령어로 컨테이너를 다시 실행합니다:

브라우저에서 이 http://your_server_public_ip 주소에 접속하면 기본 404 페이지가 표시되어야 합니다:

not found

소스 코드를 수정하지 않고 환경 변수를 사용하여 Django 앱의 런타임 동작을 제어하는 방법을 살펴보았습니다.

다음 주소로 이동하여 http://your_server_public_ip/polls 설문조사(Polls) 홈 페이지를 확인하세요:

Building a Django and Gunicorn Application with Docker on Ubuntu 6

앱을 방금 배포했기 때문에 아직 등록된 설문조사가 없습니다.

관리자 인터페이스인 http://your_server_public_ip/admin 으로 이동하여 관리자 인증 창을 확인하세요:

polls administration

로그인하려면 명령어로createsuperuser 설정한 자격 증명을 입력하세요. 이제 관리 페이지 인터페이스로 이동하게 됩니다:

site administration

모든 정적 파일은 우리가 설정한 외부 스토리지 서비스에서 제공된다는 점에 유의하세요. 브라우저 창에서 마우스 우클릭을 한 후 페이지 소스 보기를 선택할 수 있습니다.:

external storage

질문과 선택지를 추가하고 앱의 전반적인 성능을 테스트할 수 있습니다:

questions and choices

다시 설문조사 인덱스인 http://your_server_public_ip/polls 로 돌아가서 질문에 투표해 보세요:

django framework

모든 것이 예상대로 작동하는지 테스트하고 확인한 후 컨테이너를 종료할 수 있습니다.

결론

컨테이너 기반 환경에서 잘 작동하도록 Django 웹 앱을 성공적으로 구성했습니다. 이 과정에는 외부 환경 변수와 연동되도록 앱을 조정하고, 정적 파일에 클라우드 스토리지 서비스를 사용하도록 설정하고, 컨테이너 이미지를 위한 Dockerfile을 생성하는 작업이 포함되었습니다. 앱을 도커화하기 위해 변경한 사항은 django-polls-docker 브랜치에서 확인할 수 있습니다. 이 브랜치는 django-polls GitHub 리포지토리에 있습니다.

이제부터는 상상하는 모든 것이 가능합니다. 클라이언트와 Gunicorn 서버 사이에 Nginx 리버스 프록시를 설정할 수 있습니다. 또한 Certbot을 추가하여 TLS 인증서를 획득하고 Nginx 서버를 보호할 수도 있습니다. 느린 클라이언트를 버퍼링하고 서비스 거부(DoS) 공격으로부터 Gunicorn 서버를 보호하기 위해 HTTP 프록시를 추가하는 것을 권장합니다.

Dockerfile의 시작 명령어에서 3개의 워커를 정의했지만, 서버에서 사용 가능한 리소스에 따라 원하는 숫자로 설정할 수 있습니다. 자세한 정보는 공식 Gunicorn 디자인 문서에서 확인할 수 있습니다. 원한다면 빌드한 Docker 이미지를 Docker Hub에 푸시하고 Docker가 설치된 여러 환경에 배포해 볼 수 있습니다. 더 자세히 알아보고 싶다면 저희 튜토리얼 블로그를 계속 확인해 주세요. Nginx와 Let's Encrypt를 사용하여 Django 앱을 안전하게 보호하는 후속 튜토리얼을 진행할 예정입니다.

마지막으로, Docker를 활용하는 데 도움이 되는 추가 리소스는 다음과 같습니다:

즐거운 컴퓨팅 되세요!

author

Shreyas Patil

작성자 · CloudSigma

Preslav Dobrev는 CloudSigma의 크리에이티브 디자이너로서, 전통적이고 혁신적인 마케팅 채널을 활용하여 일관된 비즈니스 정체성을 구축하는 데 중점을 두고 있습니다. 그는 영향력 있는 브랜드 내러티브를 창출하기 위해 예술적 비전과 전략적 마케팅을 결합하는 데 능숙합니다.

댓글

아직 댓글이 없습니다. 첫 번째로 작성해 보세요.