Share Your Docker Image

Note

Prerequisites: You should have access to a terminal with Docker installed, a Docker Hub account, and a GitHub account. You should also have a copy of pi.py

Now that you have containerized, tested, and tagged your code in a Docker image, the next step is to disseminate it so others can use it.

Commit to GitHub

In the spirit of promoting Reproducible Science, it is now a good idea to create a new GitHub repository for this project and commit our files. The steps are:

  1. Log in to GitHub and create a new repository called pi-estimator

  2. Do not add a README or license file at this time

  3. Then in your working folder, issue the following:

$ pwd
/Users/username/python-container/
$ ls
Dockerfile     pi.py
$ git init
$ git add *
$ git commit -m "first commit"
$ git remote add origin git@github.com:username/pi-estimator.git
$ git branch -M main
$ git push -u origin main

Note

This assumes you have previously added an SSH key to your GitHub account for the machine you are working on.

Make sure to use the GitHub URI which matches your username and repo name. Let’s also tag the repo as ‘0.1’ to match our Docker image tag:

$ git tag -a 0.1 -m "first release"
$ git push origin 0.1

Finally, navigate back to your GitHub repo in a web browser and make sure your files were uploaded and the tag exists.

Push to Docker Hub

Docker Hub is the de facto place to share an image you built. Remember, the image must be name-spaced with either your Docker Hub username or a Docker Hub organization where you have write privileges in order to push it:

$ docker login
...
$ docker push username/pi-estimator:0.1

You and others will now be able to pull a copy of your container with:

$ docker pull username/pi-estimator:0.1

DockerHub also has integrations to automatically update your image in the public container registry every time you commit new code, but they are no longer available unless you have a paid account.

For example, see: Set up automated builds

Hands-On Exercise

Scenario: You have the great idea to update your python code to use argparse to better handle the command line arguments. Outside of the container, modify pi.py to look like:

 1#!/usr/bin/env python3
 2from random import random as r
 3from math import pow as p
 4from sys import argv
 5
 6# Use argparse to take command line options and generate help text
 7import argparse
 8parser = argparse.ArgumentParser()
 9parser.add_argument("number", help="number of random points (int)", type=int)
10args = parser.parse_args()
11
12# Grab number of attempts from command line
13attempts = args.number
14inside = 0
15tries = 0
16
17# Try the specified number of random points
18while (tries < attempts):
19    tries += 1
20    if (p(r(),2) + p(r(),2) < 1):
21        inside += 1
22
23# Compute and print a final ratio
24print( f'Final pi estimate from {attempts} attempts = {4*(inside/tries)}' )

(New and modified lines are highlighted). With this change, the user can execute ‘pi.py -h’ to get usage information. You can also download this code from here:

https://raw.githubusercontent.com/TACC/containers_at_tacc/master/docs/scripts/pi-updated.py

Next, update the Dockerfile to include a new kind of instruction at the very end of the file - CMD:

 1FROM ubuntu:18.04
 2
 3RUN apt-get update && apt-get upgrade -y && apt-get install -y python3
 4
 5COPY pi.py /code/pi.py
 6
 7RUN chmod +x /code/pi.py
 8
 9ENV PATH "/code:$PATH"
10
11CMD ["pi.py", "-h"]

This command will be executed in the container if the user calls the container without any arguments.

Finally, rebuild the container and update the version tag to ‘0.2’. Test that the code in the new container has been updated, and that it is working as expected.

Commit to GitHub (Again)

Finally, push your modified code to GitHub and tag the release as 0.2:

$ git add *
$ git commit -m "using argparse to parse args"
$ git push
$ git tag -a 0.2 -m "release version 0.2"
$ git push origin 0.2

By default, the git push command does not transfer tags, so we are explicitly telling git to push the tag we created (0.2) to the remote (origin).

Now, check the online GitHub repo to make sure your change / tag is there.

Other Considerations

The best way to learn to build docker images is to practice building lots of images for tools you use. The online Docker documentation contains a lot of good advice on building images.

Some miscellaneous tips for building images include:

  • Save your Dockerfiles – GitHub is a good place for this

  • You probably don’t want to use ENTRYPOINT - turns an container into a black box

  • If you use CMD, make it print the help text for the containerized code

  • Usually better to use COPY instead of ADD

  • Order of operations in the Dockerfile is important; combine steps where possible

  • Remove temporary and unnecessary files to keep images small

  • Avoid using ‘latest’ tag; use explicit tag callouts

  • The command ‘docker system prune’ will help free up space in your local environment

  • Use ‘docker-compose’ for multi-container pipelines and microservices

  • A good rule of thumb is one tool or process per container