Join GitHub today
Can I actually deploy a cgi script to something like Heroku? #1
It's definitely possible, because you can use custom buildpacks on Heroku, which basically lets you do anything. But writing a custom buildpack could be quite an undertaking.
The answer here should work - run a persistent app that is a CGI server:
EDIT: Possibly your server.py could be run this way? Don't know enough about Python webserving to say.
And some loonbag has already written a custom buildpack which only does CGI - in shell script (turns out quite simple, but it's not exactly production-strength):
Actually using a custom buildpack is not too hard:
You can specify the buildpack in the app.json:
Which means you can deploy it using a button on the GitHub page:
EDIT: But you should probably ignore buildpacks and try and get server.py running under the normal Python buildpack.
I spent the last few hours attempting to deploy this to Heroku and it was a complete failure.
As for charliesome's cgi build-pack, it could well be what I need but without a README or any guidance to how that specific project works, I daren't use it.
Sounds like something to ignore for release 1, at least!
I'm not very familiar with Heroku (i've used Cloud Foundry, which is similar but different) and yeah, there are a lot of little nuances you need to somehow know about. Even more so if depoying CGI possibly.
I strongly suspect you can deploy your app without having to do anything special with buildpacks. You might have to change the server.py from the built-in web server to Flask. Would be great to find someone who's actually done this with Python and Heroku, ie not me (sorry).
You shouldn't have to play around with buildpacks, you have a
I've not tested all this but hopefully it should give you enough of a start and clue for what to google
Get the server running
First though since you're not using a framework which has a default way to run it you need to tell Heroku to do the
in it, which tells Heroku for the
By this point you should be able to deploy and it might not crash but it probably won't work.
To get the web server bit to work you will need to make it listen on the right port and to not just listen on
So first change line 4 in server.py to
HOST = "0.0.0.0"
The difference here is that
Next we need to get the the server to listen on a port that Heroku has exposed to the internet. Before running the command in
So we need to get access to that variable from inside the python process. In the
So in server.py add
at the top and change line 3 to
PORT = int(os.getenv("PORT", 8000))
It will then set
There is a slight security issue here, in that if you are developing on your machine someone else on the network can now get to your app, you might want this but if you don't you could change the code too:
PORT = os.getenv("PORT") # We are not running on Heroku if PORT is None: PORT = 8000 HOST = "127.0.0.1" else: HOST = "0.0.0.0" PORT = int(PORT)
Get the database working
The image of the code that Heroku uses is readonly so line 7 in database.py needs to use a different location. If we are lucky you might be able to change it to:
DATABASE = "/tmp/guestbook.db"
To get it working temporarily, the only issue here is that the computer running your code in Heroku is temporary, so after you haven't requested it in a while Heroku will stop the code and throw away the virtual machine which means next time it starts up
If you don't already have a database attached to the project you can provision one following this guide and you'll then have an environment variable called
So to access the database when running on Heroku you can change the database setup lines to:
import os import urlparse DATABASE_URL = os.getenv('DATABASE_URL') # use sqlite if DATABASE_URL is None: database = SqliteDatabase("guestbook.db") else: # extract all the database connection parameters from DATABASE_URL database_url = urlparse.urlparse(DATABASE_URL) # get rid of the "/" from the path to get the database name database_name = database_url.path[1:] # connection arguments are documented here: # http://initd.org/psycopg/docs/module.html#psycopg2.connect database = PostgresqlDatabase( database_name, user=database_url.username, password=database_url.password, host=database_url.hostname, port=database_url.port )
We're really close now
It should all work now, fingers crossed, except that the postgres database won't have the tables created in it. This is what frameworks usually call migrations but for the moment you can just cheat and get a python shell on a Heroku node and run
heroku run python
Once you get the python shell
import database database.create_tables() quit()
Then if everything has worked you should be able to access it in the web browser.
So! I have made progress thanks to @pkqk. I followed your instructions but make a couple of notes:
to work with the Postgres peewee database,
If you go to: https://afternoon-everglades-3926.herokuapp.com/ you will see the assets load.
I receive the following error message:
Heroku tells me that:
But, still, progress. And thank you so much @pkqk.
Ah script might be crashing at some point. You might have to resort to print line debugging by adding
import sys # and then add this everywhere or more informative strings sys.stderr.write("I got here before crashing\n")
If you're not already getting a backtrace then normal
So I spent the last hour or two working with someone familiar with the Heroku infrastructure. I learnt a bunch of neat tricks but unfortunately it seems that Heroku just will not support even the simplest of cgi-scripts.
This may be another really unhelpful rabbit-holing comment, but you could try Cloud Foundry. There, the filesystem is only reset when you restart or redeploy the app. So you still want an external database really, but it might be a better short-term solution than Heroku.