dotCloud的目标是提供一系列不同的独立服务,作为构建模块,来构建应用程序。如果你需要一个数据库,可以直接从他们所支持的许多数据库中挑选一个。如果应用程序前端使用Django或Rails,而在后端使用Java,也是可以的。大多数开发人员不会在开发所有应用中使用同一个技术栈,所以这可以让你灵活地使用最好的工具来完成这项工作。dotCloud还提供了很好的测试环境,可以尝试新的服务,看看它们如何运行,而无需安装、配置和维护仅仅用于测试的服务。
我将详细介绍将我的博客安装到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客户端并进行配置,以便我们可以开始使用它。
#创建我的dotcloud虚拟环境。
$ mkvirtualenv dotcloud
#使用pip安装dotcloud客户端
$ pip install dotcloud
#创建我们的博客应用程序
$ dotcloud create blog
# 当收到提示时,输入api密钥,密钥可从这里获得:http://www.dotcloud.com/account/settings
#<密钥写这里>
#如果你没有收到输入密钥的提示,可以运行这个命令,它会让你再次输入你的API密钥。
$ dotcloud register
现在我们已经完成了客户端设置,并创建了一个应用程序,现在我们可以开始构建我们的服务了。我已经在github上fork了我的博客仓库,以便我可以针对dotCloud进行修改,而不会影响我的原始仓库。
#进入项目目录
CD ~/projects
#fork kkecochranenet 到新分支 kencochranenet_dotcloud,然后克隆到本地
git clone git://github.com/kencochrane/kencochranenet_dotcloud.git kencochranenet_dotcloud
#进入新的目录。
cd kencochrane_dotcloud
根据文档,现在需要创建一个wsgi.py文件,并放在项目根目录下。使用http://docs.dotcloud.com/tutorials/python/django/#wsgi-py 作为模板,创建如下wsgi.py文件。在使用默认模板时有点小问题,需要添加一个路径到sys.path,以便wsgi可以正确地找到我的django应用程序。完成的文件如下:
import os
import sys
#与示例模板不同的是,作者加入了下面这些内容
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 requirements 依赖文件来管理项目依赖关系。现在已经有pip文件了,而且在正确的位置,命名也没有问题,所以我们不需要做任何事情,但是如果没有的话,需要创建一个并放在根目录下,命名为 requirements.txt
当我们将服务添加到部署堆栈时,dotCloud会在我们的部署容器中提供一个名为“/home/dotcloud/environment.json”的文件,提供适当的连接信息。这使我们不必在settings.py文件中硬编码用户名/密码和服务器URL,而且也会更安全一些,因为无需在源码仓库中出现这些信息。
如何使用dotCloud提供的这个json文件呢?在settings.py文件的顶部,添加如下内容:
import json
with open('/home/dotcloud/environment.json') as f:
env = json.load(f)
把上述代码添加到settings.py文件,就有了一个变量env,它具有我们需要的所有env环境设置。
你可以进一步添加一些自定义代码来检查environment.json文件是否存在。如果存在,说明正在生产环境中,所以使用json里的设置,如果不存在,说明在本地调试模式,可以本地设置。如果想更好一点,可以自己写一个类似于dotCloud提供的这种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权限。权力巨大,责任重大。其中一个职责就是您需要创建自己的数据库模式和用户。一般需要通过如下命令,来完成:
#连接到dotcloud mysql服务器实例
$ 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)
# 创建用户和数据库,并授予用户权限
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客户端不支持这个。因此,dotCloud决定不完全支持memcached,而不是部署一个不安全的服务。有一些方法可以强行使用memcached,但它涉及到各种复杂的防火墙规则,并运行诸如stunnel之类的东西。虽然可以做到,但不是很好。
dotCloud建议使用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'
},
},
}
#我们也将使用redis作为会话缓存。
SESSION_ENGINE ='django.contrib.sessions.backends.cached_db'
有关使用redis作为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_ROOT ='/home/dotcloud/data/media/'
MEDIA_URL ='/media/'
#静态文件设置
STATIC_ROOT ='/home/dotcloud/data/static/'
STATIC_URL ='/static/'
#管理员前缀
ADMIN_MEDIA_PREFIX ='/static/admin/'
这是nginx.conf中的配置:
location /media/ {root/home/dotcloud/data; }
location /static/ {root/home/dotcloud/data; }
我们将创建一个postinstall脚本来处理在服务器上安装代码后需要做的所有任务。包含调用我们的createdb.py和mkadmin.py文件,以及同步我们的数据库,运行migration并运行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的方式进行了配置,下面可以配置我们的部署堆栈。这是通过一个名为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中删除,以便将这些文件正常同步。只有提交的更改才会被push,所以不要忘记提交更改。如果想用更巧妙的方式,或者想更加安全的话,可以使用脚本从安全的位置下载文件,并以这种方式进行安装。
一切都准备好了,下面所要做的就是将应用上传到dotCloud。
#推出你的更改到服务器
$ dotcloud push blog
一旦将代码推送到dotCloud,您可以通过运行info命令来查看它的信息。
#获取有关我们新服务的信息
$ 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(主/从)
redis:2(主/从)
mongodb:3或5(使用副本集)
扩展无状态服务,和扩展上述支持的有状态服务,步骤是相同的。只需在命令行中运行相应的扩展命令:
$ dotcloud scale app db=2
对于无状态应用程序,除非你是订阅了dotCloud的企业版,否则,仅限于一定数量的扩展范围。如果你的应用程序需要大量扩展,你应该联系dotCloud,让他们知道你打算做什么,他们会告诉你如何最好地实现你的目标。
链接:http : //docs.dotcloud.com/guides/scaling/
在dotCloud上托管应用程序,并不意味着不需要备份数据。应当备份的最重要的信息,就是数据库。幸运的是,dotCloud可以轻松备份数据库。如何设置数据库备份请参阅:http : //docs.dotcloud.com/guides/backups/
如果应用需要发送或接收电子邮件,请参阅下面步骤。由于dotCloud运行在EC2上,EC2被很多人利用来发送垃圾邮件,因此最好使用第三方电子邮件提供商。受欢迎的是MailGun,SendGrid,CritSend和Amazon 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不允许发送大量邮件,一旦达到每日邮件数量限制,就不能再发送了。所以,如果每天的邮件数量很少,可以这样做,但如果数量很大,就不要用gmail了。此外,电子邮件始终显示来自你的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这样的服务。
链接:
如果您的应用程序需要运行定时作业,请按照下面步骤操作:http : //docs.dotcloud.com/guides/periodic-tasks/
这个博客并不需要celery,但dotCloud支持celery。有关更多信息,请点击此链接:http : //docs.dotcloud.com/tutorials/python/django-celery/
如果您在s3上存储数据,则可以挂载s3存储桶,以便可以从应用程序上,像访问本地目录一样访问s3。在存储由访问者上传的文件,或在不同Web进程之间共享文件时很有帮助。按照以下说明进行设置:http : //docs.dotcloud.com/guides/s3fs/
如果你需要查看日志,看看运行状态,你可以通过两种方法来完成。第一种方法会在控制台显示日志。
#查看日志,打印到控制台。按ctrl-c停止。
$ dotcloud logs blog.www
或者通过ssh登录并查看你的日志。
#打开一个shell
$ dotcloud ssh blog.www
最常用的日志放在下面的目录下:
#nginx访问和错误日志。
/var/log/nginx/<app_name>.{access,error}.log
#wsgi错误日志
/var/log/supervisor/uswgi.log
如果需要重新启动服务,只需使用此命令。
#重新启动服务
dotcloud restart blog.www