Python开始Heroku入门

Heroku简介

Heroku 是 Salesforce 旗下云服务商,提供方便便捷的各种云服务,如服务器,数据库,监控,计算等等。

Heroku 提供了免费版本,这使得想搞一些小东西的人提供了莫大的便捷,虽然他有时长和宕机的限制,但是对于个人程序来说已经足够了。

快速入门

本部分需要以下准备工作

  • 免费的Heroku账号
  • 本地安装的 Python 3.7
  • 如果在本地运行应用程序,则在本地安装 Postgres
  • 不知道 Postgres 是干啥的

设置

准备工作

  • Git 的安装
  • Git 的设置

安装Heroku的命令行界面

安装完成后-登陆

1
2
3
4
heroku login
Enter your Heroku credentials.
email:
Password:

如果您位于需要使用代理连接外部HTTP / HTTPS服务的防火墙后面,则可以HTTP_PROXYHTTPS_PROXY在运行该heroku命令之前在本地开发环境中设置或环境变量。

准备应用程序

准备一个可以部署的简单应用程序。

克隆示例应用程序以便您拥有可以部署到Heroku的本地版本的代码,请在本地命令shell或终端中执行以下命令:

1
2
git clone https://github.com/heroku/python-getting-started.git
cd python-getting-started

你现在有一个功能正常的git存储库,它包含一个简单的应用程序。

  • runtime.txt指定Python 3.7.0
  • requirements.txt由Python的依赖管理器Pip使用的。

部署应用程序

创建应用程序

1
heroku create

结果:

1
2
3
heroku create <appname>
Creating app... done, ⬢ serene-caverns-82714
https://<appname:serene-caverns-82714>.herokuapp.com/ | https://git.heroku.com/<appname:serene-caverns-82714.git>

创建一个app时候也会创建一个 git remote(已调用)并与您的本地git存储库关联

appname 后面是生成的随机名称

部署你的代码

1
git push heroku master

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
git push heroku master
Counting objects: 407, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (182/182), done.
Writing objects: 100% (407/407), 68.65 KiB | 68.65 MiB/s, done.
Total 407 (delta 199), reused 407 (delta 199)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Python app detected
remote: Using supported version of Python 3.7 (python-3.7.0)
remote: -----> Installing python-3.7.0
remote: -----> Installing pip
remote: -----> Installing SQLite3
remote: -----> Installing requirements with pip
remote: Collecting django (from -r /tmp/build_394859b69f6aeb1b63e599ce5b6c69bd/requirements.txt (line 1))
remote: Downloading https://files.pythonhosted.org/packages/32/ab/22530cc1b2114e6067eece94a333d6c749fa1c56a009f0721e51c181ea53/Django-2.1.2-py3-none-any.whl (7.3MB)
remote: Collecting gunicorn (from -r /tmp/build_394859b69f6aeb1b63e599ce5b6c69bd/requirements.txt (line 2))
remote: Downloading https://files.pythonhosted.org/packages/8c/da/b8dd8deb741bff556db53902d4706774c8e1e67265f69528c14c003644e6/gunicorn-19.9.0-py2.py3-none-any.whl (112kB)
remote: Collecting django-heroku (from -r /tmp/build_394859b69f6aeb1b63e599ce5b6c69bd/requirements.txt (line 3))
remote: Downloading https://files.pythonhosted.org/packages/59/af/5475a876c5addd5a3494db47d9f7be93cc14d3a7603542b194572791b6c6/django_heroku-0.3.1-py2.py3-none-any.whl
remote: Collecting pytz (from django->-r /tmp/build_394859b69f6aeb1b63e599ce5b6c69bd/requirements.txt (line 1))
remote: Downloading https://files.pythonhosted.org/packages/30/4e/27c34b62430286c6d59177a0842ed90dc789ce5d1ed740887653b898779a/pytz-2018.5-py2.py3-none-any.whl (510kB)
remote: Collecting psycopg2 (from django-heroku->-r /tmp/build_394859b69f6aeb1b63e599ce5b6c69bd/requirements.txt (line 3))
remote: Downloading https://files.pythonhosted.org/packages/37/88/40748331bf75d068a07bbea7dc658faceb0ce2e9fffdde550e76d5475e59/psycopg2-2.7.5-cp37-cp37m-manylinux1_x86_64.whl (2.7MB)
remote: Collecting dj-database-url>=0.5.0 (from django-heroku->-r /tmp/build_394859b69f6aeb1b63e599ce5b6c69bd/requirements.txt (line 3))
remote: Downloading https://files.pythonhosted.org/packages/d4/a6/4b8578c1848690d0c307c7c0596af2077536c9ef2a04d42b00fabaa7e49d/dj_database_url-0.5.0-py2.py3-none-any.whl
remote: Collecting whitenoise (from django-heroku->-r /tmp/build_394859b69f6aeb1b63e599ce5b6c69bd/requirements.txt (line 3))
remote: Downloading https://files.pythonhosted.org/packages/07/2e/c77e71cb448f1a507bc2dfec1d5c24e35d14a737837bea6cdfd6d1ff66bd/whitenoise-4.1-py2.py3-none-any.whl
remote: Installing collected packages: pytz, django, gunicorn, psycopg2, dj-database-url, whitenoise, django-heroku
remote: Successfully installed dj-database-url-0.5.0 django-2.1.2 django-heroku-0.3.1 gunicorn-19.9.0 psycopg2-2.7.5 pytz-2018.5 whitenoise-4.1
remote:
remote: -----> $ python manage.py collectstatic --noinput
remote: 120 static files copied to '/tmp/build_394859b69f6aeb1b63e599ce5b6c69bd/staticfiles', 376 post-processed.
remote:
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 57.1M
remote: -----> Launching...
remote: Released v5
remote: https://serene-caverns-82714.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/serene-caverns-82714.git
* [new branch] revert-to-requirements -> master

该应用程序现已部署。确保至少有一个应用程序实例正在运行:

1
heroku ps:scale web=1

现在,通过其应用名称生成的网址访问该应用。作为一个方便的快捷方式,您可以按如下方式打开网站:

1
heroku open

查看日志

Heroku将日志视为从所有app和Heroku组件的输出流聚合的时间排序事件流,为所有事件提供单个通道。

1
heroku logs --tail

查看有关您使用的一个运行应用程序的信息记录命令heroku logs --tail

再次在浏览器中访问您的应用程序,您将看到生成的另一条日志消息。

Procfile 扩展

使用Procfile声明各种流程类型,包括:

  • 您应用的网络服务器
  • 多种类型的工作进程
  • 单例过程,例如时钟
  • 部署新版本之前要运行的任务

在根目录中用来声明应该启动的服务

例:

1
web: gunicorn gettingstarted.wsgi --log-file -

这声明了一个进程类型,web以及运行它所需的命令。这个名字web在这里很重要。它声明此进程类型将附加到Heroku 的HTTP路由堆栈,并在部署时接收Web流量。

Procfiles可以包含其他流程类型。例如,您可以为后台工作进程声明一个进程,该进程处理队列中的项目。

微软Windows

示例应用程序在Microsoft Windows上有一个用于本地开发的附加Procfile,位于该文件中Procfile.windows。后面的教程步骤将使用它:它启动一个不同的Web服务器,一个与Windows兼容的服务器。

1
web: python manage.py runserver 0.0.0.0:5000

扩展应用程序

现在,您的应用程序正在单个Web dyno上运行。将dyno想象成一个轻量级容器,它运行在中指定的命令Procfile。

您可以使用以下ps命令检查正在运行的dynos数量:

1
2
3
4
5
6
7
8
heroku ps
Free dyno hours quota remaining this month: 999h 6m (99%)
Free dyno usage for this app: 0h 0m (0%)
For more information on dyno sleeping and how to upgrade, see:
https://devcenter.heroku.com/articles/dyno-sleeping

=== web (Free): gunicorn gettingstarted.wsgi (1)
web.1: up 2018/10/12 14:26:45 -0500 (~ 33s ago)

默认情况下,您的应用程序部署在免费的dyno上。

免费的dynos会在半小时不活动后睡觉(如果他们没有收到任何流量)。
这会在唤醒时导致第一次请求延迟几秒钟
后续请求将正常执行。免费dynos也会从免费dyno小时的月度帐户级配额中消耗- 只要配额没有用尽,所有免费应用程序都可以继续运行

为避免dyno睡眠,您可以升级到业余爱好或专业dyno类型,如Dyno Types文章中所述。例如,如果您将应用程序迁移到专业dyno,则可以通过运行命令告诉Heroku执行特定数量的dynos,每个dynos运行您的Web进程类型,从而轻松扩展它。

在Heroku上扩展应用程序相当于更改正在运行的dynos数量。将web dynos的数量缩减为

1
heroku ps:scale web=0

通过在Web选项卡上点击刷新再次访问应用程序,或在Web选项卡heroku open中打开它。您将收到一条错误消息,因为您不再有任何可用于处理请求的Web dynos。

再次扩大规模:

1
heroku ps:scale web=1

对于滥用防范,将非免费应用程序扩展到多个dyno需要帐户验证。

声明应用依赖项

Heroku通过查找关键文件将应用程序识别为Python应用程序。

  • requirements.txt 在根目录中包含一个是Heroku识别Python应用程序的一种方法。

您部署的演示应用程序已经有了 requirements.txt ,它看起来像这样:

1
2
3
django
gunicorn
django-heroku

requirements.txt 文件一起列出了应用程序依赖项。部署应用程序时,Heroku将读取此文件并使用该pip install -r命令安装相应的Python依赖项。

要在本地执行此操作,您可以运行以下命令:

1
pip install -r requirements.txt

注意:必须正确安装 Postgres 才能使此步骤正常工作。

注意:如果您正在运行Linux,则libpq-dev还必须安装系统软件包(或您的发行版的等效软件包)。

安装依赖项还会导致安装其他几个依赖项。你可以使用pip的功能看到它们list:

1
2
3
4
5
6
7
8
9
10
11
12
pip list
Package Version
--------------- -------
dj-database-url 0.5.0
Django 2.1.2
django-heroku 0.3.1
gunicorn 19.9.0
pip 10.0.1
psycopg2 2.7.5
pytz 2018.5
setuptools 39.0.1
whitenoise 4.1

安装依赖项后,您就可以在本地运行应用程序了。

在本地运行应用程序

该应用程序几乎准备好在本地启动。Django使用本地资产,所以首先,你需要运行collectstatic:

1
python manage.py collectstatic

回答“是”。

现在使用本地启动应用程序heroku local,它是作为Heroku CLI的一部分安装的。

如果您使用的是Microsoft Windows系统,请运行以下命令:

1
heroku local web -f Procfile.windows

如果您使用的是Unix系统,只需Procfile运行以下命令即可使用默认值:

1
heroku local web

然后,您的本地Web服务器将启动:

1
2
3
4
5
[OKAY] Loaded ENV .env File as KEY=VALUE Format
2:28:11 PM web.1 | [2018-10-12 14:28:11 -0500] [18712] [INFO] Starting gunicorn 19.9.0
2:28:11 PM web.1 | [2018-10-12 14:28:11 -0500] [18712] [INFO] Listening at: http://0.0.0.0:5000 (18712)
2:28:11 PM web.1 | [2018-10-12 14:28:11 -0500] [18712] [INFO] Using worker: sync
2:28:11 PM web.1 | [2018-10-12 14:28:11 -0500] [18715] [INFO] Booting worker with pid: 18715

就像Heroku一样,heroku local检查Procfile确定要运行的内容。

使用Web浏览器打开http:// localhost:5000。您应该会看到您的应用在本地运行

要停止应用程序在本地运行,请返回终端窗口并按Ctrl+ C退出。

推送本地更改

在此步骤中,您将学习如何将本地更改传播到应用程序到Heroku。例如,您将修改应用程序添加其他依赖项使用它的代码

requests在本地安装:

1
pip install requests

然后将其添加到您的requirements.txt文件中:

1
2
3
4
django
gunicorn
django-heroku
requests

修改hello/views.py以便requests在开始时导入模块:

1
import requests

现在修改index方法以使用该模块。尝试index使用以下代码替换当前方法:

1
2
3
4
def index(request):
r = requests.get('http://httpbin.org/status/418')
print(r.text)
return HttpResponse('<pre>' + r.text + '</pre>')

现在在本地测试

1
heroku local

访问http:// localhost:5000上的应用程序。您现在应该看到获取http://httpbin.org/status/418的输出,这是一个可爱的茶壶:

1
2
3
4
5
6
7
8
9
-=[ teapot ]=-

_...._
.' _ _ `.
| ."` ^ `". _,
\_;`"---"`|//
| ;/
\_ _/
`"""`

现在部署。几乎每次部署到Heroku都遵循相同的模式。首先,将修改后的文件添加到本地git存储库

1
git add .

现在将更改提交到存储库:

1
git commit -m "Demo"

现在进行部署,就像之前一样:

1
git push heroku master

最后,检查一切是否正常:

1
heroku open

提供附加组件

附加组件是第三方云服务,可为您的应用程序提供开箱即用的附加服务,从持久性到日志记录再到监控等等。

默认情况下,Heroku会从您的应用程序中存储1500行日志。但是,它使完整的日志流可用作服务 - 并且几个附加提供程序已编写日志记录服务,提供诸如日志持久性搜索电子邮件SMS警报等内容。

在此步骤中,您将提供其中一个日志记录加载项Papertrail

配置papertrail日志记录附加组件:

1
2
3
4
heroku addons:create papertrail
Adding papertrail on sharp-rain-871... done, v4 (free)
Welcome to Papertrail. Questions and ideas are welcome (support@papertrailapp.com). Happy logging!
Use `heroku addons:docs papertrail` to view documentation.

为了帮助防止滥用,配置附加组件需要帐户验证。如果您的帐户未经过验证,系统会指示您访问验证网站。

现在为您的应用程序部署和配置了加载项。您可以为您的应用列出加载项,如下所示:

1
heroku addons

要查看此特定加载项,请访问您的应用程序的Heroku URL几次每次访问都会生成更多日志消息,现在应该将其路由到papertrail附加组件。访问papertrail控制台以查看日志消息:

1
heroku addons:open papertrail

您的浏览器将打开Papertrail Web控制台,显示最新的日志事件。该界面允许您搜索和设置警报.

启动控制台

您可以使用该命令在一次性dyno中运行命令,通常是应用程序中的脚本和应用程序heroku run。它还可用于启动附加到本地终端的REPL流程,以便在您的应用环境中进行试验:

1
2
3
4
5
6
heroku run python manage.py shell
Python 3.7.0 (default, Aug 1 2018, 21:17:03)
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

如果收到错误,Error connecting to process则可能需要配置防火墙。

Python shell在您的应用程序及其所有依赖项的上下文中运行。从这里您可以导入一些应用程序文件。例如,您将能够运行以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> import requests
>>> print(requests.get('http://httpbin.org/status/418').text)

-=[ teapot ]=-

_...._
.' _ _ `.
| ."` ^ `". _,
\_;`"---"`|//
| ;/
\_ _/
`"""`
>>> exit()

为了真正了解dynos是如何工作的,你可以创建另一个一次性dyno并运行bash命令,这会在该dyno上打开一个shell。然后,您可以在那里执行命令。每个dyno都有自己的短暂文件空间,填充了你的应用程序及其依赖项 - 一旦命令完成(在这种情况下bash),就会删除dyno

1
2
3
4
5
6
heroku run bash
Running `bash` attached to terminal... up, run.3052
~ $ ls
gettingstarted hello manage.py Procfile README.md requirements.txt runtime.txt staticfiles
~ $ exit
exit

不要忘记键入exit退出shell并终止dyno。

定义配置变量

Heroku允许您外部化配置 - 在配置变量中存储加密密钥或外部资源地址等数据。

在运行时,配置变量作为环境变量公开给应用程序。

编辑hello/views.py。首先,添加一行来导入os模块:

1
import os

现在修改index方法,使其根据TIMES环境变量的值重复操作:

1
2
3
def index(request):
times = int(os.environ.get('TIMES',3))
return HttpResponse('Hello! ' * times)

heroku local将根据.env本地目录中文件的内容自动设置环境。在项目的顶级目录中,已有一个.env包含以下内容的文件:

1
TIMES=2

如果你运行应用程序heroku local,你会看到两个“你好!”。

要在Heroku上设置config var,请执行以下命令:

1
heroku config:set TIMES=2

查看使用heroku config以下命令设置的配置变量:

1
2
3
4
heroku config
== sharp-rain-871 Config Vars
PAPERTRAIL_API_TOKEN: erdKhPeeeehIcdfY7ne
TIMES: 2

将更改的应用程序部署到Heroku以查看此操作。

提供数据库

该附加市场有大量数据存储的,从Redis的和MongoDB商,Postgres的和MySQL。在此步骤中,您将了解在部署应用程序时自动配置的免费Heroku Postgres附加组件。

数据库是一个附加组件,因此您可以使用addonsCLI中的命令找到有关为您的应用程序配置的数据库的更多信息

1
2
3
4
5
6
heroku addons
Add-on Plan Price State
───────────────────────────────────────────── ───────── ───── ───────
heroku-postgresql (postgresql-horizontal-27446) hobby-dev free created
└─ as DATABASE
...

清单您的应用程序的配置增值经销商将显示您的应用使用连接到数据库的URLDATABASE_URL

1
2
3
heroku config
=== serene-caverns-82714 Config Vars
DATABASE_URL: postgres://qayojflkqzwdlk:c9b49b89f95625e0c1ed225aed3871a888ab41ca53d6d16078fe5f6416f8a402@ec2-23-23-80-20.compute-1.amazonaws.com:5432/dbr6s55rtq1vqg

Heroku还提供了一个pg显示更多内容的命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
heroku pg
=== DATABASE_URL
Plan: Hobby-dev
Status: Available
Connections: 0/20
PG Version: 10.5
Created: 2018-10-12 19:13 UTC
Data Size: 7.6 MB
Tables: 0
Rows: 0/10000 (In compliance) - refreshing
Fork/Follow: Unsupported
Rollback: Unsupported
Continuous Protection: Off
Add-on: postgresql-horizontal-27446

这表明我有一个爱好数据库(免费),运行Postgres 10.5,没有数据。

您部署的示例应用程序已具有数据库功能,您应该可以通过访问应用程序的URL并附加来访问该功能/db。例如,如果您的应用程序已部署,https://wonderful-app-287.herokuapp.com/则访问https://wonderful-app-287.herokuapp.com/db

但是访问它会产生错误,因为在配置数据库时,尚未创建表。运行标准Django manage.py migrate来创建表。

1
2
3
4
5
6
7
8
9
10
11
heroku run python manage.py migrate
Running `python manage.py migrate` attached to terminal... up, run.1059
Synchronizing apps without migrations:
Creating tables...
Creating table hello_greeting
Running deferred SQL...
Installing custom SQL...
Running migrations:
Rendering model states... DONE
Applying contenttypes.0001_initial... OK
...

如果您看到一条消息,“您刚刚安装了Django的auth系统,这意味着您没有定义任何超级用户。你想现在创建一个吗?“,键入no。

现在/db再次访问该路由,每次访问时都会看到一个简单的页面更新:

1
2
3
4
Page View Report

April 19, 2017, 8:50 a.m.
April 19, 2017, 8:52 a.m.

访问数据库的代码很简单,并且使用了一个Greetings可以找到的简单Django模型hello/models.py

每当您访问/db应用程序的路径时,将hello/views.py调用文件中的以下方法,该方法将创建一个新的Greeting,然后呈现所有现有的Greetings:

1
2
3
4
5
6
7
8
def db(request):

greeting = Greeting()
greeting.save()

greetings = Greeting.objects.all()

return render(request, 'db.html', {'greetings': greetings})

假设您在本地安装了Postgres,请使用该heroku pg:psql命令连接到远程数据库并查看所有行:

1
2
3
4
5
6
7
heroku pg:psql
--> Connecting to postgresql-horizontal-27446
psql (10.5)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

serene-caverns-82714::DATABASE=>

阅读更多关于Heroku PostgreSQL的信息。

可以使用类似的技术来安装MongoDB或Redis附加组件。

账号注册

进入Heroku官网 进行注册。

由于Heroku使用了谷歌的人机识别,此处需要科学上网