首页  >  文章  >  后端开发  >  如何使用 Hetzner 和 Dokku 在预算内部署 Django

如何使用 Hetzner 和 Dokku 在预算内部署 Django

WBOY
WBOY原创
2024-08-29 18:33:02358浏览

部署 Django 应用程序可能具有挑战性,尤其是在选择正确的基础设施时。

Hetzner 与 Dokku 相结合,提供了强大而灵活的解决方案,使部署过程变得更加容易。

Dokku 是一个基于 Docker 构建的平台即服务 (PaaS),可让您轻松部署、管理和扩展应用程序。

本指南将向您展示如何使用 Dokku 将 Django 应用程序部署到 Hetzner。


Hetzner 和 Dokku 是什么?

Hetzner 是一家德国公司,提供各种网络托管服务,例如专用服务器、云托管、虚拟专用服务器 (VPS) 和托管服务。

它们以以实惠的价格提供高性能基础设施而闻名,使其深受开发人员、企业和技术爱好者的欢迎。

Hetzner 的数据中心主要位于德国和芬兰(还有美国和现在的新加坡),提供强大的安全性、可靠性和可扩展的解决方案。

他们因其经济高效的云托管选项而特别受到青睐,使他们成为欧洲托管市场的强大竞争对手。

多库

Dokku 是一个开源工具,可以轻松部署和管理 Web 应用程序。

它使用 Docker,并允许您使用 Git 部署应用程序,类似于 Heroku。 Dokku 可与多种编程语言和框架配合使用,并且可以处理数据库、SSL 证书等。

它轻量级且易于在服务器上设置,这使其成为想要像 Heroku 这样的自托管解决方案但具有更多控制力和灵活性的开发人员的流行选择。


您是否厌倦了编写相同的旧 Python 代码?想要将您的编程技能提升到一个新的水平吗?别再犹豫了!本书是初学者和经验丰富的 Python 开发人员的终极资源。

获取“Python 的神奇方法 - 超越 initstr

魔术方法不仅仅是语法糖,它们是可以显着提高代码功能和性能的强大工具。通过本书,您将学习如何正确使用这些工具并释放 Python 的全部潜力。


先决条件

在我们开始部署过程之前,请确保您具备以下条件:

  • Django 应用程序:您的 Django 应用程序应该已准备好部署。它应包含一个requirements.txt 文件和一个Procfile。
  • Hetzner 云帐户:如果您没有,可以在 Hetzner 注册。
  • GitHub 帐户:能够部署您的应用程序。
  • 基本命令行知识:您应该能够轻松使用终端。

第 1 步 - 在 Hetzner 中创建 VPS

首先在 Hetzner 云中创建 VPS(虚拟专用服务器)。如果您没有帐户,可以在这里注册。

进入云控制台后:

  • 创建一个新项目,我们将其命名为 Hetzner Dokku。 进入项目并添加服务器。
  • 对于位置,我们选择赫尔辛基(欧盟中部)。
  • 对于 Image,我们选择 Ubuntu 22.04(在撰写本文时,Dokku 不支持 24.04)
  • 对于类型,我们选择共享 CPU、x86 和 CX22(2vCPUS、4GB RAM、40GB SSD)。
  • 对于网络,我们保留 IPv4 和 IPv6。
  • 对于 SSH 密钥,您应该添加您的 SSH 密钥。如果没有,可以使用 ssh-keygen 生成。
  • 您现在可以放弃其他选项。稍后您可以根据需要激活防火墙。
  • 最后,给它起个名字,在本例中,我们称之为 dokku-server。

然后单击“立即创建并购买”。几秒钟后,您的 VPS 应该启动并运行,并且可以通过指定的 IP 地址通过 SSH 进行访问:

ssh root@<ip_address>

第 2 步 - 安装 Dokku

现在 VPS 已配置并运行,您可以安装 Dokku。在此之前,更新 V​​PS 是一个很好的策略,您可以使用:

apt update && apt upgrade -y

如有必要,请重新启动 VPS。

安装 Dokku

您现在可以安装 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 镜像。

安装后您应该重新启动服务器,以确保所有软件包都处于活动状态并正在运行。

设置 SSH 密钥和虚拟主机设置

为了访问应用程序,建议拥有域名。但您也可以使用支持子域的 IP 地址 https://sslip.io/。

首先,您需要将 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.


Step 3 - Creating the application in Dokku

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

Step 4 - Creating the Django application

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:

  • python-decouple for managing configuration settings.
  • dj-database-url for simplifying database configuration in Django.
  • gunicorn for serving Python web applications in production.
  • whitenoise to manage access to static files.
  • psycopg2-binary to allow access to Postgres databases.

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:

  • Database Configuration: Uses dj_database_url and decouple to parse the database URL from environment variables.
  • Allowed Hosts: Allows the application to be served from any host (useful for development), but should not be used in Production.
  • Middleware: Includes Django's security middleware and WhiteNoise middleware for serving static files.
  • Static Files: Configures the URL, root directory, additional directories, and storage backend for static files using WhiteNoise.

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:

  • web: gunicorn DjangoAppDokku.wsgi: Starts the Gunicorn web server to handle incoming HTTP requests using the WSGI application defined in DjangoAppDokku.wsgi.
  • release: python manage.py migrate: Runs Django's database migrations as part of the release process, ensuring that the database schema is up-to-date with the latest code changes.

The last set is to make sure that the requirements file is up to date:

pip freeze > requirements.txt

Step 5 - Deploying the Django application to Dokku

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:

  • 安装了最新的Python版本。
  • 安装了requirements.txt 文件中的要求。
  • 使用 python manage.pycollectstatic --noinput 收集静态。
  • 使用 python manage.py migrate 迁移数据库(在 Procfile 中定义)。
  • 启动了gunicorn服务器。

如果您现在访问指定的 URL,您应该会看到熟悉的 Django 默认页面:

How to Deploy Django on a Budget with Hetzner and Dokku

就是这样。这就是将 Django 应用程序部署到 Dokku 所需的全部内容。

这些设置非常适合测试应用程序并为测试版用户提供访问权限,但对于生产用途,您应该向应用程序添加域名并启用 SSL,请查看 Dokku 文档以获取更多信息。


结论

您已使用 Dokku 成功将 Django 应用程序部署到 Hetzner。

得益于 Dokku 简单而强大的功能,此设置可以轻松扩展和管理您的应用程序。

现在您的应用程序已部署,您可以专注于改进和扩展它,因为知道它正在可靠的基础设施上运行。

以上是如何使用 Hetzner 和 Dokku 在预算内部署 Django的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn