Heroku にデプロイしている Django アプリに、javascript、css などを含めるために、ファイルの静的ディレクトリを追加しようとしています。
heroku run python manage.py collectstatic
ストレージは AWS S3 で行われています。この静的ディレクトリを追加しようとする前に、コマンドが正常に機能し、管理サイトのすべてのアセットが AWS S3 バケットに配置された ため、この部分が機能していることがわかります。
基本的に、「コア」と呼ばれるプロジェクトのメイン アプリケーションと同じレベルに「static」というディレクトリを追加しました。collectstatic を実行したときに、このディレクトリ内のファイルが同様に AWS S3 バケットの「静的」の下に配置されることを期待していました。
しかし、これはアプリを Heroku にデプロイしようとすると得られるものです...
(primedminds-FA7a2hIW) bash-3.2$ git push heroku master
Counting objects: 2, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 236 bytes | 236.00 KiB/s, done.
Total 2 (delta 1), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Python app detected
remote: ! The latest version of Python 3.6 is python-3.6.6 (you are using python-3.6.5, which is unsupported).
remote: ! We recommend upgrading by specifying the latest version (python-3.6.6).
remote: Learn More: https://devcenter.heroku.com/articles/python-runtimes
remote: Skipping installation, as Pipfile.lock hasn't changed since last deploy.
remote: -----> $ python manage.py collectstatic --noinput
remote: /app/.heroku/python/lib/python3.6/site-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from release 2.8; in order to keep installing from binary please use "pip install psycopg2-binary" instead. For details see: <http://initd.org/psycopg/docs/install.html#binary-install-from-pypi>.
remote: """)
remote: Traceback (most recent call last):
remote: File "manage.py", line 10, in <module>
remote: execute_from_command_line(sys.argv)
remote: File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
remote: utility.execute()
remote: File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/__init__.py", line 365, in execute
remote: self.fetch_command(subcommand).run_from_argv(self.argv)
remote: File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/base.py", line 288, in run_from_argv
remote: self.execute(*args, **cmd_options)
remote: File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/base.py", line 335, in execute
remote: output = self.handle(*args, **options)
remote: File "/app/.heroku/python/lib/python3.6/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 189, in handle
remote: collected = self.collect()
remote: File "/app/.heroku/python/lib/python3.6/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 105, in collect
remote: for path, storage in finder.list(self.ignore_patterns):
remote: File "/app/.heroku/python/lib/python3.6/site-packages/django/contrib/staticfiles/finders.py", line 125, in list
remote: for path in utils.get_files(storage, ignore_patterns):
remote: File "/app/.heroku/python/lib/python3.6/site-packages/django/contrib/staticfiles/utils.py", line 28, in get_files
remote: directories, files = storage.listdir(location)
remote: File "/app/.heroku/python/lib/python3.6/site-packages/django/core/files/storage.py", line 313, in listdir
remote: for entry in os.listdir(path):
remote: FileNotFoundError: [Errno 2] No such file or directory: '/tmp/build_c0914e5498ba1b53e00fb3adb7ce14d8/static'
remote:
remote: ! Error while running '$ python manage.py collectstatic --noinput'.
remote: See traceback above for details.
remote:
remote: You may need to update application code to resolve this error.
remote: Or, you can disable collectstatic for this application:
remote:
remote: $ heroku config:set DISABLE_COLLECTSTATIC=1
remote:
remote: https://devcenter.heroku.com/articles/django-assets
remote: ! Push rejected, failed to compile Python app.
remote:
remote: ! Push failed
remote: Verifying deploy...
remote:
remote: ! Push rejected to primedminds.
remote:
To https://git.heroku.com/primedminds.git
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/primedminds.git'
また、collectstatic コマンドを手動で実行すると、別の欠落しているディレクトリが表示されます。「アプリ」という名前のアプリはなく、設定ファイルに「アプリ」についての言及がないことに注意してください。
(primedminds-FA7a2hIW) bash-3.2$ heroku run python manage.py collectstatic
Running python manage.py collectstatic on ⬢ primedminds... up, run.7871 (Free)
/app/.heroku/python/lib/python3.6/site-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from release 2.8; in order to keep installing from binary please use "pip install psycopg2-binary" instead. For details see: <http://initd.org/psycopg/docs/install.html#binary-install-from-pypi>.
""")
You have requested to collect static files at the destination
location as specified in your settings.
This will overwrite existing files!
Are you sure you want to do this?
Type 'yes' to continue, or 'no' to cancel: yes
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
utility.execute()
File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/__init__.py", line 365, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **cmd_options)
File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/base.py", line 335, in execute
output = self.handle(*args, **options)
File "/app/.heroku/python/lib/python3.6/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 189, in handle
collected = self.collect()
File "/app/.heroku/python/lib/python3.6/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 105, in collect
for path, storage in finder.list(self.ignore_patterns):
File "/app/.heroku/python/lib/python3.6/site-packages/django/contrib/staticfiles/finders.py", line 125, in list
for path in utils.get_files(storage, ignore_patterns):
File "/app/.heroku/python/lib/python3.6/site-packages/django/contrib/staticfiles/utils.py", line 28, in get_files
directories, files = storage.listdir(location)
File "/app/.heroku/python/lib/python3.6/site-packages/django/core/files/storage.py", line 313, in listdir
for entry in os.listdir(path):
FileNotFoundError: [Errno 2] No such file or directory: '/app/static’
これは私のsettings.pyファイルです:
"""
Django settings for primedminds project.
Generated by 'django-admin startproject' using Django 1.9.
For more information on this file, see
https://docs.djangoproject.com/en/1.9/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.9/ref/settings/
"""
import os
import socket
import django_heroku
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = ‘<redacted>'
# SECURITY WARNING: don't run with debug turned on in production!
if socket.gethostname().endswith('.local'): # True in your local computer
DEBUG = True
ALLOWED_HOSTS = ['localhost', '127.0.0.1',]
else:
DEBUG = False
ALLOWED_HOSTS = ['.herokuapp.com', 'primedminds.com',]
#ALLOWED_HOSTS = ['*']
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django': {
'handlers': ['console'],
'level': os.getenv('DJANGO_LOG_LEVEL', 'DEBUG'),
},
},
}
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'import_export',
'storages',
'core',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'primedminds.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'primedminds.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': os.environ['DATABASE_NAME'],
'USER': os.environ['DATABASE_USER'],
'PASSWORD': os.environ['DATABASE_PASSWORD'],
'HOST': '',
'PORT': '',
}
}
# Password validation
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/1.9/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'America/Los_Angeles'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = os.path.normpath(os.path.join(BASE_DIR, 'static'))
STATICFILES_DIRS = [
os.path.normpath(os.path.join(BASE_DIR, 'static')),
]
# AWS S3
AWS_ACCESS_KEY_ID = os.environ['AWS_ACCESS_KEY_ID']
AWS_SECRET_ACCESS_KEY = os.environ['AWS_SECRET_ACCESS_KEY']
AWS_STORAGE_BUCKET_NAME = 'primedminds'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
AWS_LOCATION = 'static'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
DEFAULT_FILE_STORAGE = 'primedminds.storage_backends.MediaStorage'
STATIC_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)
#ADMIN_MEDIA_PREFIX = STATIC_URL + 'admin/'
# Import export
#IMPORT_EXPORT_USE_TRANSACTIONS = True
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
# Configure Django App for Heroku.
#django_heroku.settings(locals(), staticfiles=True)
django_heroku.settings(locals())
更新 1:.gitignore
ファイルを設定しstatic
てstaticfiles
リスト したことを忘れていました。そのため、アップロードするファイルがないかのように動作していました。それらの行を削除すると、.gitignore
それは先に進みました。
ここで問題になるのは、予想どおり、ファイルが AWS S3 バケットに保存されない理由です。staticfiles
代わりに、 /tmp の下のディレクトリに移動しているようです。何が起こっているかは次のとおりです。
(primedminds-FA7a2hIW) bash-3.2$ git push heroku master
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 586 bytes | 586.00 KiB/s, done.
Total 6 (delta 3), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Python app detected
remote: ! The latest version of Python 3.6 is python-3.6.6 (you are using python-3.6.5, which is unsupported).
remote: ! We recommend upgrading by specifying the latest version (python-3.6.6).
remote: Learn More: https://devcenter.heroku.com/articles/python-runtimes
remote: Skipping installation, as Pipfile.lock hasn't changed since last deploy.
remote: -----> $ python manage.py collectstatic --noinput
remote: /app/.heroku/python/lib/python3.6/site-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from release 2.8; in order to keep installing from binary please use "pip install psycopg2-binary" instead. For details see: <http://initd.org/psycopg/docs/install.html#binary-install-from-pypi>.
remote: """)
remote: 148 static files copied to '/tmp/build_53bed4ea57eaa119caf33247adadfed7/staticfiles', 178 post-processed.
remote:
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 193.6M
remote: -----> Launching...
remote: Released v85
remote: https://primedminds.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/primedminds.git
fc1cde0..0033cfe master -> master
更新 2: AWS に保存されなかった理由の少なくとも 1 つはwhitenoise.storage.CompressedManifestStaticFilesStorage
、設定ファイルで設定した AWS ストレージ ミドルウェアではなく、WhiteNoise ローカル ファイル ストレージ ( )を使用したかったためであることが判明しました。
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage’
原因は、設定ファイルの末尾にある次の行でした。
django_heroku.settings(locals())
STATICFILES_STORAGE
その行は私の変数をオーバーライドします。だから私はそれを次のように変更しました:
django_heroku.settings(locals(), staticfiles=False)
これで解決すると思っていましたが、collectstatic はまだSTATICFILES_DIRS
AWS S3 バケットにあるファイルを入れていません。Heroku サーバーで次のコマンドを実行しました。
django-admin collectstatic --settings=primedminds.settings
そして、次の出力を得ました:
~ $ django-admin collectstatic --settings=primedminds.settings
/app/.heroku/python/lib/python3.6/site-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from release 2.8; in order to keep installing from binary please use "pip install psycopg2-binary" instead. For details see: <http://initd.org/psycopg/docs/install.html#binary-install-from-pypi>.
""")
You have requested to collect static files at the destination
location as specified in your settings.
This will overwrite existing files!
Are you sure you want to do this?
Type 'yes' to continue, or 'no' to cancel: yes
0 static files copied, 148 unmodified.
少なくとも今は、ファイルをローカルにコピーするだけではありません。しかし、まだ AWS にコピーされたファイルはありません。--clear
旗でも やってみましたが、ダイスはありませんでした。
[ちなみに、後者のコマンドは何らかの理由でプロジェクト設定ファイルをソースしなかったため、django-admin
ではなくコマンドを使用する必要がありました!]python manage.py collectstatic
これは非常に長くなってしまったので、おそらくこの時点では独り言を言っているにすぎませんが、記録として、私が今直面している問題は、今でも、collectstatic が期待どおりに動作しないのはなぜですか、私が持っているファイルを配置することです私STATICFILES_DIRS
のAWS S3バケットに?