Ukladanie statických a media súborov na Amazone S3 službách miesto ukladania na server aplikácie značne zvýši výkonnosť aplikácie. Taktiež rieši otázku ukladania súborov v prostredi Heroku, kde defaultne nieje aplikáciam umožnené trvalo ukladať súbory v rámci hierarchie súborov aplikácie. Táto implementácia je tiež dôležitá v ďalšom zlepšovaní výkonosti pri zavedení služby Amazon CloudFront, ktorý slúži ako Content Delivery Network (CDN).

V tomto článku si ukážeme ako nastaviť S3 bucket Amazonu. Nastavíme oprávnenia k súborom, upload súborov a ako celý mechanizmus spustiť v Djangu.

S3 Bucket Access

Je potrebné mať vytvorené konto na http://aws.amazon.com a ďalej sa riadiť týmto návodom:

  • Vytvoriť bucket
  • Nakonfigurovať bucket pre verejný prístup
  • Vytvoriť AWS používateľské skupiny (user group)
  • Nastaviť oprávnenia (policy) k používateľským skupinám aby mohli pristupovať k súborom
  • Vytvoriť používateľa a pridať ho k skupine

S3 a práca so static files v Djangu

URL k statickým súborom ako je obrázok, css alebo javascriptové súbory v Djangu by nikdy nemali byť hardcodované, čiže napísané natvrdo v rámci relatívnej cesty k súborom. Vždy je preto potrebné používať tag static tak ako to ukazuje príklad.

            {% load static %}
            <img src="{% static 'images/rooster.png' %}">
                            

Presun statických súborov do S3 Amazon

Je potrebné spraviť dve veci. Za prvé nastaviť všetky statické súbory aplikácie, aby ukazovali na S3 storage a za druhé, nejak tieto súbory tam fyzicky dostať. My si spravíme custom storage handler, ktorý zabezpečí aby pri volaní python manage.py collectstatic sa automaticky zobrali všetky statické súboru a uploadli na backet S3 servera.

Nainštalujeme si potrebné knižnice django-storages z ktorej budeme dedit našu custom triedu a boto3, ktorá slúži ako ovládač pre S3 Amazon storage.

Inštalácia knižníc

            pip install django-storages boto3
                            

Pridáme aplikáciu do settings.py

            INSTALLED_APPS = (
                ...,
                'storages',
            )
                            

Nepovinné údaje ohladne kešovania súborov nastavujú vlastnosti ako http header v response. Hovoria prehliadaču pri načítaní súboru aby ich kešoval na dlhú dobu.

            AWS_S3_OBJECT_PARAMETERS = {
                'Expires': 'Thu, 31 Dec 2099 20:00:00 GMT',
                'CacheControl': 'max-age=94608000',
            }
                            

Dalšie parametre, ktoré je potrebné pridať do settings.py

            AWS_STORAGE_BUCKET_NAME = 'BUCKET_NAME'
            AWS_S3_REGION_NAME = 'REGION_NAME'  # e.g. us-east-2
            AWS_ACCESS_KEY_ID = 'xxxxxxxxxxxxxxxxxxxx'
            AWS_SECRET_ACCESS_KEY = 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'

            # Hovorí django-storages od kadiaľ sa načítajú súbory.
            AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME

            # Hovorí staticfiles aplikácii aby použila S3Boto3 storage ked sa zadá príkaz
            # ... `collectstatic`
            STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
                            

Po nastavení stačí zadať

            python manage.py collectstatic
                            

Otestovanie cez develop server

            python manage.py runserver --nostatic
                            

Ak si pozriete zdrojový kod stránky v prehliadači, uvidíte, že statické súbory ukazujú na S3 storage. Je potrebné si všimnúť, že media súbory ostávajú stále na localhoste. Postupujeme ted ďalej.

Nastavenie Django media súborov na S3

Vytvoríme si súbor custom_storages.py na top-level úrovni projektu (v roote aplikácie) presne tam kde je aj súbor manage.py. Vytvoriíme si tak custom triedu, ktorá bude mať na starosti statické súbory a potom druhú triedu nižšie, ktorá bude mať na starosti media súbory.

            # custom_storages.py
            from django.conf import settings
            from storages.backends.s3boto3 import S3Boto3Storage

            class StaticStorage(S3Boto3Storage):
                location = settings.STATICFILES_LOCATION

            class MediaStorage(S3Boto3Storage):
                location = settings.MEDIAFILES_LOCATION
                            

Potom v settings:

            STATICFILES_LOCATION = 'static'
            STATICFILES_STORAGE = ‘custom_storages.StaticStorage'
            MEDIAFILES_LOCATION = 'media'
            DEFAULT_FILE_STORAGE = 'custom_storages.MediaStorage'
                            

Zhrnutie

S3 pravdepodobne obslúžia Vaše súbory oveľa lepšie ako kebyže ostanú na serveri kde je aplikácia. S3 Vám šetrí zdroje a tiež je tu možnosť lepšie škálovať a replikovať servre. V neposlednom rade ak už máme súbory na S3, ďalším krokom môže byť využitie CloudFront ale o tom niekedy inokedy.


Michal Kalman
Michal Kalman
Softvérový vývojár

Softvérový vývojár a podnikateľ zameriavajúci sa na platformu Java, Python a Javascript. Mám dlhoročné profesionálne skúsenosti s vývojom Java/JavaEE aplikácií. Som zakladateľ firmy Morione, ktorá sa venuje návrhom a realizáciou efektívnych webových aplikácií. Podporujem a vyvíjam viaceré startupy. Vo voľnom čase cestujem po svete, behám po horách, píšem blogy a tvorím kreatívne videá.