Some simple recipes for getting started with running some demo virtual applications in variety of ways.
Docker and Zeit Now – flaskdemo
This first demo creates a simple flask app and a Dockerfile with just enough to get it running; it runs locally if you have docker installed locally, and will also run on Zeit Now.
Create a new directory – flaskdemo
– and create a couple of files in it, specifically:
flaskdemo.py
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, World!' if __name__ == "__main__": app.run(host='0.0.0.0', port=5005)
Dockerfile
FROM python:3.6-slim-stretch RUN pip3 install flask EXPOSE 5005 COPY ./flaskdemo.py /var/flaskdemo.py CMD ["python3","/var/flaskdemo.py"]
Download and run the Zeit Now application, then on the command line cd
into the flaskdemo
folder and type: now
to launch the application and now ls
to lookup the URL where it’s running.
If you prefer, and have docker installed locally:
- on the command line,
cd
into the directory and then build the Docker container with the commanddocker build -t myflaskdemo .
(the dot / . is important – it says “the path to the Dockerfile is the current directory) - run the container with:
docker run -d -p 8087:5005 myflaskdemo
and you should see a hello message on port 8087.
Compare this with what I had to do to get a flask app running via the Reclaim CPanel.
Note that as well as deploying to my local docker instance, the docker-machine
command line application also allows me to launch remote servers (for example, on Digital Ocean) and then build/deploy the container there (old example). It’s not quite as easy as Zeit Now though…
Docker demo – Jupyter notebook powered API
This demo shows how to knock up an API server where the API is defined in a Jupyter notebook and published using the Jupyter Kernel Gateway (see also Building a JSON API Using Jupyter Notebooks in Under 5 Minutes). This is probably all overkill but it make for a literate definition of your API defining code…
Create a new directory – jupyterkgdemo
and copy the following Jupyter notebook into it (gist/psychemedia/jupyterkgdemo.ipynb
):
jupyterkgdemo.ipynb
Add the following Dockerfile
:
FROM python:3.5-slim-stretch RUN pip3 install jupyter_kernel_gateway EXPOSE 5055 COPY ./jupyterkgdemo.ipynb /var/jupyterkgdemo.ipynb CMD ["/usr/local/bin/jupyter","kernelgateway","--ip=0.0.0.0","--KernelGatewayApp.api='kernel_gateway.notebook_http'","--KernelGatewayApp.seed_uri='/var/jupyterkgdemo.ipynb'", "--port=5055"]
With Docker installed locally:
- on the command line,
cd
into the directory and then build the Docker container with the commanddocker build -t myjupyyterapidemo .
(the dot / . is important – it says “the path to the Dockerfile is the current directory) - run the container with:
docker run -d -p 8089:5055 myjupyyterapidemo
and you should see a message on port 8089; go tolocalhost:8089/hello/whoever
and you should get a message personalised towhoever
.
Note that this doesn’t seem to run on Zeit Now; another port seems to be detected that I think breaks things?
Vagrant Demo
Vagrant is a tool that helps automate the deployment of virtual machines using Virtualbox. In some senses, it’s overkill; in others, it means we don’t have to provide instructions about setting up various Virtualbox bits and bobs…
Install vagrant
and then add the following files to a vagrantdemo
folder:
First, the simple flask app demo code we used before:
flaskdemo.py
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, World!' if __name__ == "__main__": app.run(host='0.0.0.0', port=5005)
We can run this as a Linux service inside the VM – we means we need to provide a service definition file:
flaskservice.service
[Unit] Description=Demo Flask Server After=network.target [Service] Type=simple PIDFile=/run/flaskdemo.pid WorkingDirectory=/var/flaskdemo ExecStart=/usr/bin/python3 flaskdemo.py Restart=always RestartSec=10 [Install] WantedBy=multi-user.target
To install the packages we need, and copy the local files into the correct locations inside the VM, we can define a config shell script:
flaskserver.sh
#!/usr/bin/env bash apt-get update && apt-get install -y python3 python3-dev python3-pip && apt-get clean pip3 install flask THISDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" mkdir -p /var/flaskdemo cp $THISDIR/flaskdemo.py /var/flaskdemo/ cp $THISDIR/flaskserver.service /lib/systemd/system/flaskserver.service # Enable autostart systemctl enable flaskserver.service # Refresh service config systemctl daemon-reload systemctl restart flaskserver
Now we need a Vagrantfile to marshal the VM:
Vagrantfile
Vagrant.configure("2") do |config| config.vm.box = "bento/ubuntu-16.04" config.vm.network :forwarded_port, guest: 5005, host: 8077, auto_correct: true config.vm.synced_folder ".", "/vagrant" config.vm.provision :shell, :inline => <<-SH cd /vagrant/ source ./flaskserver.sh SH end
On the command line, cd into the folder and run vagrant up
. You should be able to see the hello world on localhost:8077
.
Note that as well as using vagrant to provision a VM using Virtualbox, other provisioners are available that would let me automatically fire up a server on a remote host (such as Digital Ocean using the Digital Ocean provisioner) and then run the same set-up script to build the machine there.
PS an example of running a crappy shiny demo (a file uploader) can be found via here. I'll add a demo to this post at some point, though not sure when… In testing, the R/shiny server image is too big to run under the Zeit Now free plan (The built image size (452.8M) exceeds the 100MiB limit).