W tym samouczku zajmiemy się prostym lokalnym projektem Django, opartym na bazie danych MySQL, i przekonwertujemy go, aby działał w Heroku. Amazon S3 będzie używany do hostowania naszych plików statycznych, a Fabric zautomatyzuje proces wdrażania.
Projekt to prosty system wiadomości. Może to być aplikacja do zrobienia, blog, a nawet klon Twittera. Aby zasymulować rzeczywisty scenariusz, projekt zostanie najpierw utworzony z backendem MySQL, a następnie przekonwertowany na Postgres w celu wdrożenia w Heroku. Osobiście miałem pięć lub sześć projektów, w których musiałem zrobić dokładnie to samo:przekonwertować lokalny projekt, wspierany przez MySQL, na działającą aplikację na Heroku.
Konfiguracja
Wymagania wstępne
- Przeczytaj oficjalny przewodnik szybkiego startu Django w Heroku. Po prostu to przeczytaj. Pomoże Ci to zorientować się, co będziemy robić w tym samouczku. Będziemy używać oficjalnego samouczka jako przewodnika po naszym własnym, bardziej zaawansowanym procesie wdrażania.
- Utwórz konto AWS i skonfiguruj aktywny zasobnik S3.
- Zainstaluj MySQL.
Zacznijmy
Zacznij od pobrania projektu testowego tutaj, rozpakuj, a następnie aktywuj wirtualne środowisko:
$ cd django_heroku_deploy
$ virtualenv --no-site-packages myenv
$ source myenv/bin/activate
Utwórz nowe repozytorium na Github:
$ curl -u 'USER' https://api.github.com/user/repos -d '{"name":"REPO"}'
Pamiętaj, aby zastąpić wszystkie wersaliki SŁOWA KLUCZOWE własnymi ustawieniami. Na przykład:curl -u 'mjhea0' https://api.github.com/user/repos -d '{"name":"django-deploy-heroku-s3"}'
Dodaj plik readme, zainicjuj lokalne repozytorium Git, a następnie PRZEŚLIJ lokalną kopię do 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
Pamiętaj, aby zmienić adres URL na adres URL repozytorium utworzony w poprzednim kroku.
Skonfiguruj nową bazę danych MySQL o nazwie 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
Zaktualizuj settings.py :
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django_deploy',
'USER': 'root',
'PASSWORD': 'your_password',
}
}
Zainstaluj zależności:
$ pip install -r requirements.txt
$ python manage.py syncdb
$ python manage.py runserver
Uruchom serwer pod adresem http://localhost:8000/admin/ i upewnij się, że możesz zalogować się do administratora. Dodaj kilka elementów do Whatever
obiekt. Zabij serwer.
Konwertuj z MySQL na Postgres
Uwaga: W tej hipotetycznej sytuacji załóżmy, że pracujesz nad tym projektem przez jakiś czas przy użyciu MySQL, a teraz chcesz przekonwertować go do Postgresa.
Zainstaluj zależności:
$ pip install psycopg2
$ pip install py-mysql2pgsql
Skonfiguruj bazę danych Postgres:
$ psql -h localhost
psql (9.2.4)
Type "help" for help.
michaelherman=# CREATE DATABASE django_deploy;
CREATE DATABASE
michaelherman=# \q
Przenieś dane:
$ py-mysql2pgsql
To polecenie tworzy plik o nazwie mysql2pgsql.yml , zawierający następujące informacje:
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
Zaktualizuj to dla swojej konfiguracji. Ten przykład obejmuje tylko podstawową konwersję. Możesz także uwzględnić lub wykluczyć niektóre tabele. Zobacz pełny przykład tutaj.
Przenieś dane:
$ py-mysql2pgsql -v -f mysql2pgsql.yml
Po przeniesieniu danych zaktualizuj plik settings.py plik:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
"NAME": "your_database_name",
"USER": "foo",
"PASSWORD": "bar",
"HOST": "localhost",
"PORT": "5432",
}
}
Na koniec ponownie zsynchronizuj bazę danych, uruchom serwer testowy i dodaj kolejny element do bazy danych, aby upewnić się, że konwersja się powiodła.
Dodaj plik local_settings.py
Dodając local_settings.py możesz rozszerzyć plik settings.py plik z ustawieniami odpowiednimi dla Twojego lokalnego środowiska, podczas gdy główny settings.py plik jest używany wyłącznie w środowiskach pomostowych i produkcyjnych.
Upewnij się, że dodałeś local_settings.py do Twojego .gitignore plik w celu utrzymania pliku poza twoimi repozytoriami. Ci, którzy chcą używać lub wnosić swój wkład w Twój projekt, mogą następnie sklonować repozytorium i utworzyć własne local_settings.py plik specyficzny dla ich własnego środowiska lokalnego.
Chociaż ta metoda używania dwóch plików ustawień jest od wielu lat konwencją, wielu programistów Pythona używa teraz innego wzorca o nazwie The One True Way. Możemy przyjrzeć się temu wzorcowi w przyszłym samouczku.
Aktualizuj settings.py
Musimy wprowadzić trzy zmiany w naszym bieżącym settings.py plik:
Zmień DEBUG
tryb na fałsz:
DEBUG = False
Dodaj następujący kod na końcu pliku:
# 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
Zaktualizuj ustawienia bazy danych:
# we only need the engine name, as heroku takes care of the rest
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
}
}
Utwórz swój local_settings.py plik:
$ touch local_settings.py
$ pip install dj_database_url
Następnie dodaj następujący kod:
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",
}
}
Uruchom serwer testowy, aby upewnić się, że wszystko nadal działa. Dodaj jeszcze kilka rekordów do bazy danych.
Konfiguracja Heroku
Dodaj profil do głównego katalogu:
$ touch Procfile
i dodaj następujący kod do pliku:
web: python manage.py runserver 0.0.0.0:$PORT --noreload
Zainstaluj pasek narzędzi Heroku:
$ pip install django-toolbelt
Zablokuj zależności:
$ pip freeze > requirements.txt
Zaktualizuj wsgi.py plik:
from django.core.wsgi import get_wsgi_application
from dj_static import Cling
application = Cling(get_wsgi_application())
Przetestuj swoje ustawienia Heroku lokalnie:
$ foreman start
Przejdź do http://localhost:5000/.
Wygląda dobrze? Uruchommy Amazon S3.
Amazonka S3
Chociaż hipotetycznie możliwe jest hostowanie plików statycznych w repozytorium Heroku, najlepiej jest użyć hosta innej firmy, zwłaszcza jeśli masz aplikację skierowaną do klienta. S3 jest łatwy w użyciu i wymaga tylko kilku zmian w pliku settings.py plik.
Zainstaluj zależności:
$ pip install django-storages
$ pip install boto
Dodaj storages
i boto
do Twoich INSTALLED_APPS
w „settings.py”
Dodaj następujący kod na końcu „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
Ustawienia zależne od środowiska AWS są przechowywane jako zmienne środowiskowe. Więc nie musimy ustawiać ich z terminala za każdym razem, gdy uruchamiamy serwer deweloperski, możemy ustawić je w naszym virtualenv activate
scenariusz. Pobierz nazwę zasobnika AWS, identyfikator klucza dostępu i tajny klucz dostępu z S3. Otwórz myenv/bin/activate
i dołącz następujący kod (upewnij się, że dodałeś konkretne informacje, które właśnie pobrałeś z 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
Dezaktywuj i ponownie aktywuj virtualenv, a następnie uruchom serwer lokalny, aby upewnić się, że zmiany weszły w życie:
$ foreman start
Zabij serwer, a następnie zaktualizuj plik requirements.txt plik:
$ pip freeze > requirements.txt
Przejdź do Github i Heroku
Zróbmy kopię zapasową naszych plików na Github przed PUSH do Heroku:
$ git add .
$ git commit -m "update project for heroku and S3"
$ git push -u origin master
Utwórz projekt/repozytorium Heroku:
$ heroku create <name>
Nazwij go, jak chcesz.
PRZEŚLIJ do Heroku:
$ git push heroku master
Wyślij zmienne środowiskowe AWS do 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
Zbierz pliki statyczne i wyślij do Amazon:
$ heroku run python manage.py collectstatic
Dodaj bazę danych deweloperskich:
$ 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
Teraz zsynchronizuj bazę danych:
$ heroku run python manage.py syncdb
Transfer danych
Musimy przenieść dane z lokalnej bazy danych do produkcyjnej bazy danych.
Zainstaluj dodatek Heroku PGBackups:
$ heroku addons:add pgbackups
Zrzuć lokalną bazę danych:
$ pg_dump -h localhost -Fc library > db.dump
Aby Heroku mógł uzyskać dostęp do zrzutu bazy danych, musisz przesłać go gdzieś do Internetu. Możesz użyć osobistej strony internetowej, skrzynki referencyjnej lub S3. Po prostu przesłałem go do wiadra S3.
Zaimportuj zrzut do Heroku:
$ heroku pgbackups:restore DATABASE http://www.example.com/db.dump
Test
Sprawdźmy, czy wszystko działa.
Najpierw zaktualizuj dozwolone hosty do określonej domeny na settings.py :
ALLOWED_HOSTS = ['[your-project-name].herokuapp.com']
Sprawdź swoją aplikację:
$ heroku open
Tkanina
Fabric służy do automatyzacji wdrażania aplikacji.
Zainstaluj:
$ pip install fabric
Utwórz plik fab:
$ touch fabfile.py
Następnie dodaj następujący kod:
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')
Test:
$ fab deploy
Masz pytania lub komentarze? Dołącz do dyskusji poniżej.