How to use docker for GIS development

So, do you now docker, right? No? docker is a way to “virtualize” your applications in a lightweight manner. Actually docker is a container platform. It allows you build and use containers, which ideally would host a single process each.

So, let’s say you have a complicated application, made up of lots of moving parts, like:

  1. Database
  2. Cache Storage
  3. Application
  4. Web server
  5. Async workers

Instead of installing all those things inside your machine, you can just use containers.

Containers are lightweight and ephemeral. That means they only live as long as you need, and they only virtualize the processes you need, it’s not a full blown virtual machine, that is slow, takes time to build and takes up a lot of space.

So, how do you use it? Usually, you will have a Dockerfile describing how do you want to build your container. After you have your Dockerfile ready, you can build it. That is called an image. Images allow you to spin off containers quickly, without the build step.

This container will have a base image, for example, ubuntu, where you are going to modify through your Dockerfile.

There are several keywords that you can use to customize your Dockerfile, it’s entry point (entry point is the command you want to run as soon as the container is ready), etc.

A simple Flask example

This example is available on the official docker tutorial, but let’s break it down to make things a little easier.

  1. Install docker;
  2. Create a new folder, anywhere you want. I usually use /home/<username>/projects/<myproject>;
  3. Inside this new folder, create a new file, called Dockerfile without an extension;
# Dockerfile
FROM python:3.6-alpine
WORKDIR /app
ADD . /app
RUN pip install -r requirements.txt
EXPOSE 80
ENV NAME World
CMD ["python", "app.py"]

The dockerfile above defines a few things. First and foremost it’s the base image, using the keyword FROM. You can check out tons of base images available on [docker-hub]. They are ready for use or for customization and creation of your own Dockerfiles.

Next, we have WORKDIR /app. This tells the container to consider the work directory (where your commands) are going to executed inside the container. After that, we ADD our current directory (represented by a dot) to the /app directory in the container.

From those two commands, we already instructed Docker to get own directory, and place it inside the container, so we can play with it.

After that, the RUN command tells docker to execute a command inside the container. We are just installing some requirements. The EXPOSE command, tells docker to open up port 80 inside the container for us, so we can reach it from outside. You can define your environment variables, using ENV instruction. We just defined NAME to be World.

And last, but not least, we defined an entry point. This is just a command that tells what Docker needs to run. If everything goes well, docker will execute python app.py and it will keep running it until it dies or have a problem that it cannot recover from. If the python app.py process dies, the whole container will be shutdown.

Check the application (app.py and the requirements.txt) files.

# app.py
from flask import Flask
import socket
app = Flask(__name__)

@app.route("/")
def hello():
    return 'Hello world from Docker!'

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)
# requirements.txt
Flask

Pretty easy right?

So, how do I run this?

Inside your myproject directory, assuming you installed and configured Docker correctly, you can do in a terminal (where myapplication refers to the name of the image):

docker build . -t myapplication

After the image is built and running, you’ll be able to run it using the following command:

docker run -p 4000:80 myapplication

Docker will spin a new container, start your application and map your port 4000 to the container’s port 80 (remember we EXPOSEd a port?). Open a browser and hit localhost:4000 on your machine and you should see the response from the Flask server.

You can control your container using docker CLI:

  1. docker start/stop
  2. docker pause/unpause

There are several other commands docker supports, check them out by just typing docker on your terminal.

More details can be found on the docs.

In the next article of this series, I’ll create our own (more complicated) Dockerfile, suitable for GIS Development.

Stay tuned!

George Rodrigues da Cunha Silva