使用dotCloud在云端部署Django应用程序

dotCloud的目标是提供一系列独立服务,你可以使用这些服务来构建你的应用程序。比方说,如果你需要一个数据库,就从其所支持的众多数据库中挑选一个。如果需要一个在前端使用Django或Rails的应用程序,而在后端使用Java,那也是可以的。他们意识到,大多数开发人员不会在自己所有的应用程序上坚持同一个标准的技术栈,使用不同的技术栈可以让你灵活地使用最好的工具来完成这项工作。它还为你提供了一个不错的试验场,可以尝试新的服务,看看它们如何运行,而无需安装,配置和维护这些仅用于测试的服务。

我将详细介绍将我的博客安装到dotCloud上的步骤,希望这个过程能够回答一些常见的问题。

(译者注:注意!文章时间比较久远,步骤仅供参考)

文档

在我开始使用任何新服务之前,我通常会做的第一件事就是查看文档。DotCloud有一个很好的文档列表以及一些关于如何开始的教程。这4个文件是我使用最多的文件。

http://docs.dotcloud.com/firststeps/platform-overview/

http://docs.dotcloud.com/tutorials/python/django/

http://docs.dotcloud.com/services/mysql/

http://docs.dotcloud.com/services/mysql-masterslave/

第一步:

像现在所有很酷的服务一样,dotCloud使用基于python的CLI,所以在我们开始之前,我们需要安装dotCloud客户端并进行配置,以便我们可以开始使用它。

# create my dotcloud virtual environment.
$ mkvirtualenv dotcloud

# install dotcloud client using pip
$ pip install dotcloud

# create our application called blog
$ dotcloud create blog

#enter api key that we got from: http://www.dotcloud.com/account/settings when prompted
#<key goes here>

# if you were not prompted to enter your key you can run this command, and it will let you enter your API key again.
$ dotcloud register

现在我们已经完成了客​​户端设置,并创建了一个应用程序,现在我们可以开始构建我们的服务了。我已经在github上fork了我的博客存储库,以便我可以对dotCloud进行特定的更改,而不会影响我的原始存储库。

# go into projects directory
cd ~/projects

# forked kencochranenet to kencochranenet_dotcloud, now clone that. locally
git clone git://github.com/kencochrane/kencochranenet_dotcloud.git kencochranenet_dotcloud

# go into the new directory.
cd kencochrane_dotcloud

通过文档发现,我需要创建一个wsgi.py文件,并放入项目的根目录中。使用http://docs.dotcloud.com/tutorials/python/django/#wsgi-py作为模板,我在下面创建了我的wsgi.py文件。我需要对默认模板做出调整,需要添加一个目录到sys.path,以便wsgi可以正确地找到我的django应用程序。这是我完成的文件。

import os
import sys

# Ken added this, only thing that is different from the example template (not counting settings file name)
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__),'mysite')))
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'

import django.core.handlers.wsgi
djangoapplication = django.core.handlers.wsgi.WSGIHandler()
def application(environ, start_response):
    if 'SCRIPT_NAME' in environ:
        del environ['SCRIPT_NAME']
    return djangoapplication(environ, start_response)

DotCloud使用PIP需求文件来管理你的项目依赖关系。我们已经有正确命名的PIP需求文件,并被放在正确的位置上,所以我们不需要做任何事情,但是如果没有,我们需要创建一个并放在根目录下,并命名为requirements.txt

服务

当我们将服务添加到部署堆栈时,dotCloud会在我们的部署容器中提供给我们一个名为“/home/dotcloud/environment.json”的文件,并在这个文件中提供适当的连接信息。这使我们不必在我们的settings.py文件中硬编码用户名/密码和服务器URL,这种方式也提供了一些安全性,因为我们不需要在我们的源代码仓库中拥有这些信息。

这是我们如何使用它。在settings.py文件的顶部,添加以下代码读取这个存放连接信息的文件。

import json
with open('/home/dotcloud/environment.json') as f:
  env = json.load(f) 

一旦我们把它添加到settings.py文件,我们现在有一个变量env,变量env拥有我们需要的所有env设置。

你可以进一步添加一些自定义代码来检查environment.json文件是否存在,如果存在,意味着正处于生产模式,便调用该设置,如果没有该文件,那你肯定处于本地模式,所以使用本地设置。如果你想更酷些,你可以写一个自己的json文件,它有一个类似于本地开发的设置,如果它找不到dotcloud,它可以查找你自己的json文件,并从中加载你的设置。这将允许你为生产和开发使用相同的设置文件,只需要在顶部添加一些代码即可加载正确的env文件。

数据库

大多数应用程序需要一个数据库,这个博客也同样如此。以下就是我们如何设置在dotcloud上部署我们的博客时使用的数据库。我们选择MySQL作为我们的数据库。使用Django,你需要在settings.py中进行数据库设置。以下是我们在settings.py中设置mysql数据库连接的方法。请注意,数据库的名称不是来自env变量,而是自行设定的。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'blogdb',
        'USER': env['DOTCLOUD_DB_MYSQL_LOGIN'],
        'PASSWORD': env['DOTCLOUD_DB_MYSQL_PASSWORD'],
        'HOST': env['DOTCLOUD_DB_MYSQL_HOST'],
        'PORT': int(env['DOTCLOUD_DB_MYSQL_PORT']),
    }
}

创建数据库

dotCloud允许用户建立自己的专用数据库,具有完全的root权限。权力巨大也就意味着责任重大。其中一个职责就是需要创建自己的数据库和数据库用户。通过以下的步骤进行,注意替换blog_username,strong_password为你自己的用户名和密码。

# connect to dotcloud mysql server instance
$ dotcloud run blog.db -- mysql -u root -p

# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 34
Server version: 5.1.41-3ubuntu12.10 (Ubuntu)

# create the user and database and give user permissions to database.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database blogdb;
Query OK, 1 row affected (0.00 sec)

mysql> create user 'blog_username' identified by 'strong_password';
Query OK, 0 rows affected (0.05 sec)

mysql> grant all on blogdb.* to 'blog_user'@'%';
Query OK, 0 rows affected (0.04 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> exit;Bye
Shared connection to database closed.

这看起来很熟悉吗?如果你想要做得更多的话,我在这里有一些参考。

为了方便起见,我们将创建一个小的python脚本来检查是否创建了我们的数据库,如果没有的话,它会为我们创建它。这将使我们不必登录到我们的数据库,并在部署之前手动完成。该文件被称为createdb.py,这就是它的样子。这个脚本是针对mysql的。如果你使用的是postgreSQL数据库,你可以使用这个文件作为模板,然后修改它,以便在postgreSQL上运行。

import MySQLdb
import os
from wsgi import *

def create_dbs(names):
    print("create_dbs: let's go.")
    django_settings = __import__(os.environ['DJANGO_SETTINGS_MODULE'], fromlist='DATABASES')
    print("create_dbs: got settings.")
    databases = django_settings.DATABASES
    for name, db in databases.iteritems():
        if name in names and db['ENGINE'].endswith('mysql'):
            host = db['HOST']
            user = db['USER']
            password = db['PASSWORD']
            port = db['PORT']
            db_name = db['NAME']
            print 'creating database %s on %s' % (db_name, host)
            db = MySQLdb.connect(user=user,
                                passwd=password,
                                host=host,
                                port=port)
            cur = db.cursor()
            print("Check if database is already there.")
            cur.execute("""SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
                         WHERE SCHEMA_NAME = %s""", (db_name,))
            results = cur.fetchone()
            if not results:
                print("Database %s doesn't exist, lets create it." % db_name)
                sql = """CREATE DATABASE IF NOT EXISTS %s """ % (db_name,)
                print("> %s" % sql)
                cur.execute(sql)
                print(".....")
            else:
                print("database already exists, moving on to next step.")


if __name__ == '__main__':
    import sys
    print("create_dbs start")
    create_dbs(sys.argv[1:])
    print("create_dbs all done")

添加一个缓存引擎

由于大部分博客内容变化不大,所以博客内容非常适合缓存。因此,我们将利用Django内置的缓存功能,并在我们的博客中添加一些缓存引擎。通常我使用memcached进行缓存,但是dotCloud的memcached支持目前是有限的。之所以受到限制,是因为memcached没有任何内置的认证机制,为了确保它是安全的,你需要运行一个支持SASL的特殊版本的memcached,大多数的memcached客户端不支持SASL。因此,dotCloud决定不完全支持它,而不是部署一个不安全的服务。有一些方法可以使用它,但它涉及到各种复杂的防火墙规则,并需要运行诸如stunnel之类的东西。所以这是可能的,但不是很好用和安全。

因此,他们建议你使用redis来代替,redis具有与memcached相同的缓存功能,还支持更多功能,包括身份验证。所以我们将使用redis作为我们的缓存引擎。为了使用redis,我们将需要添加redis库,因为redis缓存引擎没有内置到Django中。在你的requirements.txt文件中,需要添加django-redis == 1.4.5,以便这些库可供Django使用。

一旦你安装了这个库,你将需要将这些设置添加到settings.py文件中,以便django知道使用哪个redis服务器和密码。

CACHES = {
    'default': {
        'BACKEND': 'redis_cache.cache.RedisCache',
        'LOCATION': env['DOTCLOUD_CACHE_REDIS_HOST']+':'+env['DOTCLOUD_CACHE_REDIS_PORT'],
        'OPTIONS': {
            'DB': 1,
            'PASSWORD': env['DOTCLOUD_CACHE_REDIS_PASSWORD'],
            'PARSER_CLASS': 'redis.connection.HiredisParser'
        },
    },
}

# we also are going to use redis for our session cache as well.
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'

有关使用redis作为Django缓存的更多信息,请查看这些链接。

Django管理员

我们还需要一个简单的方法来为我们创建我们的django管理员帐户。我使用这个mkadmin.py脚本来完成这项工作。使用脚本会将密码默认设置为“P@s$w0rd1”,一旦您安装了代码,您将需要登录到管理员帐户,并将密码更改为更安全的密码。

#!/usr/bin/env python
from wsgi import *
from django.contrib.auth.models import User
u, created = User.objects.get_or_create(username='admin')
if created:
    u.set_password('P@s$w0rd1')
    u.is_superuser = True
    u.is_staff = True
    u.save()

媒体

我们需要将我们的静态和媒体文件放在以下位置:static = / home / dotcloud / data / static /和media = / home / dotcloud / data / media /。然后我们需要更改settings.py文件中的媒体目录,并设置一个nginx.conf文件以将媒体文件映射到正确的位置。这里是settings.py文件的更改。

# media settings
MEDIA_ROOT = '/home/dotcloud/data/media/'
MEDIA_URL = '/media/'

# static settings
STATIC_ROOT = '/home/dotcloud/data/static/'
STATIC_URL = '/static/'

# admin prefix
ADMIN_MEDIA_PREFIX = '/static/admin/'

这是nginx.conf文件

location / media / {root / home / dotcloud / data; }
location / static / {root / home / dotcloud / data; }

安装后

我们将创建一个postinstall脚本来处理我们在服务器上安装代码后还需要做的所有任务。主要工作是调用我们上述提到的createdb.py和mkadmin.py文件,以及同步我们的数据库,运行迁移并运行collectstatic将所有静态文件移动到正确的位置。

#!/bin/sh
python createdb.py default
python mysite/manage.py syncdb --noinput
python mysite/manage.py migrate
python mkadmin.py
mkdir -p /home/dotcloud/data/media /home/dotcloud/data/static
python mysite/manage.py collectstatic --noinput

不要忘记确保你的postinstall,createdb.py和mkadmin.py脚本是运行权限

#使脚本可执行。
$ chmod + x postinstall createdb.py mkadmin.py

dotcloud.yml

现在我们已经将应用程序的项目结构全部设置好了,并且按照dotCloud的方式进行了配置,然后我们可以开始配置我们的部署堆栈。这是通过一个名为dotcloud.yml的文件完成的。有关dotcloud.yml文件的更多信息,请查看此链接:http ://docs.dotcloud.com/guides/build-file/

www:
  type: python
db:
  type: mysql
cache:
  type: redis

这告诉我们我们需要3个服务,一个python www服务,一个mysql数据库服务和一个redis缓存服务。这是一个非常基本的设置,未来根据你想要达到什么,你可以将设置变得更加复杂。请注意,这不是针对高可用性设置的,因为没有任何实例是可伸缩的。有关更多信息,请参阅下面的缩放部分。如果您正在dotCloud的生产应用程序中运行,建议您扩展所有服务,以便能够承受EC2服务器崩溃和其他不可预见的问题。

部署

现在我们准备部署我们的Django应用程序,但是在我进一步了解之前,了解以下内容很重要。Dotcloud会关注你的.gitignore文件。如果在.gitignore文件中有一个设置文件,这样它就不会保存在仓库中,它不会将这些更改推送到云端。您需要将其从.gitignore中删除,以便将这些文件被正常上传。记住只有提交的更改才会生效,所以不要忘记提交更改。如果你想让事情变得复杂,你可以使用脚本从安全的位置下载文件,并以这种方式进行安装,如果你想确保事情变得超级安全。

一切都准备好了,所以我们所要做的就是将我们的应用推向dotCloud。

# push out your changes to the server
$ dotcloud push blog .

服务信息

一旦将代码推送到dotCloud,您可以通过运行info命令来查看它各项信息。

# get the information about our new services
$ dotcloud info blog
cache:
    config:
        redis_password: <password>
        redis_replication: true
    instances: 1
    type: redis
db:
    config:
        mysql_masterslave: true
        mysql_password: <password>
    instances: 1
    type: mysql
www:
    config:
        static: static
        uwsgi_processes: 4
    instances: 1
    type: python
    url: <url was here>

伸缩性

通过扩展可以增长应用程序的能力,以便处理更多流量或可能发生的可能故障。使用正常的非PaaS设置,伸缩应用程序可能会非常痛苦和耗时,但使用PaaS可以像运行一些命令一样简单。有三种缩放类型,垂直,水平,以及高可用性。

纵向扩展,意味着增加现在的服务,使其规模变得更大。这在数据库维护中很受欢迎,数据库越大,所需的空间和内存就越多。

水平缩放意味着创建一个以上的服务实例,在各服务实例之间共享工作,均衡负载,提供更大的容量。

高可用性意味着您一次只能运行一个以上的服务,因此如果其中一个服务出现问题,另一个服务将会填补空缺。这将有助于避免发生故障(EC2实例崩溃)的停机时间。理想情况下,在生产环境中运行时,您的所有服务都应按照“高可用性”进行扩展。

有两种服务,有状态的,无状态的。有状态服务是持有持久数据的服务。持久化的例子是mysql,redis,postgresql,solr,MongoDB和RabbitMQ。

水平在dotCloud上扩展有状态服务的高可用性意味着创建一个主/从设置,如果主设置有任何问题,可以自动切换从从设置。dotCloud在MySQL,Redis和MongoDB上支持HA扩展。

持久化服务的规模如下

  • mysql : 2 (master/slave)
  • redis : 2 (master/slave)
  • mongodb : 3 or 5 (using replica sets)

扩展无状态和支持的有状态服务之一是相同的。您只需运行scale命令行命令。

$ dotcloud scale app db = 2

对于无状态应用程序,除非你在企业计划中,否则仅限于一定数量的缩放单位。如果你需要有很多规模单位的应用程序,你应该联系dotCloud,让他们知道你打算做什么,他们会告诉你如何最好地实现你的目标。

链接:http : //docs.dotcloud.com/guides/scaling/

数据库备份

仅仅因为你在dotCloud上托管你的应用程序并不意味着你可以不备份你的数据。要备份的最重要的数据是数据库。幸运的是,dotCloud可以轻松备份数据库。有关如何在这里设置数据库备份非常有用的指南:http : //docs.dotcloud.com/guides/backups/

电子邮件

如果您需要从您的应用程序发送或接收电子邮件,您可以这样做。由于dotCloud运行在EC2上,EC2是SPAMMERS发送垃圾邮件的热门地点,因此最好使用第三方电子邮件提供商为您发送电子邮件。受欢迎的是MailGunSendGridCritSendAmazon SES

你可以用几种不同的方法来设置它。第一种方法是最简单的方法,它允许您为每个服务配置SMTP设置。你会这样做(见下文)。您可以手动设置该服务的SMTP设置,当您的应用程序需要发送电子邮件时,它将使用这些设置。这是最简单的设置,但这种方法有缺点。你需要为每个服务设置这个,如果你有多个将被复制的地方。另外,如果您想更改设置,则需要销毁服务并重新创建它,因为创建服务时只能将这些配置设置一次。

www:
  type: python
  config:
    smtp_server: smtp.mailgun.org
    smtp_port: 25
    smtp_username: postmaster@company.com
    smtp_password: YourMailGunPassword

更好的方法是使用dotCloud的SMTP服务。SMTP服务构建为接收来自您的服务的电子邮件并将其转发到适当的位置。最好使用第三方电子邮件提供商,但是你也可以使用典型的穷人解决方案,您可以使用gmail发送电子邮件。使用gmail时一定要小心,因为你不能通过gmail每天发送大量的电子邮件,一旦你达到你的日常限制,你将被阻止,所以这对一天只有一些电子邮件是OK的。此外,电子邮件将始终来自您的Gmail地址,适用于系统电子邮件,但如果您正在尝试运行一些业务,则不太合适。

这里是一个使用mailgun的例子。

mailer:
  type: smtp
  config:
    smtp_relay_server: smtp.mailgun.org
    smtp_relay_port: 587
    smtp_relay_username: postmaster@yourmailgundomain.com
    smtp_relay_password: YourMailgunPassword

这里是一个使用Gmail的例子。

mailer:
  type: smtp
  config:
    smtp_relay_server: smtp.gmail.com
    smtp_relay_port: 587
    smtp_relay_username: your_gmail_username@gmail.com
    smtp_relay_password: Your_Gmail_Password 

一旦你有了这些所有的设置,它们将在你的environment.json文件中可用。

如果您想收到电子邮件,最好使用像MailGun这样的服务。

链接:

Cron工作

如果您的应用程序需要运行cron作业,请按照本指南中的步骤操作:http : //docs.dotcloud.com/guides/periodic-tasks/

Celery

这个博客并不需要Celery,但dotCloud确实支持它。有关更多信息,请点击此链接:http : //docs.dotcloud.com/tutorials/python/django-celery/

S3FS

如果您在s3上存储数据,则可以挂载s3存储桶,以便可以从应用程序访问s3,就像它是容器上的本地目录一样。这对存储由访问者上传的文件或在不同Web进程之间共享文件很有帮助。按照以下说明进行设置:http : //docs.dotcloud.com/guides/s3fs/

日志

如果你需要查看日志,看看它是如何进行的,你可以通过两种方法来完成。第一种方法你的控制台查看日志。

# look at logs of your service, it will tail them to your console. ctrl-c to stop.
$ dotcloud logs blog.www

或者通过ssh登录并查看你的日志。

# Open up a shell
$ dotcloud ssh blog.www

这里是你最关心的信息。

# nginx access and error logs.
/var/log/nginx/<app_name>.{access,error}.log

# wsgi error logs
/var/log/supervisor/uswgi.log

重新启动服务

如果您需要重新启动服务,只需键入此命令。

# restart the service
dotcloud restart blog.www

本文的版权归 Sepmer Fi 所有,如需转载请联系作者。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏MYSQL轻松学

Mysql5.5&Mysql5.6&Mysql5.7特性

Mysql5.5 特性,相对于Mysql5.1 性能提升 默认InnoDB plugin引擎。具有提交、回滚和crash恢复功能、ACID兼容。 行级锁(一致性...

3555
来自专栏小樱的经验随笔

【干货分享】常用端口服务对照表

端口:0 服务:Reserved 说明:通常用于分析操作系统。这一方法能够工作是因为在一些系统中“0”是无效端口,当你试图使用通常的闭合端口连接它时将产生不...

4225
来自专栏沃趣科技

MySQL 8.0 首个自适应参数横空出世

MySQL8.0推出一个号称可以自适应服务器的参数,保证在各种不同的服务器、虚拟机、容器下自动适配服务器资源,让我们一起来看看到底它能做到什么地步。

1363
来自专栏杨建荣的学习笔记

巧用外部表备份历史数据(r5笔记第62天)

在很多的系统中,随着时间的推移,都会沉淀大量的历史数据。一般数据量达到一定程度都会考虑使用分区表来处理。根据业务规则,可能有些历史数据隔一段时间就需要做清理了,...

35412
来自专栏FreeBuf

Linux爆新漏洞,长按回车键70秒即可获得root权限

按住回车70秒,黑客就能在linux系统绕过认证,进而获取root权限,并能远程控制经过加密的linux系统。 漏洞来源 这个安全问题来源于Cryptsetu...

2235
来自专栏快乐八哥

普通文件和数据库存储的对比

在大多数企业开发或Web开发中,都会涉及数据的存储和检索。存储数据有两种基本的方法:保存到普通文件中(File System),或者保存到数据库(Databas...

1869
来自专栏云之翼

某项目中客户自建Elastic Search向腾讯云上迁移总结(一)

在某婚恋客户合作过程中,由于以前该客户的所有基础架构环境全部部署在客户自己的IDC中,但是该IDC建设于10年前,IDC已经使用很久了,而且是运营商IDC,外网...

240
来自专栏IT大咖说

Sharding-JDBC:分布式微服务数据库访问框架的设计与实现

摘要 当当架构部总监分享分布式微服务数据库访问框架Sharding-JDBC的设计与实现。 ? 互联网领域数据库面临的问题 我们在互联网领域数据库面临的问题主要...

5597
来自专栏腾讯云Elasticsearch Service

Elasticsearch调优实践

本文基于ES 5.6.4,从性能和稳定性两方面,从linux参数调优、ES节点配置和ES使用方式三个角度入手,介绍ES调优的基本方案。当然,ES的调优绝不能一概...

1341
来自专栏软件工程师成长笔记

《等你下课》让我们一起一步一步搭建RocketMQ可视化管理控制台

早晨起来,听着杰伦的新歌《等你下课》,轻快的旋律,动听的曲调,让我回想18岁的我........

1103

扫码关注云+社区