Docker & Docker-Compose
Many of our projects use the Docker containerization technology (plus the docker-compose container creation manager) to simplify establishing a development environment. By using containers to spin up a dev environment, software team members can have a uniform development experience on any Linux distro, thus avoiding the “it works on my machine” conundrum.
Make sure you understand Linux before attempting to understand Docker, as our Docker images are all based on Linux.
The full docs for Docker and Docker-Compose are here:
This doc only provides a high level overview of what you need to maintain the stack; it does not give in depth info about Docker. We recommend you consult the docs and Google for more info.
Common Errors
You may run into permission issues running docker/docker-compose commands. You can add yourself to the docker group (usermod -a -G docker <user>) or use sudo.
Docker and Dockerfiles
In order to understand docker you need to understand a few terms/concepts:
- Images are templates that docker containers are created from.
- Containers are the actual container environment the program runs in. Think of it as a chroot on steroids.
- Dockerfiles are files that describe how to create an image.
At the core of Docker is the Dockerfile, which describes how to create the image. Here’s a sample Dockerfile from IMS:
FROM python:3.9.0-alpine3.12
COPY . /classitron
WORKDIR /classitron
# Install dependencies
RUN apk add --no-cache --virtual .build-deps \
gcc \
libc-dev \
libffi-dev \
linux-headers \
jpeg-dev \
mariadb-dev \
python3-dev \
postgresql-dev \
git \
;
RUN pip3 install -r requirements.txt
# That's literally it lmao
# Setup command
WORKDIR /classitron/classitron
CMD python3 manage.py runserver
Let’s break this down:
FROM - this is the base image your image is derived from. In this case, we’re pulling the public python image from Docker Hub. The variant (3.9.0-alpine3.12) is specified after the colon. This whole thing (image name + variant) is called the image tag.
COPY - here, we’re copying the current directory (which is the classitron project itself) on the host system to the /classitron path. This is so we can run the project inside the container.
WORKDIR - this sets the current directory, equivalent to cd. Note that since environment changes don’t persist over RUN commands you can’t just RUN cd <dir>, as it will just be reset.
RUN - this runs a command as you normally would from the shell.
Notice that instead of a common package manager like apt, Docker images usually use the Alpine Linux distro and the apk package manager.
Creation
To create a Dockerfile for a project, put a file named Dockerfile (case sensitive) in the project root. You can either build the image manually (see docs) or have docker-compose do it for you (read below).
Maintenance Notes
The IMS Dockerfile above specifies a specific Python version and Alpine version to derive from. While this allows additional stability, in that the environment will not suddenly change on you, it also means you will need to update the image every few months; find the right image tag (in the case of IMS, python:
You can also base your Dockerfile off the :latest tag. However, this means that if the maintainer of the image updates :latest, your environment may change/break.
Other than that you should be fine. See the handbook and official docs for more details.
Docker-Compose
Docker Compose is a tool to automate creating and managing an environment with multiple containers. This allows us to e.g. run a separate mysql container which the classitron container can conect to. It also massively simplifies creating and running containers by putting it all in a readable YAML format.
With your earlier basic knowledge of Docker, you should more or less be able to understand what most of this docker-compose.yml does:
version: "3"
services:
classitron:
image: "registry.gitlab.com/amadoruavs/vision/classitron:latest"
build: ./
stdin_open: true
tty: true
network_mode: host
environment:
- INTEROP_URL="http://localhost"
- INTEROP_PORT="8000"
- INTEROP_USER="testuser"
- INTEROP_PASS="testpass"
- DB_HOST="mysql"
- DB_NAME="classitron"
- DB_USER="classitron"
- DB_PASS="suasdev2020" # Development purposes
mysql:
image: "mysql:latest"
stdin_open: true
tty: true
environment:
- MYSQL_USER="classitron" # Same as above
- MYSQL_PASSWORD="suasdev2020" # Development purposes
- MYSQL_ROOT_PASSWORD="suasdev2020" # Development purposes
Again, we can break this down:
version: "3" specifies the docker-compose YML format version. This should always be 3 unless you have a specific need to use an older version.
services specifies the containers used in the docker-compose application. In this case, we list 2 containers used below - classitron and mysql.
classitron: and mysql: are the container names. These can be basically arbitrary, but must follow regular network hostname rules. In each container, you can reference the other using the container name as the hostname (e.g. classitron connects on mysql://mysql:3306).
image is the image used. Notice that one pulls from Docker Hub (simple