En este tutorial, tomaremos un proyecto Django local simple, respaldado por una base de datos MySQL, y lo convertiremos para que se ejecute en Heroku. Amazon S3 se utilizará para alojar nuestros archivos estáticos, mientras que Fabric automatizará el proceso de implementación.
El Proyecto es un sistema de mensajes simple. Podría ser una aplicación de tareas pendientes o un blog o incluso un clon de Twitter. Para simular un escenario real, el proyecto primero se creará con un backend de MySQL y luego se convertirá a Postgres para su implementación en Heroku. Personalmente, tuve cinco o seis proyectos en los que tuve que hacer exactamente esto:convertir un proyecto local, respaldado con MySQL, en una aplicación activa en Heroku.
Configuración
Requisitos previos
- Lea la guía oficial de inicio rápido de Django en Heroku. Solo leelo. Esto le ayudará a tener una idea de lo que lograremos en este tutorial. Usaremos el tutorial oficial como guía para nuestro propio proceso de implementación más avanzado.
- Cree una cuenta de AWS y configure un depósito S3 activo.
- Instalar MySQL.
Empecemos
Comience por descargar el proyecto de prueba aquí, descomprímalo y luego active un entorno virtual:
$ cd django_heroku_deploy
$ virtualenv --no-site-packages myenv
$ source myenv/bin/activate
Crea un nuevo repositorio en Github:
$ curl -u 'USER' https://api.github.com/user/repos -d '{"name":"REPO"}'
Asegúrese de reemplazar las PALABRAS CLAVE en mayúsculas con su propia configuración. Por ejemplo:curl -u 'mjhea0' https://api.github.com/user/repos -d '{"name":"django-deploy-heroku-s3"}'
Agregue un archivo Léame, inicialice el repositorio local de Git, luego EMPUJE la copia local a 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
Asegúrese de cambiar la URL a la URL de su repositorio que creó en el paso anterior.
Configure una nueva base de datos MySQL llamada 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
Actualizar settings.py :
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django_deploy',
'USER': 'root',
'PASSWORD': 'your_password',
}
}
Instale las dependencias:
$ pip install -r requirements.txt
$ python manage.py syncdb
$ python manage.py runserver
Ejecute el servidor en http://localhost:8000/admin/ y asegúrese de que puede iniciar sesión en el administrador. Agregue algunos elementos a Whatever
objeto. Mata al servidor.
Convertir de MySQL a Postgres
Instalar dependencias:
$ pip install psycopg2
$ pip install py-mysql2pgsql
Configure una base de datos de Postgres:
$ psql -h localhost
psql (9.2.4)
Type "help" for help.
michaelherman=# CREATE DATABASE django_deploy;
CREATE DATABASE
michaelherman=# \q
Migrar datos:
$ py-mysql2pgsql
Este comando crea un archivo llamado mysql2pgsql.yml , que contiene la siguiente información:
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
Actualice esto para su configuración. Este ejemplo solo cubre la conversión básica. También puede incluir o excluir ciertas tablas. Vea el ejemplo completo aquí.
Transferir los datos:
$ py-mysql2pgsql -v -f mysql2pgsql.yml
Una vez que se transfieran los datos, asegúrese de actualizar su settings.py archivo:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
"NAME": "your_database_name",
"USER": "foo",
"PASSWORD": "bar",
"HOST": "localhost",
"PORT": "5432",
}
}
Finalmente, vuelva a sincronizar la base de datos, ejecute el servidor de prueba y agregue otro elemento a la base de datos para asegurarse de que la conversión se realizó correctamente.
Agregue un archivo local_settings.py
Agregando un local_settings.py archivo, puede extender el settings.py archivo con la configuración relevante para su entorno local, mientras que el principal settings.py El archivo se utiliza únicamente para sus entornos de ensayo y producción.
Asegúrese de agregar local_settings.py a tu .gitignore archivo para mantener el archivo fuera de sus repositorios. Aquellos que quieran usar o contribuir con su proyecto pueden clonar el repositorio y crear su propio local_settings.py archivo específico para su propio entorno local.
Aunque este método de usar dos archivos de configuración ha sido convencional durante varios años, muchos desarrolladores de Python ahora usan otro patrón llamado The One True Way. Es posible que veamos este patrón en un tutorial futuro.
Actualizar configuración.py
Necesitamos hacer tres cambios en nuestro settings.py actual archivo:
Cambiar DEBUG
modo a falso:
DEBUG = False
Agregue el siguiente código al final del archivo:
# 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
Actualice la configuración de la base de datos:
# we only need the engine name, as heroku takes care of the rest
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
}
}
Cree su local_settings.py archivo:
$ touch local_settings.py
$ pip install dj_database_url
Luego agregue el siguiente 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",
}
}
Encienda el servidor de prueba para asegurarse de que todo sigue funcionando. Agregue algunos registros más a la base de datos.
Configuración de Heroku
Agregue un Procfile al directorio principal:
$ touch Procfile
y agregue el siguiente código al archivo:
web: python manage.py runserver 0.0.0.0:$PORT --noreload
Instale el cinturón de herramientas de Heroku:
$ pip install django-toolbelt
Congelar las dependencias:
$ pip freeze > requirements.txt
Actualice wsgi.py archivo:
from django.core.wsgi import get_wsgi_application
from dj_static import Cling
application = Cling(get_wsgi_application())
Pruebe su configuración de Heroku localmente:
$ foreman start
Navegue a http://localhost:5000/.
¿Luciendo bien? Hagamos funcionar Amazon S3.
Amazon S3
Aunque hipotéticamente es posible alojar archivos estáticos en su repositorio de Heroku, es mejor utilizar un host de terceros, especialmente si tiene una aplicación orientada al cliente. S3 es fácil de usar y solo requiere unos pocos cambios en su settings.py archivo.
Instalar dependencias:
$ pip install django-storages
$ pip install boto
Agregar storages
y boto
a tus INSTALLED_APPS
en "configuraciones.py"
Agregue el siguiente código al 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
La configuración dependiente del entorno de AWS se almacena como variables ambientales. Así que no tenemos que configurarlos desde la terminal cada vez que ejecutamos el servidor de desarrollo, podemos configurarlos en nuestro virtualenv activate
texto. Tome el nombre del depósito de AWS, el ID de la clave de acceso y la clave de acceso secreta de S3. Abra myenv/bin/activate
y agregue el siguiente código (asegúrese de agregar su información específica que acaba de obtener de 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
Desactive y reactive su virtualenv, luego inicie el servidor local para asegurarse de que los cambios surtieron efecto:
$ foreman start
Elimine el servidor, luego actualice requirements.txt archivo:
$ pip freeze > requirements.txt
Enviar a Github y Heroku
Hagamos una copia de seguridad de nuestros archivos en Github antes de enviarlos a Heroku:
$ git add .
$ git commit -m "update project for heroku and S3"
$ git push -u origin master
Crear un proyecto/repositorio de Heroku:
$ heroku create <name>
Nómbralo como quieras.
EMPUJAR a Heroku:
$ git push heroku master
Envía las variables ambientales de AWS a 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
Recopile los archivos estáticos y envíelos a Amazon:
$ heroku run python manage.py collectstatic
Agregar base de datos de desarrollo:
$ 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
Ahora sincroniza la base de datos:
$ heroku run python manage.py syncdb
Transferencia de datos
Necesitamos transferir los datos de la base de datos local a la base de datos de producción.
Instale el complemento Heroku PGBackups:
$ heroku addons:add pgbackups
Volcar su base de datos local:
$ pg_dump -h localhost -Fc library > db.dump
Para que Heroku acceda al volcado de db, debe cargarlo en Internet en algún lugar. Puede usar un sitio web personal, Dropbox o S3. Simplemente lo cargué en el depósito S3.
Importar el volcado a Heroku:
$ heroku pgbackups:restore DATABASE http://www.example.com/db.dump
Prueba
Probemos para asegurarnos de que todo funciona.
Primero, actualice sus hosts permitidos a su dominio específico en settings.py :
ALLOWED_HOSTS = ['[your-project-name].herokuapp.com']
Echa un vistazo a tu aplicación:
$ heroku open
Tela
Fabric se utiliza para automatizar la implementación de su aplicación.
Instalar:
$ pip install fabric
Crea el archivo fab:
$ touch fabfile.py
Luego agregue el siguiente 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')
Prueba:
$ fab deploy
¿Tiene preguntas o comentarios? Únase a la discusión a continuación.