Deploying a Python app - Part 1 (Docker)
- Create a Flask app
- Run a quick 'hello world' type test
- Setup the Dockerfile
- Deconstruct the Dockerfile
- Run the docker container locally
In this tutorial, we show how you can build and deploy a really simple Python app using Docker. To demonstrate, we'll create an API to return details of the TFL train lines in London. We'll use Flask to build the application.
from flask import Flask, jsonify, request
import sys
import logging
logging.basicConfig(level=logging.INFO)
app = Flask(__name__)
tasks = [
{
'id': 1,
'service': 'tube',
'line': 'northern',
'colour': 'black'
},
{
'id': 2,
'service': 'tube',
'line': 'circle',
'colour': 'red'
}
]
def shutdown_server():
func = request.environ.get('werkzeug.server.shutdown')
if func is None:
raise RuntimeError('Not running with the Werkzeug Server')
func()
@app.route('/trains', methods=['GET'])
def get_tasks():
return jsonify({'tasks': tasks})
@app.route('/')
def hello_world():
return 'Welcome to trains API'
@app.route('/exit')
def exit():
message = logging.info("Stopping application")
shutdown_server()
print("The Flask server has been shutdown.")
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
import requests
url = "http://192.168.1.74:5000/"
response = requests.get(url)
response_code = response.status_code
response_text = requests.get(url).text
display(response_code)
display(response_text)
Next, we want to package the application into a container using a Dockerfile. The finished Dockerfile will look as follows:
FROM python:3.7-alpine
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
EXPOSE 5000
CMD ["python", "app.py"]
Deconstruct the Dockerfile
Let's break down each line in turn to describe what is happening...
In the first line we declare a parent image which is the image our own image is based on. Each subsequent declaration in the Dockerfile modifies this image. In our example, we use a version of Alpine Linux as our base image. Alpine Linux is a lightweight Linux distribution which makes it ideal for our container.
FROM python:3.7-alpine
Next we copy all of the files from the current host directory into the container's app directory.
COPY . /app
We change our working directory to the app directory. And then we tell Docker to install the Python packages needed for the app.py
WORKDIR /app
RUN pip install -r requirements.txt
Next we tell the container to listen on a specific network port at runtime. The default is TCP but you can also specify UDP. Note that the EXPOSE instruction does not actually publish the port. This instruction is there for documentation purposes. To actually publish the port, you need to use the -p flag on the docker run command.
EXPOSE 5000
Finally, we run the app:
CMD ["python", "app.py"]
Run the docker container locally
You might want to run the Dockerfile on your own machine to verify that it is working correctly. To do that, we docker build and then docker run:
You can build the Dockerfile as follows. The -t or tag allows you to tag the image with a name.
docker build -t slemasne/trains .
Then run the image to create a container which runs our application. The '-p' flag maps port 5000 on localhost in the host to port 5000 in the docker container.
docker run -p 5000:5000 slemasne/trains
You can also run the command with a '-d' detached flag to run the container in the background:
docker run -d -p 5000:5000 slemasne/trains
The application can be accessed on our localhost:
http://localhost:5000/trains