Django 애플리케이션 배포는 특히 올바른 인프라를 선택할 때 어려울 수 있습니다.
Dokku와 결합된 Hetzner는 배포 프로세스를 더 쉽게 만드는 강력하고 유연한 솔루션을 제공합니다.
Docker를 기반으로 구축된 PaaS(Platform-as-a-Service)인 Dokku를 사용하면 애플리케이션을 쉽게 배포, 관리 및 확장할 수 있습니다.
이 가이드에서는 Dokku를 사용하여 Django 애플리케이션을 Hetzner에 배포하는 방법을 보여줍니다.
헤츠너(Hetzner)는 전용 서버, 클라우드 호스팅, 가상 사설 서버(VPS), 코로케이션 서비스 등 다양한 웹 호스팅 서비스를 제공하는 독일 회사입니다.
저렴한 가격에 고성능 인프라를 제공하는 것으로 알려져 개발자, 기업, 기술 애호가들 사이에서 인기가 높습니다.
Hetzner의 데이터 센터는 주로 독일과 핀란드(미국과 싱가포르에도 위치)에 위치해 있으며 강력한 보안, 신뢰성 및 확장 가능한 솔루션을 제공합니다.
특히 비용 효율적인 클라우드 호스팅 옵션으로 많은 사랑을 받고 있으며, 이는 유럽 호스팅 시장에서 강력한 경쟁자로 자리매김하고 있습니다.
Dokku는 웹 애플리케이션을 쉽게 배포하고 관리할 수 있는 오픈 소스 도구입니다.
Docker를 사용하며 Heroku와 유사한 Git으로 앱을 배포할 수 있습니다. Dokku는 다양한 프로그래밍 언어 및 프레임워크와 함께 작동하며 데이터베이스, SSL 인증서 등을 처리할 수 있습니다.
가벼워서 서버에 설치하기가 간단하므로 Heroku와 같은 자체 호스팅 솔루션을 원하지만 더 많은 제어력과 유연성을 원하는 개발자에게 인기 있는 선택입니다.
똑같은 Python 코드를 작성하는 데 지치셨나요? 프로그래밍 기술을 한 단계 더 발전시키고 싶으신가요? 더 이상 보지 마세요! 이 책은 초보자와 숙련된 Python 개발자 모두를 위한 최고의 리소스입니다.
"Python의 Magic Methods - Beyond init 및 str"
가져오기매직 메서드는 단순한 구문 설탕이 아니라 코드의 기능과 성능을 크게 향상시킬 수 있는 강력한 도구입니다. 이 책을 통해 이러한 도구를 올바르게 사용하는 방법을 배우고 Python의 잠재력을 최대한 활용하게 될 것입니다.
배포 프로세스를 시작하기 전에 다음 사항을 확인하세요.
헤츠너 클라우드에 VPS(Virtual Private Server)를 만드는 것부터 시작해 보세요. 계정이 없다면 여기에서 가입할 수 있습니다.
클라우드 콘솔에서 한 번:
그런 다음 지금 만들기 및 구매를 클릭하세요. 몇 초 후에 VPS가 실행되고 표시된 IP 주소에서 SSH를 통해 액세스할 수 있습니다.
ssh root@<ip_address>
이제 VPS가 구성 및 실행되었으므로 Dokku를 설치할 수 있습니다. 그 전에 VPS를 업데이트하는 것이 좋은 정책입니다.
apt update && apt upgrade -y
필요한 경우 VPS를 다시 시작하세요.
이제 Dokku를 설치할 수 있습니다:
wget -NP . https://dokku.com/install/v0.34.8/bootstrap.sh sudo DOKKU_TAG=v0.34.8 bash bootstrap.sh
작성 당시 최신 버전은 v0.34.8이었습니다. 최신 버전은 Dokku 홈페이지에서 확인하세요.
배포 프로세스를 지원하는 Docker 이미지 두 개도 가져와야 하므로 몇 분 정도 걸릴 수 있습니다.
모든 패키지가 활성화되어 실행 중인지 확인하려면 설치 후 서버를 다시 시작해야 합니다.
애플리케이션에 액세스하려면 도메인 이름을 갖는 것이 좋습니다. 하지만 https://sslip.io/에서 하위 도메인을 지원하는 IP 주소를 사용할 수도 있습니다.
먼저 SSH 키를 Dokku SSH 관리자 키에 복사해야 합니다.
cat ~/.ssh/authorized_keys | dokku ssh-keys:add admin
그런 다음 도메인이나 IP 주소를 설정할 수 있습니다.
dokku domains:set-global <ip_address>.sslip.io
In this case, it defines the IP address, but with support for sub-domains with sslip.io.
With Dokku installed and configured, you can now create the application in Dokku that will receive your Django application:
dokku apps:create django-app
This command creates an app called django-app.
Django requires a database and normally there is two choices, either a SQLite or Postgres database.
On Dokku, databases are part of the plugin packages and need to be installed separately:
dokku plugin:install https://github.com/dokku/dokku-postgres.git
This command will install Postgres by downloading the supporting Docker images.
To actually create a database that you can use with the recently created application, you can use the command:
dokku postgres:create django-app-db
Once the the database is created, you will need to link it to the Dokku application:
dokku postgres:link django-app-db django-app
Linked the database to the application means that the database URL is added to the environment variables of the application definitions in Dokku.
You can check that with the command:
dokku config:show django-app
Which should give a similar response to this:
=====> django-app env vars DATABASE_URL: postgres://postgres:bca0d7f59caf98c78a74d58457111a1e@dokku-postgres-django-app-db:5432/django_app_db
With Dokku installed, configured and an application created, you are now ready to create the actual Django application.
There are several guides on the Internet on how to create a Django application from scratch, so the focus on this article is on deploying the application to Django.
For this tutorial, I created a Django application in PyCharm using the default settings called DjangoAppDokku.
To be able to deploy the application to Dokku, there is some preparation steps that are necessary.
Let's start with making sure there is a requirements file with the command:
pip freeze > requirements.txt
Then you can install some necessary packages to prepare for the Dokku deploying:
pip install python-decouple dj-database-url gunicorn whitenoise psycopg2-binary
This installs three useful packages:
Now you can create the environment variable file on a file called .env:
DATABASE_URL=sqlite:///db.sqlite3
This configures (for local use) a database URL using SQLite. When the application is deployed to Django it will use the URL defined in Dokku, as we have seen before.
For that to be possible, you need to make some changes in the settings.py file:
import dj_database_url import os from decouple import config from django.conf.global_settings import DATABASES ... ALLOWED_HOSTS = ['*'] ... MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', "whitenoise.middleware.WhiteNoiseMiddleware", ... all others middleware ... ] ... DATABASES['default'] = dj_database_url.parse(config('DATABASE_URL'), conn_max_age=600) ... STATIC_URL = 'static/' STATIC_ROOT = BASE_DIR / "static" STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'staticfiles'), ) STATICFILES_STORAGE = 'whitenoise.storage.CompressedStaticFilesStorage'
This code snippet configures various settings for a Django application:
For Dokku to know how to run the Django application and how to migrate the database, yo will need to create a Procfile:
web: gunicorn DjangoAppDokku.wsgi release: python manage.py migrate
The Procfile defines two important processes for your Django application, which Dokku will execute:
The last set is to make sure that the requirements file is up to date:
pip freeze > requirements.txt
With the Django application and the Dokku application prepared, you can now deploy the application to Dokku.
First you will need create a new repository on GitHub then you can add the Django application to it.
So, on your Django project directory, open a terminal and execute these commands:
echo "# DjangoAppDokku" >> README.md git init git add . git commit -m "First Commit" git branch -M main git remote add origin [Your GitHub repository URL] git push -u origin main
Now you add a new git remote for the Dokku server:
git remote add dokku dokku@<your_server_ip>:<your_dokku_app_name>
And finally deploy the application with:
git push dokku
This will produce an output similar to this:
Enumerating objects: 23, done. Counting objects: 100% (23/23), done. Delta compression using up to 8 threads Compressing objects: 100% (21/21), done. Writing objects: 100% (23/23), 5.48 KiB | 160.00 KiB/s, done. Total 23 (delta 8), reused 0 (delta 0), pack-reused 0 -----> Cleaning up... -----> Building django-app from herokuish -----> Adding BUILD_ENV to build environment... BUILD_ENV added successfully -----> Python app detected -----> No Python version was specified. Using the buildpack default: python-3.12.5 To use a different version, see: https://devcenter.heroku.com/articles/python-runtimes -----> Requirements file has been changed, clearing cached dependencies -----> Installing python-3.12.5 -----> Installing pip 24.0, setuptools 70.3.0 and wheel 0.43.0 -----> Installing SQLite3 -----> Installing requirements with pip Collecting asgiref==3.8.1 (from -r requirements.txt (line 1)) Downloading asgiref-3.8.1-py3-none-any.whl.metadata (9.3 kB) Collecting dj-database-url==2.2.0 (from -r requirements.txt (line 2)) Downloading dj_database_url-2.2.0-py3-none-any.whl.metadata (12 kB) Collecting Django==5.1 (from -r requirements.txt (line 3)) Downloading Django-5.1-py3-none-any.whl.metadata (4.2 kB) Collecting psycopg2-binary==2.9.9 (from -r requirements.txt (line 4)) Downloading psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.4 kB) Collecting python-decouple==3.8 (from -r requirements.txt (line 5)) Downloading python_decouple-3.8-py3-none-any.whl.metadata (14 kB) Collecting sqlparse==0.5.1 (from -r requirements.txt (line 6)) Downloading sqlparse-0.5.1-py3-none-any.whl.metadata (3.9 kB) Collecting typing_extensions==4.12.2 (from -r requirements.txt (line 7)) Downloading typing_extensions-4.12.2-py3-none-any.whl.metadata (3.0 kB) Collecting tzdata==2024.1 (from -r requirements.txt (line 8)) Downloading tzdata-2024.1-py2.py3-none-any.whl.metadata (1.4 kB) Collecting whitenoise==6.7.0 (from -r requirements.txt (line 9)) Downloading whitenoise-6.7.0-py3-none-any.whl.metadata (3.7 kB) Downloading asgiref-3.8.1-py3-none-any.whl (23 kB) Downloading dj_database_url-2.2.0-py3-none-any.whl (7.8 kB) Downloading Django-5.1-py3-none-any.whl (8.2 MB) Downloading psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.0 MB) Downloading python_decouple-3.8-py3-none-any.whl (9.9 kB) Downloading sqlparse-0.5.1-py3-none-any.whl (44 kB) Downloading typing_extensions-4.12.2-py3-none-any.whl (37 kB) Downloading tzdata-2024.1-py2.py3-none-any.whl (345 kB) Downloading whitenoise-6.7.0-py3-none-any.whl (19 kB) Installing collected packages: python-decouple, whitenoise, tzdata, typing_extensions, sqlparse, psycopg2-binary, asgiref, Django, dj-database-url Successfully installed Django-5.1 asgiref-3.8.1 dj-database-url-2.2.0 psycopg2-binary-2.9.9 python-decouple-3.8 sqlparse-0.5.1 typing_extensions-4.12.2 tzdata-2024.1 whitenoise-6.7.0 -----> $ python manage.py collectstatic --noinput System check identified some issues: WARNINGS: ?: (staticfiles.W004) The directory '/tmp/build/staticfiles' in the STATICFILES_DIRS setting does not exist. 127 static files copied to '/tmp/build/static'. -----> Discovering process types Procfile declares types -> release, web -----> Releasing django-app... -----> Checking for predeploy task No predeploy task found, skipping -----> Checking for release task Executing release task from Procfile in ephemeral container: python manage.py migrate =====> Start of django-app release task (ae9dc2b83) output remote: ! System check identified some issues: remote: ! WARNINGS: remote: ! ?: (staticfiles.W004) The directory '/app/staticfiles' in the STATICFILES_DIRS setting does not exist. Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying auth.0012_alter_user_first_name_max_length... OK Applying sessions.0001_initial... OK =====> End of django-app release task (ae9dc2b83) output -----> Checking for first deploy postdeploy task No first deploy postdeploy task found, skipping =====> Processing deployment checks remote: ! No healthchecks found in app.json for web process type No web healthchecks found in app.json. Simple container checks will be performed. For more efficient zero downtime deployments, add healthchecks to your app.json. See https://dokku.com/docs/deployment/zero-downtime-deploys/ for examples -----> Deploying django-app via the docker-local scheduler... -----> Deploying web (count=1) Attempting pre-flight checks (web.1) -----> Executing 2 healthchecks Running healthcheck name='default' type='uptime' uptime=10 Running healthcheck name='port listening check' attempts=3 port=8000 retries=2 timeout=5 type='listening' wait=5 Healthcheck succeeded name='port listening check' Healthcheck succeeded name='default' All checks successful (web.1) =====> Start of django-app container output (8d55f0f3b481 web.1) Python buildpack: Couldn't determine available memory. Skipping automatic configuration of WEB_CONCURRENCY. [2024-08-29 08:32:56 +0000] [14] [INFO] Starting gunicorn 23.0.0 [2024-08-29 08:32:56 +0000] [14] [INFO] Listening at: http://0.0.0.0:8000 (14) [2024-08-29 08:32:56 +0000] [14] [INFO] Using worker: sync [2024-08-29 08:32:56 +0000] [153] [INFO] Booting worker with pid: 153 =====> End of django-app container output (8d55f0f3b481 web.1) =====> Triggering early nginx proxy rebuild -----> Ensuring network configuration is in sync for django-app -----> Configuring django-app.<ip_address>.sslip.io...(using built-in template) -----> Creating http nginx.conf Reloading nginx -----> Running post-deploy -----> Ensuring network configuration is in sync for django-app -----> Configuring django-app.<ip_address>.sslip.io...(using built-in template) -----> Creating http nginx.conf Reloading nginx -----> Checking for postdeploy task No postdeploy task found, skipping =====> Application deployed: http://django-app.<ip_address>.sslip.io To <ip_address>:django-app * [new branch] master -> master
Dokku has performed the following actions to deploy the application:
이제 표시된 URL로 이동하면 익숙한 Django 기본 페이지가 표시됩니다:
그리고 그게 다입니다. 이것이 Django 애플리케이션을 Dokku에 배포하는 데 필요한 전부입니다.
이러한 설정은 애플리케이션을 테스트하고 베타 사용자에게 액세스를 제공하는 데 유용하지만, 프로덕션 용도로 사용하려면 애플리케이션에 도메인 이름을 추가하고 SSL을 활성화해야 합니다. 자세한 내용은 Dokku 문서를 확인하세요.
Dokku를 사용하여 Django 애플리케이션을 Hetzner에 성공적으로 배포했습니다.
이 설정을 사용하면 Dokku의 단순하면서도 강력한 기능 덕분에 애플리케이션을 쉽게 확장하고 관리할 수 있습니다.
이제 애플리케이션이 배포되었으므로 애플리케이션이 안정적인 인프라에서 실행되고 있음을 확인하여 개선 및 확장에 집중할 수 있습니다.
위 내용은 Hetzner 및 Dokku를 사용하여 예산에 맞게 Django를 배포하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!