I have made a code with python flask and I am following the next steps to deploy it:
Deploying to Heroku (takes 7 minutes)
Install heroku (if you don't have it yet)
$ npm i heroku -g
Login to heroku on the command line (if you have not already)
$ heroku login -i
Create an application (if you don't have it already)
$ heroku create <your_application_name>
Enviroment Variables (takes 2 minutes)
Now navigate to your heroku dashboard and look for your application settings, we have to manually add our environment variables into heroku:
You cannot create a .env file on Heroku, instead you need to manually create all the variables under your project settings.
Open your .env file and copy and paste each variable (FLASK_APP, DB_CONNECTION_STRING, etc.) to Heroku.
Deploying your database to Heroku (takes 3 minutes)
You local MySQL Database now has to be uploaded to a cloud, there are plenty of services that provide MySQL database hosting but we recommend JawDB because it has a Free Tier, its simple and 100% integrated with Heroku.
Go to your heroku project dashboard and look to add a new heroku add-on.
Look for JawDB MySQL and add it to your project (it may ask for a Credit Card but you will not be charged as long as your remain within 5mb database size, enough for your demo.
Once JawDB is added to your project look for the Connection String inside your JawDB dashboard, something like:
mysql://tqqa0ui0cga32nxd:eqi8nchjbpwth82v#c584md9egjnm02sk.5btxwkvyhwsf.us-east-1.rds.amazonaws.com:3306/45fds423rbtbr
Copy the connection string and create a new environment variable on your project settings.
Run migrations on heroku: After your database is connected, you have to create the tables and structure, you can do that by running the pipenv run upgrade command on the production server like this:
$ heroku run -a=<your_app_name> pipenv run upgrade
:warning: Note: Notice that you have to replace <your app name> with your application name, you also have to be logged into heroku in your terminal (you can do that by typing heroku login -i)
Push to the Heroku codebase
Commit and push to heroku, make sure you have added and committed your changes and push to heroku
$ git push heroku main hh
That is it!
Now the problem is when I run this command:
heroku run -a=<your_app_name> pipenv run upgrade
And the respons is:
bash: pipenv: command not found
This is my Pipfile.txt:
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
flask = "*"
sqlalchemy = "*"
flask-sqlalchemy = "*"
flask-migrate = "*"
flask-swagger = "*"
psycopg2-binary = "*"
python-dotenv = "*"
mysql-connector-python = "*"
flask-cors = "*"
gunicorn = "*"
mysqlclient = "*"
flask-admin = "*"
cloudinary = "*"
flask-login = "*"
pipenv = "*"
[requires]
python_version = "3.8"
[scripts]
start="flask run -p 3000 -h 0.0.0.0"
init="flask db init"
migrate="flask db migrate"
upgrade="flask db upgrade"
deploy="echo 'Please follow this 3 steps to deploy: https://github.com/4GeeksAcademy/flask-rest-hello/blob/master/README.md#deploy-your-website-to-heroku' "
These are the commands I run before deploying:
pipenv install;
mysql -u root -e "CREATE DATABASE example";
pipenv run init;
pipenv run migrate;
pipenv run upgrade;
If I don't run the upgrade in heroku this is what Release Log in heroku:
sqlalchemy.exc.DatabaseError: (mysql.connector.errors.DatabaseError) 2003 (HY000): Can't connect to MySQL server on 'localhost' (111)
(Background on this error at: http://sqlalche.me/e/14/4xp6)
It seems you are missing the pipenv tool or missing in PATH. You may install it using:
$ pip install pipenv
If pipenv already is installed check the PATH variable and if you are able to locate pipenv using $ which pipenv. Have a look at the docs regarding PATH:
https://pipenv-fork.readthedocs.io/en/latest/advanced.html
Related
I've been trying to configure an Amplify project with a Python based Lambda backend API.
I have followed the tutorials by creating an API through the AWS CLI and installing all the dependencies through pipenv.
When I cd into the function's directory, my Pipfile looks like this:
name = "pypi"
url = "https://pypi.python.org/simple"
verify_ssl = true
[dev-packages]
[packages]
src = {editable = true, path = "./src"}
flask = "*"
flask-cors = "*"
aws-wsgi = "*"
boto3 = "*"
[requires]
python_version = "3.8"
And when I run amplify push everything works and the Lambda Function gets created successfully.
Also, when I run the deploy pipeline from the Amplify Console, I see in the build logs that my virtual env is created and my dependencies are downloaded.
Something else that was done based on github issues (otherwise build would definitely fail) was adding the following to amplify.yml:
backend:
phases:
build:
commands:
- ln -fs /usr/local/bin/pip3.8 /usr/bin/pip3
- ln -fs /usr/local/bin/python3.8 /usr/bin/python3
- pip3 install --user pipenv
- amplifyPush --simple
Unfortunately, from the Lambda's logs (both dev and prod), I see that it fails importing every dependency that was installed through Pipenv. I added the following in index.py:
import os
os.system('pip list')
And saw that NONE of my dependencies were listed so I was wondering if the Lambda was running through the virtual env that was created, or was just using the default Python.
How can I make sure that my Lambda is running the virtualenv as defined in the Pipfile?
Lambda functions do not run in a virtualenv. Amplify uses pipenv to create a virtualenv and download the dependencies. Then Amplify packages those dependencies, along with the lambda code, into a zip file which it uploads to AWS Lambda.
Your problem is either that the dependencies are not packaged with your function or that they are packaged with a bad directory structure. You can download the function code to see exactly how the packaging went.
Started going a bit mad on this, hence first post.
I have yet to deploy an app public facing for others to use. They launch locally just fine..
How can I get this app to deploy on Heroku?
Here is my repository: https://github.com/codereyes-1/tesseract_flask_new
I wrote a python app in Flask that makes a call to google tesseract function. The app works locally but fails in Heroku.
There is no Flask build pack I can find. Some research returned "add a requirements.txt and Profile" but that didn't work.
Here is the build log from Heroku:
"
Building on the Heroku-20 stack
-----> Using buildpack: heroku/python
-----> App not compatible with buildpack: https://buildpack-registry.s3.amazonaws.com/buildpacks/heroku/python.tgz
More info: https://devcenter.heroku.com/articles/buildpacks#detection-failure
! Push failed
"
¯\(ツ)/¯
This is what you will need to do to deploy your app to Heroku:
Login to heroku on your terminal ($ heroku login)
Ensure your application is in a git repository ($ git remote -v)
Create a Heroku application ($ heroku apps:create my_app-app)
Create Postgres database ($ heroku addons:add heroku-postgresql:hobby-dev)
Log errors to STDOUT
Set environment variables in Heroku ($ heroku config:set LOG_TO_STDOUT=1 # Add others if you have them)
Install gunicorn and psycopg2 ($ pip3 install gunicorn psycopg2)
Add Procfile to root directory and update it ($ touch Procfile)
Update your requirements.txt (pip3 freeze > requirements.txt)
Commit your changes ($ git commit -m '<your-commit-message>')
A remote Heroku repository ($ heroku git:remote -a <your-heroku-app-name>)
Push to Heroku ($ git push heroku master)
I was missing "web: gunicorn app:app" in my Procfile, I matched python to supported versions in runtime.txt.App launches correctly with these settings.
#BeppeC #Still_learning #Gitau Harrison Thank you all for your help. I got the app deployed, and I learned how to deploy my other apps as well. 🤜🏽🤛🏽
I have a basic django app (Newsdiffs)that runs just fine at localhost:8000 with python website/manage.py runserver but I'd like to migrate it to Heroku and I can't figure out what my next step is.
I thought getting it running locally would translate to running it on Heroku, but I'm realizing that python website/manage.py runserver is launching the dev settings and I'm not sure how to tell it to use the main settings.
All that is in my Procfile is this:
web: python website/manage.py runserver
Locally, that works fine, though it launches it at http://127.0.0.1:8000/ which is probably not what I want on Heroku. So how do I figure out where to set the hostname and port? I don't see either in the app anyplace.
I have just drawn this list for myself two days ago.
It was put together after having followed the steps described in Heroku's help pages for python.
It's by no means definitive nor perfect, and it will change, but it's a valid trace, since I was able to put the site online.
Some issues remain, to be checked thoroughly, e.g. the location of the media/ directory where files are uploaded should/could live outside your project for security reasons (now it works, but I have noticed if the dyno sleeps then the files are not reached/displayed by the template later).
The same goes for the staticfiles/ directory (although this one seems to work fine).
Also, you might want to set django's debug mode to false.
So here it is:
My first steps to deploy an EXISTING django application to Heroku
ASSUMPTIONS:
a) your django project is in a virtual environment already
b) you have already collected all your project's required packages with
pip freeze > requirements.txt
and committed it to git
git add requirements.txt
git commit -m 'my prj requirements'
0) Activate your project's virtual environment
workon xyz #using virtualenvwrapper
then go to your django project's directory (DPD for short) if not already taken there
cd ~/prj/xyz (or cdproject with virtualenvwrapper if setup properly)
and create a new git branch for heroku twiddling to prevent messing things up
git checkout -b he
1) Create the app on heroku
heroku create xyz
that also adds heroku as a remote of your repo
2) Add the needed packages to requirements.txt
vi requirements.txt
add
dj-database-url==0.3.0
django-postgrespool==0.3.0
gunicorn==19.3.0
psycopg2==2.6
django-toolbelt==0.0.1
static3==0.5.1
whitenoise==2.0.3
3) Install all dependencies in the local venv
pip install -r requirements.txt --allow-all-external
4) Setup the heroku django settings
cd xyz
create a copy
cp setting.py settings_heroku.py
and edit it
vi settings_heroku.py
import os
import dj_database_url
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'), )
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
replace django's std db cfg with
DATABASES['default'] = dj_database_url.config()
DATABASES['default']['ENGINE'] = 'django_postgrespool'
and
WSGI_APPLICATION = 'xyz.wsgi_heroku.application'
5) Configure the necessary environment variables (heroku configs)
edit the .env file
vi .env
e.g.
DJANGO_SECRET_KEY=whatever
EMAIL_HOST_USER=youruser#gmail.com
EMAIL_HOST_PASSWORD=whateveritis
and/or set them manually if needed (in my case .env had no effect, wasn't loaded apparently, and had to set the vars manually for now)
heroku config:set DJANGO_SECRET_KEY=whatever
heroku config:set EMAIL_HOST_USER=youruser#gmail.com
heroku config:set EMAIL_HOST_PASSWORD=whateveritis
6) Create a separate wsgi file for heroku
cd xyx
cp wsgi.py wsgi_heroku.py
and edit it to make it point to the right settings
vi wsgi_heroku.py
from whitenoise.django import DjangoWhiteNoise
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xyz.settings_heroku")
application = get_wsgi_application()
application = DjangoWhiteNoise(application)
7) Make sure all the templates use
{% load staticfiles %}
8) Define the Procfile file so that it points to the right wsgi
e.g.
cd ~/prj/xyz (DPD)
vi Procfile
add
web: gunicorn xyz.wsgi_heroku --log-file -
9) Collect all static content into DPD/staticfiles/
locally, make sure django points to the right wsgi settings
export WSGI_APPLICATION=blogger.wsgi_heroku.application
python manage.py collectstatic
10) add the changes to the local git repo (he branch)
git add --all .
git commit -m 'first 4 heroku'
11) check the whole thing works locally
heroku local # in heroku's help they also add `web`, not needed?!
12) push your code to heroku
git push heroku he:master
13) make sure a instance of the app is running
heroku ps:scale web=1
14) create the tables on the heroku DB
heroku run python manage.py migrate
Note: if you see a message that says, “You just installed Django’s auth system, which means you don’t have any superusers defined. Would you like to create one now?”, type no.
15) add the superuser to the heroku DB
heroku run bash
python manage.py createsuperuser
and fill in the details, as usual
16) Populate the DB with the necessary fixtures
heroku run python manage.py loaddata yourfile.json
17) Visit the website page on heroku's webserver
heroku open
or go to
https://xyz.herokuapp.com/
and the admin
https://xyz.herokuapp.com/admin/
and the DB
https://xyz.herokuapp.com/db
Useful commands:
View the app's logs
heroku logs [--tail]
List add-ons deployed
heroku addons
and use one:
heroku addons:open <add-on-name>
Run a command on heroku (the remote env, where you are deploying)
heroku run python manage.py shell
heroku run bash
Set a config var on Heroku
heroku config:set VARNAME=whatever
View the config vars that are set (including the DB's)
heroku config
View postgres DB details
heroku pg
If you know some python and have a lot of experience building web apps in other languages but don't totally understand where Heroku fits, I highly recommend Discover Flask, which patched a lot of the holes in my understanding of how these pieces all fit together.
Some of the things that I worked out:
you really do need an isolated virtual environment if you're going to deploy to Heroku, because Heroku installs Python modules from the requirements.txt file.
Gunicorn is a web server, and you definitely need to run your app under Gunicorn or it won't run on Heroku.
The "Procfile" doesn't just give the command you use to run the app locally. And Heroku requires it. So if you've got an app that was built to run on Heroku and it doesn't include a Procfile, they left something out.
You don't tell Heroku what your hostname is. When you run heroku create it should tell you what your domain name is going to be. And every time you run git push heroku master (or whatever branch you're pushing, maybe it isn't master), Heroku will (try to) restart your app.
Heroku doesn't support sqlite. You have to run your Production DB in Postgres.
This doesn't directly answer my question, but it does fill in some of the missing pieces that were making it hard for me to even ask the right question. RTFM notwithstanding. :)
So I'm following this tutorial http://rosslaird.com/blog/building-a-project-with-mezzanine/ for building a project with Mezzanine. I am extremely new to all of this stuff (including Linux and the command line) and frankly do not really know what I am doing. I am at this part of the tutorial:
Run this command within the same directory as your local_settings.py and settings.py files: python manage.py createdb
The tutorial says that after I enter the "python manage" command I will be "asked to create a super-user, to provide details that user, and to answer a few more questions". When I entered the command none of those questions showed up. Why is this? Thank you very much in advance.
So you are trying to run this on the commandline right (terminal)?
sudo -u postgres createuser --superuser $USER
sudo -u postgres psql
postgres=# \password [enter your username]
Enter new password:
Enter it again:
\q
createdb $USER;
Change $USER with your designated name.
Sorry that the link you provided is 404'd (Most likely because this post is over 2 years old) .
But... I think I found it here (sort of)... There's a few bits and pieces missing which might have made it confusing. The "manage.py" should be in the parent directory that's prior to where your "settings.py | local_settings.py | urls.py" files reside. Just make sure you are in the appropriate directory when running the manage command. An easy ls or ls -la command will show you where your files are at within the directory. I myself am a novice Mezzanine user. I've been playing around with it for a year now and hope this info can serve as a quickstart guide for setting up Mezzanine on PostgreSQL while also resolving your issue.
So... Once the following conditions are met you should be able to create a Mezzanine project with a PostgreSQL database instance. But first, make sure you have Mezzanine set up and running without warnings or errors.
For Mezzanine Setup...
Preconditions:
You've installed Python, pip, etc...
Get virtualenv & virtualenvwrapper installed and configured.
pip install virtualenv
pip install virtualenvwrapper
Make sure to add your environment variables for your virtual environments. Just point the paths to where you want your Mezzanine projects to live as well as the environments. An easy way to do it is edit your bashrc in the home directory. I like to keep my virtualenvs separate from my working directory but adjust the paths to how you like. Just sudo vi ~/.bashrc then add the following...
## Virtualenvwrapper Settings
export WORKON_HOME=$HOME/.virtualenvs
export PROJECT_HOME=$HOME/envs/mezzanine/projects/live/here
source /usr/local/bin/virtualenvwrapper.sh
Note: Do i to insert text and when done editing type ctrl + c to exit the prompt then :wq! to write (save) and quit. Then close your terminal and open a new one so the new changes take effect. If not, restart your computer.
Next, cd over to your project directory cd ~/envs/mezzanine/projects/live/here and create your virtualenv for your Mezzanine project (It'll activate once created).
mkvirtualenv environment_name
You can deactivate your environment by simply typing deactivate in terminal. To re-activate your environment, type workon environment_name
Now you can install Mezzanine...
pip install -U mezzanine
Then create your Mezzanine project and watch those folders get created in your project directory...
mezzanine-project project_name
Collect your templates & static files.
python manage.py collecttemplates
python manage.py collectstatic
Now create your db instance (by default this will be SQLite if you haven't changed anything in settings.py .
Make sure you have your ALLOWED_HOSTS configured and edit your settings.py if you haven't already.
vi ~/envs/mezzanine/projects/live/here/project_name/project_name/settings.py .
ALLOWED_HOSTS = [
'127.0.0.1:8000',
'localhost',
'www.mydomain.com' #if you want to set that too.
]
Note: Don't forget to save your changes ctrl+c & :wq! .
At this point you should be able to go back a directory and run your server python manage.py runserver and get a response from your localhost (loopback address) at port 8000 by opening a browser and typing in 127.0.0.1:8000. (make sure your environment has been activated first)
Now For Your PostgreSQL Database...
Check this out. It's a pretty good resource and even touches base on virtualenv. You can also replace the Django references with Mezzanine (almost). The most important part is the database setup portion...
https://www.digitalocean.com/community/tutorials/how-to-use-postgresql-with-your-django-application-on-ubuntu-14-04
Install Postgres and dependencies. (You might need to run as sudo with -H flag here)
sudo apt-get install libpq-dev python-dev postgresql postgresql-contrib
Install psysopg2 (Might need sudo -H as well)
sudo pip install psycopg2
Login as "postgres" user:
sudo -su postgres
Run the psql shell command: psql. You should see the 'postgres=#' text.
Now, create your database (Remember to end psql statements with a semicolon;) CREATE DATABASE mydb;
Create database user: CREATE USER mydbuser WITH PASSWORD 'mypassword';
Set your user roles:
ALTER ROLE mydbuser SET client_encoding TO 'utf8';
ALTER ROLE mydbuser SET default_transaction_isolation TO 'read committed';
ALTER ROLE mydbuser SET timezone TO 'UTC';
8: Then give the database user access rights: GRANT ALL PRIVILEGES ON DATABASE mydb TO mydbuser;
Type ctrl + d to exit shell, then type exit to exit postgres user.
Now, go to your settings.py and local_settings.py in your Mezzanine project's working directory and modify your DATABASES settings with the credentials you previously created... cd ~/envs/mezzanine/projects/live/here/project_name/project_name/ and then vi settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'mydb',
'USER': 'mydbuser',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '5432',
}
}
Note: Don't forget local_settings.py
Now you can create your database via manage.py.
python manage.py createdb
The above command should prompt you to do the initial setup of your database along with your site info, as well as create a superuser. Just follow the prompts. To create additional superusers just do
`python manage.py createsuperuser' .
Now go back a directory to the project root cd .. and run your server python manage.py runserver . And now... you should have your new Mezzanine project running on PostgreSQL. Congratulations!! :)
The tutorial is just wrong. The writer has got confused with the Postgres createdb command used earlier, and the actual manage.py command, which is syncdb.
You would be better off using the actual Django tutorial.
I'm following tutorial from http://www.marinamele.com/2013/12/how-to-set-django-app-on-heroku-part-i.html and I can't pass the section with foreman -> guicorn configuration. My django app is in myproject directory.
When I'm trying to run command from my virtualenv, console freeze, but django app works in my browser - but foreman can't work properly
(myenv) ... gunicorn myproject.wsgi
But when I run:
(myenv) ... gunicorn myproject:wsgi
I got Failed to find application: 'myproject'.
my requirements.txt:
Django==1.6.5
argparse==1.2.1
gunicorn==19.0.0
wsgiref==0.1.2
this might of some help;
https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/gunicorn/
especially below 2 lines
This requires that your project be on the Python path; the simplest way to ensure that is to run this command from the same directory as your manage.py file