Dockerize Code - cogeorg/teaching GitHub Wiki
In order for code to run in a environment agnostic setup, it has to be containerized. There a various container solutions, e.g. Rocket and Kata Containers, but the most popular is the open-source project Docker, so we will focus on that. A container is comprised of code, runtime, system tools, system libraries and settings, including everything for the code to run on a stand-alone basis and being independent of the host system.
Consider a very easy piece of code, stored in code.py
, a function that computes the mean of an array of values:
def mean(a):
return sum(a)/len(a)
This function shall be containerized and available via an HTTP request, i.e., the container listens for incoming POST requests containing an array of values in the body and returns the result. Since the above example is Python code, we will continue with the example using a python web server. A very lightweight microframework is Flask, which allows us to create an endpoint that will return the solution of a computation given some input values. Here is the example using the mean
function:
from flask import Flask, request
from code import mean
app = Flask(__name__)
@app.route("/", methods=['POST'])
def compute():
args = eval(request.get_json().get('data'))
return str(mean(args))
if __name__ == '__main__':
app.run(host='0.0.0.0')
The above code, app.py
, could be executed by running
$ python app.py
However, it is missing its dependencies and libraries that we may not want to install globally. Hence it should be containerized, which is done be defining a Dockerfile. Note that this file has no file ending but is only called Dockerfile
.
# 1
FROM python:3.6-alpine
# 2
RUN mkdir -p /usr/src
# 3
WORKDIR /usr/src
# 4
COPY code.py .
COPY app.py .
# 5
RUN pip install Flask
# 6
EXPOSE 5000
# 7
CMD ["python", "app.py"]
- defines the docker image that serves as a baseline for this container. It contains the computing environment necessary to run python scripts.
- runs a bash command. Here, it creates a directory called
/usr/src
- sets the working directory to
/usr/src
- copies the code files into the docker container
- installs the dependencies for the code
- exposes the port to the host. If this is not set, the endpoint is only reachable from within the container but not from the host
- defines the command that is run when the container is started. Here, it is
python app.py
.
This Dockerfile is used to build an image. Containers are running instances of an image.
$ docker build -t meanimage:0.1.0 .
$ docker run -d --name meancontainer -p 5000:5000 meanimage:0.1.0
The first command builds the docker image, calling it meanimage
and tagging it with version number 0.1.0
. The second command starts the container in detached mode (-d
, optional), calling it meancontainer
(--name
, optional), exposing the port (-p
), and specifying the image and its version.
The function can now be invoked making a POST request to the endpoint:
$ http POST http://localhost:5000 data=[1,2,3,4]
returning
HTTP/1.0 200 OK
Content-Length: 3
Content-Type: text/html; charset=utf-8
Date: Sun, 27 Jan 2019 02:02:43 GMT
Server: Werkzeug/0.14.1 Python/3.6.8
2.5
All running docker containers and images are listed using
$ docker ps
$ docker images
respectively, and the running container is stopped and removed using
$ docker stop meancontainer
$ docker rm meancontainer
More docker commands can be found on this cheat sheet.