I am trying to deploy my static files of my application that will go to heroku, in amazon s3, because that is how I have it configured in my settings.
When I run the command heroku run python manage.py collectstatic
I get the following error:
(nrb_dev) ➜ neurorehabilitation_projects git:(master) ✗ heroku run python manage.py collectstatic
Running python manage.py collectstatic on neurorehabilitation.... up, run.5168
python: can't open file 'manage.py': [Errno 2] No such file or directory
(nrb_dev) ➜ neurorehabilitation_projects git:(master) ✗
This is strange to me, since I am currently in the directory where the file is located.manage.py
I tried to apply permissions to the file manage.py
using chmod +x manage.py
but the result is the same
When I run the command git push heroky master
without deploying the statics before with heroku run python manage.py collectstatic
, I have this log:
remote: $ python manage.py collectstatic --noinput
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.4/site-packages/django/core/management/__init__.py", line 353, in execute_from_command_line
remote: utility.execute()
remote: File "/app/.heroku/python/lib/python3.4/site-packages/django/core/management/__init__.py", line 345, in execute
remote: self.fetch_command(subcommand).run_from_argv(self.argv)
remote: File "/app/.heroku/python/lib/python3.4/site-packages/django/core/management/base.py", line 348, in run_from_argv
remote: self.execute(*args, **cmd_options)
remote: File "/app/.heroku/python/lib/python3.4/site-packages/django/core/management/base.py", line 399, in execute
remote: output = self.handle(*args, **options)
remote: File "/app/.heroku/python/lib/python3.4/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 176, in handle
remote: collected = self.collect()
remote: File "/app/.heroku/python/lib/python3.4/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 98, in collect
remote: for path, storage in finder.list(self.ignore_patterns):
remote: File "/app/.heroku/python/lib/python3.4/site-packages/django/contrib/staticfiles/finders.py", line 112, in list
remote: for path in utils.get_files(storage, ignore_patterns):
remote: File "/app/.heroku/python/lib/python3.4/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.4/site-packages/django/core/files/storage.py", line 299, in listdir
remote: for entry in os.listdir(path):
remote: FileNotFoundError: [Errno 2] No such file or directory: '/app/neurorehabilitation/settings/static'
With a different project I was able to successfully execute the command `heroku run python manage.py collectstatic``
I can't figure out the reason why my heroku toolbet can't find my filemanage.py
UPDATE
In order to have an early deployment of my application, I have chosen to disable the static files option in the platform by setting the environment variable DISABLE_COLLECT_STATIC
in this way:
(nrb_dev) ➜ neurorehabilitation_projects git:(master) ✗ heroku config:set DISABLE_COLLECTSTATIC=1
Setting config vars and restarting neurorehabilitation... done
DISABLE_COLLECTSTATIC: 1
(nrb_dev) ➜ neurorehabilitation_projects git:(master)
This way, when I git push heroku master
finally did it I was able to deploy my application because the final notification was:
remote:
remote:
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 46M
remote: -----> Launching...
remote: Released v15
remote: https://neurorehabilitation.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/neurorehabilitation.git
* [new branch] master -> master
(nrb_dev) ➜ neurorehabilitation_projects git:(master) ✗
As you can see, in my main link https://neurorehabilitation.herokuapp.com/ there is an error, I assume it is because the static files were not placed or are not being related... I don't know if I'm right? I am?
But something that intrigues me is that I can detail the Django admin https://neurorehabilitation.herokuapp.com/admin/ and it is something that intrigues me because the Django administrator also has static files, so I don't know if heroku is there or not working with them...
What will have happened here in this situation with my static files?
However, I continued and this time if I can remotely deploy actions involving the command on heroku pyhon manage.py <acción>
, proof of this is that I effectively perform my first migrations of my application:
(nrb_dev) ➜ neurorehabilitation_projects git:(master) ✗ heroku run python manage.py migrate
Running python manage.py migrate on neurorehabilitation.... up, run.7836
Operations to perform:
Apply all migrations: contenttypes, auth, userprofiles, sessions, medical_encounter_information, admin
Running migrations:
Rendering model states... DONE
Applying contenttypes.0001_initial... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0001_initial... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying userprofiles.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying userprofiles.0002_auto_20160225_2130... OK
Applying userprofiles.0003_auto_20160225_2130... OK
Applying medical_encounter_information.0001_initial... OK
Applying medical_encounter_information.0002_auto_20160225_2130... OK
Applying medical_encounter_information.0003_auto_20160225_2130... OK
Applying medical_encounter_information.0004_auto_20160225_2211... OK
Applying medical_encounter_information.0005_auto_20160225_2211... OK
Applying medical_encounter_information.0006_auto_20160225_2303... OK
Applying medical_encounter_information.0007_auto_20160229_2204... OK
Applying medical_encounter_information.0008_auto_20160229_2208... OK
Applying medical_encounter_information.0009_auto_20160301_0130... OK
Applying medical_encounter_information.0010_auto_20160301_0312... OK
Applying medical_encounter_information.0011_auto_20160301_1525... OK
Applying medical_encounter_information.0012_auto_20160301_1601... OK
Applying medical_encounter_information.0013_auto_20160301_1606... OK
Applying medical_encounter_information.0014_auto_20160301_1629... OK
Applying medical_encounter_information.0015_auto_20160301_1633... OK
Applying medical_encounter_information.0016_auto_20160301_1636... OK
Applying sessions.0001_initial... OK
Applying userprofiles.0004_auto_20160225_2211... OK
Applying userprofiles.0005_auto_20160225_2211... OK
Applying userprofiles.0006_auto_20160225_2303... OK
Applying userprofiles.0007_auto_20160229_2204... OK
Applying userprofiles.0008_auto_20160229_2208... OK
Applying userprofiles.0009_auto_20160301_0130... OK
Applying userprofiles.0010_auto_20160301_0312... OK
Applying userprofiles.0011_auto_20160301_1525... OK
Applying userprofiles.0012_auto_20160301_1601... OK
Applying userprofiles.0013_auto_20160301_1606... OK
Applying userprofiles.0014_auto_20160301_1629... OK
Applying userprofiles.0015_auto_20160301_1633... OK
Applying userprofiles.0016_auto_20160301_1636... OK
(nrb_dev) ➜ neurorehabilitation_projects git:(master)
I also managed to create in my app deployed on heroku a super user for it, from my local toolbet:
(nrb_dev) ➜ neurorehabilitation_projects git:(master) ✗ heroku run python manage.py createsuperuser
Running python manage.py createsuperuser on neurorehabilitation.... up, run.5381
Username: bgarcial
Email address: [email protected]
Password:
Password (again):
Superuser created successfully.
(nrb_dev) ➜ neurorehabilitation_projects git:(master) ✗
Then I deactivate the previously configured environment variable DISABLE_COLLECTSTATIC=1
(What I have done is delete it from my heroku dashboard in the settings of my application)
But when I want to run the command again heroku run python manage.py collectstatic
, this happens:
(nrb_dev) ➜ neurorehabilitation_projects git:(master) ✗ heroku run python manage.py collectstatic
Running python manage.py collectstatic on neurorehabilitation.... up, run.9342
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.4/site-packages/django/core/management/__init__.py", line 353, in execute_from_command_line
utility.execute()
File "/app/.heroku/python/lib/python3.4/site-packages/django/core/management/__init__.py", line 345, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/app/.heroku/python/lib/python3.4/site-packages/django/core/management/base.py", line 348, in run_from_argv
self.execute(*args, **cmd_options)
File "/app/.heroku/python/lib/python3.4/site-packages/django/core/management/base.py", line 399, in execute
output = self.handle(*args, **options)
File "/app/.heroku/python/lib/python3.4/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 176, in handle
collected = self.collect()
File "/app/.heroku/python/lib/python3.4/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 98, in collect
for path, storage in finder.list(self.ignore_patterns):
File "/app/.heroku/python/lib/python3.4/site-packages/django/contrib/staticfiles/finders.py", line 112, in list
for path in utils.get_files(storage, ignore_patterns):
File "/app/.heroku/python/lib/python3.4/site-packages/django/contrib/staticfiles/utils.py", line 28, in get_files
directories, files = storage.listdir(location)
File "/app/.heroku/python/lib/python3.4/site-packages/django/core/files/storage.py", line 299, in listdir
for entry in os.listdir(path):
FileNotFoundError: [Errno 2] No such file or directory: '/app/neurorehabilitation/settings/static'
(nrb_dev) ➜ neurorehabilitation_projects git:(master) ✗
Seeing all this, I assume that the error is here at the end:
directories, files = storage.listdir(location)
File "/app/.heroku/python/lib/python3.4/site-packages/django/core/files/storage.py", line 299, in listdir
for entry in os.listdir(path):
FileNotFoundError: [Errno 2] No such file or directory: '/app/neurorehabilitation/settings/static'
And I assume that in the remote application that I have deployed, the directory is not found, static
which, like in the local one, is from there where they originate to be stored in a CDN, in this case to amazon S3.
I don't know how to deal with this, why are the directories that I have on my local machine not fully generated in my deployment?
UPDATE 2
I have run heroku run bash
to detail the directory structure in my cloud app and I am able to detail the root of my project, called /app
in heroku.
(nrb_dev) ➜ neurorehabilitation_projects git:(master) ✗ heroku run bash
Running bash on neurorehabilitation.... up, run.5840
~ $ pwd
/app
~ $
By listing its content I see all my directories and files, similar to how I have them in my IDE/development environment
~ $ ls
avatars custom_storages.py django-multiselectfield-0.1.3.tar.gz functional_tests manage.py medical_encounter_information neurorehabilitation Procfile requirements requirements.txt runtime.txt userprofiles
Since my error has to do with this file...
FileNotFoundError: [Errno 2] No such file or directory: '/app/neurorehabilitation/settings/static'
Then I enter that directory /app/neurorehabilitation/settings/
but I see that there is no directory called static
in there as heroku tries to search for it
~ $ cd /app/neurorehabilitation/settings/
~/neurorehabilitation/settings $ ls
base.py development.py __init__.py production.py staging.py testing.py
~/neurorehabilitation/settings $
And this is because according to the directory structure that I established when I created my Django project in my local development environment, I defined the following:
So, according to this, why git when deploying to heroku is looking for a path neurorehabilitation/settings/static
when it is not given, from the original source (my machine or development environment) ...
What could I do about it, because heroku, when I give it, heroky run python manage.py collectstatic
it looks for a directory that does not exist or is not included in the file structure of my project?
I even think that this is the reason why my static files are not shown, because of course it is obvious, I did not upload them in the push
then in my main url of the application already deployed https://neurorehabilitation.herokuapp.com they are not rendered or neither my templates nor my CSS nor my JS because I suppose that according to what happens to me, heroku looks for them in that directory that doesn't exist, right?
Although I don't know why the admin works https://neurorehabilitation.herokuapp.com/admin/ despite being an app (django-suit) but this one has CSS JS and others...
You may have misunderstood how heroku works in the deployment sense regarding files and directories
I appreciate any guidance :)
I've wanted to create a step-by-step answer based on some guidance I've received (including the answers and comments on this question) and what I've been able to find from resources and information around the topic.
Next I will share the step by step that I have done for the deployment of my application in Heroku. I hope that what I can write here can be useful.
settings
deploying to HerokuThe issue that I couldn't deploy my static files to Heroku was in my file configuration
settings/base.py
Specifically, the problem was in the value that my directive called
PROJECT_ROOT
. Heroku suggests that the configuration directivePROJECT_ROOT
be in this form:I configured
PROJECT_ROOT
( I have called itBASE_DIR
in my filesettings/base.py
and it will be referred to from here on in my answer) as Heroku said, but the error always appeared.What I decided was that since BASE_DIR has a default configuration value when the Django project is created, so I left it as is with that value and not as Heroku says.
So things, my error I had, which was this:
it was because I had a
BASE_DIR
like this:So, to correct it, finally my file
settings/base.py
to configure my application and that it be deployed in Heroku, has been in this form:Actually, the root of the error is in the value that the directive took,
STATICFILES_DIRS
which is the one that finally sets the standard in relation to the directory structure of the static files, regardless of the infrastructure where they are deployed.By having my BASE_DIR configured in a certain way, this affects the value that it takes
STATICFILES_DIRS
, which also remains in this way for a correct deployment of my application: (I think that is how Django puts it by default, so there is no need to move nothing with her)As I have a settings directory (
settings/{base.py, development.py,production.py,testing.py,staging.py}
) and as I am currently preparing to put my application into production on Heroku, then I must configure my file appropriately,settings/production.py
since it is the one that Heroku will take for the deployment configuration.My file
settings/production.py
in relation to Heroku looks like this:It's worth noting that if you don't have a set of settings like I do here, all these settings can go in the settings.py file that Django generates by default when you create the project.
Additionally, it is also necessary to install the package
dj-database-url
in my virtual environment that I use on my machineand likewise add it to my file
requirements/production.txt
in this wayPara los requerimientos de paquetes, también se tiene un conjunto de archivos de esta forma
requirements/{base.txt,development.txt,production.txt,testing.txt}
acorde a esta definición u orientaciónEntonces, además, también he querido compartir el proceso de despliegue de mi aplicación Django en Heroku y otros requisitos para que se haga efectivo.
Adicionalmente, para que el proceso de despligue sea exitoso, es necesario tener en la raíz de mi proyecto los siguientes archivos:
requirements.txt: Como había mencionado anteriormente, tengo este conjunto de archivos para las dependencias de mis paquetes
requirements/{base.txt,development.txt,production.txt,testing.txt}
Entonces en la raíz de mi proyecto creo un archivo llamado
requirements.txt
(ver recuadro amarillo en el enlace) con el siguiente contenido:Y mi archivo
requirements/production.txt
ha quedado asi:El archivo
requirements/base.txt
contiene todas las dependencias o paquetes necesarios que son base para mi aplicación.runtime.txt
Acorde a este enlace, es necesario que Heroku instale la versión de python con la cual estamos trabajando, en mi caso, tengo la 3.4.3, por lo que el contenido de mi archivo runtime.txt (que también debe ir en la raíz de mi proyecto) es:
Procfile
Segun este enlace el archivo
Procfile
Con relación a esta definición, básicamente lo que hacemos es que nuestro archivo
Procfile
tendrá la instrucción que habilitará el servidor gunicorn que tomará las peticiones y las redirigirá a python, por lo cual es WSGIAsi las cosas, el archivo Procfile en la raíz del proyecto debe quedar asi:
Es necesario instalar Heroku Toolbet el cual proporciona acceso a una interfaz de línea de comandos de Heroku (basicamente es una porción o un sistema operativo unix de la maquina en donde esta alojada mi aplicación en Heroku) la cual es utilizada para administrar y escalar aplicaciones asi como extensiones, entre otras cosas.
Probamos el acceso a Heroku desde nuestra máquina de esta forma:
Acorde a esta respuesta como mi aplicación a desplegar es python y Django, la aplicación en Heroku desde la herramienta toolbet debe ser creada de esta manera:
Entonces, de esta manera, mi aplicación Heroku se crea en mi dashboard en mi cuenta web:
Particularmente en mi proyecto, en mi entorno virtual en mi maquina local, tengo algunas variables de entorno definidas. Algunas son utilizadas para ocultar valores como el de mis
SECRET_KEY
's,DATABASE_USER
,DATABASE_NAME
,DATABASE_PASSWORD
, y como estoy utilizando Amazon S3 para alojar mis archivos estáticos, entonces también utilizo algunas claves e identificadores para acceder a estos recursos en Amazon.Entonces como decíamos, es necesario indicarle a Heroku la forma en la que él conocerá estas variables de entorno.
De acuerdo a este enlace, se configuran las siguientes variables via heroku toolbeet de esta forma:
DJANGO_SETTINGS_MODULE
Mi despliegue, a nivel de configuración, será guiado por el archivo
settings/production.py
el cual hereda desettings/base.py
que es el que tiene todas las dependencias necesarias desde la perspectiva del dominio de mi aplicación.Entonces la variable
DJANGO_SETTINGS_MODULE
en Heroku sera configurada de esta forma:SECRET_KEY
Para
SECRET_KEY
la configuración es la siguiente:Para el acceso a la base de datos, se configuran las siguientes variables:
DATABASE_NAME
Nombre de la base de datos:
DATABASE_USER
Usuario de la base de datos:
DATABASE_PASSWORD
Contraseña de la base de datos, el password debe ir en comillas simples
Para acceder a Amazon S3 es necesario configurar las siguientes variables:
El valor del ID debe ir en comillas simples
El valor de la clave debe ir en comillas simples
El valor del nombre del bucket (unidad de almacenamiento en Amazon) debe ir en comillas simples
Entonces, acorde a las opciones de arriba, en mi dashboard web, las variables de entorno han quedado asi:
git commit
) al repositorio de mi aplicación en HerokuPrimero examinamos los archivos que ha sido agregados y están en fase de
staging
o están listos para ser confirmados:Realizamos la operación de
commit
Antes de ello, es bueno que nos cercioremos que repositorios remotos o alias tenemos asignados. Es importante, porque el alias de
heroku
es el que debemos tener en cuenta para el deployment al repositorio que heroku crea al crear la aplicación.Desplegamos la aplicación al repositorio heroku
Realizamos el proceso de migración para que se hagan efectivos nuestros modelos:
A traves de
createsuperuser
And this is how my application is displayed on the heroku platform https://test-nrb.herokuapp.com/
Git doesn't save directories, only files and only creates directories when cloning that have files inside, so maybe if the directory is empty (meaning there is no file tracked in git inside the directory) then heroku won't will have that directory.
Also you have to keep in mind that in heroku you don't have write permission in
/app
, if you need to write files (even temporarily when compiling) you have to do it in/tmp