A Docker-Centric Approach to Software Development 🐳
In my experience developing software within a team, standardization of environment dependencies has always been a constant pain. There had been countless instances where trying to get more hands onboard resulted in more intense bouts of stress, rather than actually resolving the issue at hand.
This often comes in the form of teammates being unable to set up a project’s complex network of software dependencies which would likely conflict with their own workstation’s existing dependencies. While it is easier to manage such conflicts within python environments, the same cannot be said for C++ libraries as well as lower-level hardware-centric backends like Nvidia’s CUDA. Usually, the workarounds would be a quick dirty hack to switch different versions around while the simpler option would be to completely remove and install the required versions tediously.
Therefore, this article hopes to address this issue of environment standardization through an intuitive use of Docker.
Setup
-
If you do not have Docker installed, please follow the offical installation guide.
-
Configure
docker
such that you need not always have to run it withsudo
. Do note this carries security risk but at least offers ease of use within the context of largely-offline development.
ℹ️ To avoid such security risk, please consider setting up Docker rootless.
Run
- Downloading public docker images
docker pull <image_name:tag_name>
- Building local docker images using
Dockerfile
docker build -t <image_name:tag_name> .
Replace <image_name:tag_name>
with something like cardboardcode/opencv:1
- Run docker images as containers:
#!/usr/bin/env bash
xhost +local:docker
XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
docker run -m 8GB -it --rm -e DISPLAY=$DISPLAY -v $XSOCK:$XSOCK -v $XAUTH:$XAUTH -e XAUTHORITY=$XAUTH -v ${PWD}:/src -it <image_name:tag_name>
xhost -local:docker
Save & Share
This section covers an offline methodology of sharing varying docker images in order to achieve the quick environmental standardization among different developers:
- Save a docker image as
.tar
file:
docker save -o <file_name>.tar <docker_image_name>
#Eg. docker save -o mynginx1.tar nginx
- Load a
.tar
file as docker image on different workstations:
docker load < <file_name>.tar
#Eg. docker load < mynginx1.tar
Clean-Up 🧹
This section covers how to remove Docker containers/images. Create the following .bash
file and run them.
1a. 🐧 [ Linux ] - remove_all_docker_containers.bash
#!/bin/bash
# Run the command to get container IDs in a single line
container_ids=$(docker ps -a -q)
# Check if the variable is empty
if [[ -z "$container_ids" ]]; then
echo "No containers found."
else
echo "Containers found:"
# Print each container ID on a new line
echo "$container_ids"
# Prompt user for confirmation
read -p "Do you want to stop and remove these containers? (y/N): " answer
# Convert user input to lowercase
answer=${answer,,}
# Check if user confirms
if [[ "$answer" == "y" || "$answer" == "yes" ]]; then
# Use loop to stop and remove containers safely
for container_id in $containers; do
docker stop "$container_id" && docker rm -f "$container_id"
echo "Removed container: $container_id"
done
else
echo "Containers not stopped or removed."
fi
fi
1b. 🪟 [ Windows - Powershell ]
docker ps -aq | Where-Object { $_ -ne "" } | ForEach-Object { docker rm $_ }
1c. 🐧 [ Linux ]
docker rm $(docker ps -aq)
2a. 🐧 [ Linux ] - remove_all_docker_images.bash
#!/bin/bash
# Run the command to get image IDs in a single line
image_ids=$(docker images -a -q)
# Check if the variable is empty
if [[ -z "$image_ids" ]]; then
echo "No images found."
else
echo "Images found:"
# Print each image ID on a new line
echo "$image_ids"
# Prompt user for confirmation
read -p "Do you want to remove all these images? (y/N): " answer
# Convert user input to lowercase for case-insensitive comparison
answer=${answer,,}
# Check if user confirms (y or yes)
if [[ "$answer" == "y" || "$answer" == "yes" ]]; then
# Use loop to remove images safely
for image_id in $image_ids; do
docker rmi -f "$image_id"
echo "Removed image: $image_id"
done
else
echo "Images not removed."
fi
fi
2b. 🪟 [ Windows - Powershell ]
docker rmi -f $(docker images -aq)
2c. 🐧 [ Linux ]
docker rmi $(docker images -q)
Limitations 👎
-
MEMORY - Docker images could easily exceed
10GB
in memory space use. -
GRAPHIC USER INTERFACE - Instantiating Graphical User Interfaces through docker instances can be problematic and impossible in many cases. While users could circumvent this, most approaches introduces security risks which one should be mindful of.
-
SECURITY - Please consider reading up on security risks posed in the following recent hacks:
ℹ️ Coinhive has shut down as of 2019. [Ref]
ℹ️ Docker versions 18.09.2, 17.03.1-ce, and 17.06.2-ce and later addressed the issue.
- HARDWARE - Hardware-specific programs that rely on devices such as GPU cannot be instantiated or virtualized effectively through Docker.