I usually run my various projects in python in separate virtualenvs. This is a great way to keep things compartmentalized. However, it does have its drawbacks. For example, I wanted to work on my laptop but realized that it had a different version of python installed on it. It also didn't have other items installed that I needed. It isn't a huge issue, but it means that I need to download and compile the correct version.

I decided to take a step back and think about what I could do. I decided on writing a template for a docker container that I could use for different projects.

Typically, my workflow is something like this:

  • Install the correct version of python
  • pip install what I need and create a requirements file
  • create a shell script to activate the environment (I use the source command to run the script, so I stay in an interactive shell)

I find that workflow pretty efficient. You do have to set it up on every computer that you use or upgrade to a different O/S. I wanted something much more consistent and reproducible. This is where docker comes in. Theoretically, to move to a different computer, it should be as easy as running a docker build and then launching the container.

Without further ado, here is the Dockerfile that I created:

FROM python:latest

LABEL maintainer="Troy Williams <troy.williams@bluebill.net>"

ADD requirements.txt /tmp/requirements.txt
RUN pip install --no-cache-dir -r /tmp/requirements.txt

ENV USER=troy USER_ID=1000 USER_GID=1000

# now creating user
RUN groupadd --gid "${USER_GID}" "${USER}" && \
    useradd --uid ${USER_ID} --gid ${USER_GID} --create-home --shell /bin/bash ${USER}

# Change to the user
USER ${USER}

# create a folder to link the code to
RUN mkdir -p /home/${USER}/code

WORKDIR /home/${USER}/code

You need to build the image:

$ docker build -t twilliams/app_name .

To run the container, I use the following in a shell script:

docker run -i -t --rm \
           -v "$PWD":/home/troy/code 
           twilliams/app_name \
           bash

Place the shell script in the same folder as the code. The reference to "$PWD" is for the script to replace the variable with the current working directory so that the host system maps the code folder in the container to the correct location on the disk.

It is also possible to pass in different uid and gid values or you can hardcode them into the Dockerfile if you like.