Neste tutorial, vamos pegar um projeto Django local simples, apoiado por um banco de dados MySQL, e convertê-lo para rodar no Heroku. O Amazon S3 será usado para hospedar nossos arquivos estáticos, enquanto o Fabric automatizará o processo de implantação.
O Projeto é um sistema de mensagens simples. Pode ser um aplicativo de tarefas ou um blog ou até mesmo um clone do Twitter. Para simular um cenário real, o projeto será criado primeiro com um backend MySQL e depois convertido em Postgres para implantação no Heroku. Eu pessoalmente tive cinco ou seis projetos em que tive que fazer exatamente isso:converter um projeto local, apoiado com MySQL, em um aplicativo ao vivo no Heroku.
Configuração
Pré-requisitos
- Leia o guia oficial do Django Quick Start no Heroku. Basta lê-lo. Isso ajudará você a ter uma ideia do que realizaremos neste tutorial. Usaremos o tutorial oficial como um guia para nosso próprio processo de implantação mais avançado.
- Crie uma conta da AWS e configure um bucket S3 ativo.
- Instale o MySQL.
Vamos começar
Comece baixando o projeto de teste aqui, descompacte e ative um virtualenv:
$ cd django_heroku_deploy
$ virtualenv --no-site-packages myenv
$ source myenv/bin/activate
Crie um novo repositório no Github:
$ curl -u 'USER' https://api.github.com/user/repos -d '{"name":"REPO"}'
Certifique-se de substituir todas as PALAVRAS-CHAVE em maiúsculas por suas próprias configurações. Por exemplo:curl -u 'mjhea0' https://api.github.com/user/repos -d '{"name":"django-deploy-heroku-s3"}'
Adicione um arquivo leia-me, inicialize o repositório Git local e, em seguida, PUSH a cópia local para o Github:
$ touch README.md
$ git init
$ git add .
$ git commit -am "initial"
$ git remote add origin https://github.com/username/Hello-World.git
$ git push origin master
Certifique-se de alterar o URL para o URL do seu repositório que você criou na etapa anterior.
Configure um novo banco de dados MySQL chamado django_deploy :
$ mysql.server start
$ mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
mysql> CREATE DATABASE django_deploy;
Query OK, 1 row affected (0.01 sec)
mysql>
mysql> quit
Bye
Atualize settings.py :
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django_deploy',
'USER': 'root',
'PASSWORD': 'your_password',
}
}
Instale as dependências:
$ pip install -r requirements.txt
$ python manage.py syncdb
$ python manage.py runserver
Execute o servidor em http://localhost:8000/admin/ e certifique-se de que consegue fazer login no admin. Adicione alguns itens ao
Whatever
objeto. Mate o servidor. Converter do MySQL para Postgres
Observação: Nesta situação hipotética, vamos fingir que você está trabalhando neste projeto há algum tempo usando MySQL e agora deseja convertê-lo para Postgres.
Instalar dependências:
$ pip install psycopg2
$ pip install py-mysql2pgsql
Configure um banco de dados Postgres:
$ psql -h localhost
psql (9.2.4)
Type "help" for help.
michaelherman=# CREATE DATABASE django_deploy;
CREATE DATABASE
michaelherman=# \q
Migrar dados:
$ py-mysql2pgsql
Este comando cria um arquivo chamado mysql2pgsql.yml , contendo as seguintes informações:
mysql:
hostname: localhost
port: 3306
socket: /tmp/mysql.sock
username: foo
password: bar
database: your_database_name
compress: false
destination:
postgres:
hostname: localhost
port: 5432
username: foo
password: bar
database: your_database_name
Atualize isso para sua configuração. Este exemplo cobre apenas a conversão básica. Você também pode incluir ou excluir determinadas tabelas. Veja o exemplo completo aqui.
Transfira os dados:
$ py-mysql2pgsql -v -f mysql2pgsql.yml
Depois que os dados forem transferidos, certifique-se de atualizar seu settings.py Arquivo:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
"NAME": "your_database_name",
"USER": "foo",
"PASSWORD": "bar",
"HOST": "localhost",
"PORT": "5432",
}
}
Por fim, sincronize novamente o banco de dados, execute o servidor de teste e adicione outro item ao banco de dados para garantir que a conversão seja bem-sucedida.
Adicione um arquivo local_settings.py
Ao adicionar um local_settings.py arquivo, você pode estender o arquivo settings.py arquivo com configurações relevantes para seu ambiente local, enquanto o arquivo principal settings.py arquivo é usado exclusivamente para seus ambientes de preparação e produção.
Certifique-se de adicionar local_settings.py para o seu .gitignore file para manter o arquivo fora de seus repositórios. Aqueles que desejam usar ou contribuir com seu projeto podem clonar o repositório e criar seu próprio local_settings.py arquivo específico para seu próprio ambiente local.
Embora esse método de usar dois arquivos de configuração seja uma convenção há vários anos, muitos desenvolvedores de Python agora usam outro padrão chamado The One True Way. Podemos olhar para este padrão em um tutorial futuro.
Atualizar settings.py
Precisamos fazer três alterações em nosso settings.py atual Arquivo:
Alterar
DEBUG
modo para falso:DEBUG = False
Adicione o seguinte código ao final do arquivo:
# Allow all host hosts/domain names for this site
ALLOWED_HOSTS = ['*']
# Parse database configuration from $DATABASE_URL
import dj_database_url
DATABASES = { 'default' : dj_database_url.config()}
# Honor the 'X-Forwarded-Proto' header for request.is_secure()
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# try to load local_settings.py if it exists
try:
from local_settings import *
except Exception as e:
pass
Atualize as configurações do banco de dados:
# we only need the engine name, as heroku takes care of the rest
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
}
}
Crie seu local_settings.py Arquivo:
$ touch local_settings.py
$ pip install dj_database_url
Em seguida, adicione o seguinte código:
from settings import PROJECT_ROOT, SITE_ROOT
import os
DEBUG = True
TEMPLATE_DEBUG = True
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
"NAME": "django_deploy",
"USER": "foo",
"PASSWORD": "bar",
"HOST": "localhost",
"PORT": "5432",
}
}
Inicie o servidor de teste para garantir que tudo ainda funcione. Adicione mais alguns registros ao banco de dados.
Configuração do Heroku
Adicione um Procfile ao diretório principal:
$ touch Procfile
e adicione o seguinte código ao arquivo:
web: python manage.py runserver 0.0.0.0:$PORT --noreload
Instale o cinto de ferramentas Heroku:
$ pip install django-toolbelt
Congele as dependências:
$ pip freeze > requirements.txt
Atualize o wsgi.py Arquivo:
from django.core.wsgi import get_wsgi_application
from dj_static import Cling
application = Cling(get_wsgi_application())
Teste suas configurações do Heroku localmente:
$ foreman start
Navegue até http://localhost:5000/.
Parece bom? Vamos colocar o Amazon S3 em execução.
Amazon S3
Embora seja hipoteticamente possível hospedar arquivos estáticos em seu repositório Heroku, é melhor usar um host de terceiros, especialmente se você tiver um aplicativo voltado para o cliente. O S3 é fácil de usar e requer apenas algumas alterações em seu settings.py Arquivo.
Instalar dependências:
$ pip install django-storages
$ pip install boto
Adicionar
storages
e boto
para seu INSTALLED_APPS
em “configurações.py” Adicione o seguinte código ao final de “settings.py”:
# Storage on S3 settings are stored as os.environs to keep settings.py clean
if not DEBUG:
AWS_STORAGE_BUCKET_NAME = os.environ['AWS_STORAGE_BUCKET_NAME']
AWS_ACCESS_KEY_ID = os.environ['AWS_ACCESS_KEY_ID']
AWS_SECRET_ACCESS_KEY = os.environ['AWS_SECRET_ACCESS_KEY']
STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
S3_URL = 'http://%s.s3.amazonaws.com/' % AWS_STORAGE_BUCKET_NAME
STATIC_URL = S3_URL
As configurações dependentes do ambiente da AWS são armazenadas como variáveis ambientais. Portanto, não precisamos configurá-los no terminal toda vez que executamos o servidor de desenvolvimento, podemos configurá-los em nosso virtualenv
activate
roteiro. Obtenha o nome do AWS Bucket, o ID da chave de acesso e a chave de acesso secreta do S3. Abra myenv/bin/activate
e anexe o seguinte código (certifique-se de adicionar suas informações específicas que você acabou de extrair do S3):# S3 deployment info
export AWS_STORAGE_BUCKET_NAME=[YOUR AWS S3 BUCKET NAME]
export AWS_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXX
export AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXX
Desative e reative seu virtualenv e, em seguida, inicie o servidor local para garantir que as alterações tenham efeito:
$ foreman start
Mate o servidor e atualize o requirements.txt Arquivo:
$ pip freeze > requirements.txt
Enviar para Github e Heroku
Vamos fazer backup de nossos arquivos no Github antes de enviar para o Heroku:
$ git add .
$ git commit -m "update project for heroku and S3"
$ git push -u origin master
Crie um projeto/repositório Heroku:
$ heroku create <name>
Dê o nome que quiser.
PUSH para Heroku:
$ git push heroku master
Envie as variáveis ambientais da AWS para o Heroku
$ heroku config:set AWS_STORAGE_BUCKET_NAME=[YOUR AWS S3 BUCKET NAME]
$ heroku config:set AWS_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXX
$ heroku config:set AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXX
Colete os arquivos estáticos e envie para a Amazon:
$ heroku run python manage.py collectstatic
Adicionar banco de dados de desenvolvimento:
$ heroku addons:add heroku-postgresql:dev
Adding heroku-postgresql on deploy_django... done, v13 (free)
Attached as HEROKU_POSTGRESQL_COPPER_URL
Database has been created and is available
! This database is empty. If upgrading, you can transfer
! data from another database with pgbackups:restore.
Use `heroku addons:docs heroku-postgresql` to view documentation.
$ heroku pg:promote HEROKU_POSTGRESQL_COPPER_URL
Promoting HEROKU_POSTGRESQL_COPPER_URL to DATABASE_URL... done
Agora sincronize o banco de dados:
$ heroku run python manage.py syncdb
Transferência de dados
Precisamos transferir os dados do banco de dados local para o banco de dados de produção.
Instale o complemento Heroku PGBackups:
$ heroku addons:add pgbackups
Despeje seu banco de dados local:
$ pg_dump -h localhost -Fc library > db.dump
Para que o Heroku acesse o dump de banco de dados, você precisa enviá-lo para a Internet em algum lugar. Você pode usar um site pessoal, caixa de depósito ou S3. Eu simplesmente fiz o upload para o bucket do S3.
Importe o dump para o Heroku:
$ heroku pgbackups:restore DATABASE http://www.example.com/db.dump
Teste
Vamos testar para ter certeza de que tudo funciona.
Primeiro, atualize seus hosts permitidos para seu domínio específico em settings.py :
ALLOWED_HOSTS = ['[your-project-name].herokuapp.com']
Confira seu aplicativo:
$ heroku open
Tecido
O Fabric é usado para automatizar a implantação do seu aplicativo.
Instalar:
$ pip install fabric
Crie o arquivo fab:
$ touch fabfile.py
Em seguida, adicione o seguinte código:
from fabric.api import local
def deploy():
local('pip freeze > requirements.txt')
local('git add .')
print("enter your git commit comment: ")
comment = raw_input()
local('git commit -m "%s"' % comment)
local('git push -u origin master')
local('heroku maintenance:on')
local('git push heroku master')
local('heroku maintenance:off')
Teste:
$ fab deploy
Tem perguntas ou comentários? Participe da discussão abaixo.