The life-cycle of a container

The command docker ps lists all the docker containers that are currently running. Adding the -a argument lists all containers, even those that have been exited.

docker ps
docker ps -a

The docker images command lists all images present on your machine. The size of the image is given, and some images can be quite large. As you can see, you can be quickly use-up disk space by downloading many images.

docker images

Even after a container has been exited, it can be re-activated and modified at any point. If you do want this option, you can specifiy the --rm flag when running a container. In the following chunk, the first run statement should create a new entry in the output of docker ps -a, whereas the second container run with the --rm flag will not.

docker run -it ubuntu
docker ps -a
docker run --rm -it ubuntu
docker ps -a

If you find your disk filling up with docker images, there are convenient one-liners for removing all containers and images.

Don’t run this now, unless you want everything you’ve been working on to be deleted!

docker rm $(docker ps -a -q)
docker rmi $(docker images -q)

You can go back into the environment of a container that has been exited. Firstly, we make sure the container is running by using docker start:-

docker start <container_ID>

We can then use docker attach. Note that you will have to press ENTER twice in order to get a new command prompt within the container.

docker attach <container_ID>

Modifying a container and saving the changes

As an example we will take the standard Ubuntu image and modify it to include the samtools software suite.

Example: installing samtools in a plain Ubuntu image

We start by running the plain ubuntu image interactively.

docker run -it ubuntu

We’ll now assume that you know something about installing packages on Ubuntu. For those familiar with CentOS, you could use yum for the following steps. We are installing wget to allow us to download a file, and build-essential which provided c compilers and other useful tools for building and making software. The -y argument stops apt-get asking for a prompt before installing.

Note that we do not need to prefix these commands with sudo, as we are automatically running as a superuser.

####Run this inside the ubuntu container####
apt-get update
apt-get install -y wget build-essential

NOTE build-essential is quite a large package, so there could be network issues if many people try and download at the same time. In this case, we can use a pre-built container as our starting point

docker run -it markdunning/ubuntu-build-essential

We now dowload the source code for a particular version of samtools. Alternative steps would have been to clone the repository in github, or even use an apt-get command like we did for wget and build-essential. However, this would get whatever the latest version is at the point in time. Sometimes for the sake of reproducibility, we want to say exactly version of the software was used. Typically we install into the \opt directory.

####Run this inside the ubuntu container####
wget https://github.com/samtools/samtools/releases/download/1.3.1/samtools-1.3.1.tar.bz2
mv samtools-1.3.1.tar.bz2 /opt
cd /opt

We unpack the source code and attempt to install by first running ./configure

####Run this inside the ubuntu container####
tar -jxf samtools-1.3.1.tar.bz2
cd samtools-1.3.1
./configure

it turns out that we need an additional library, and after a quick google search we come across ncurses-dev

####Run this inside the ubuntu container####
apt-get install -y ncurses-dev
./configure

this time it even tells us which library was missing. This allows us to make and make install so that samtools is available from anywhere in our directory structure.

####Run this inside the ubuntu container####
apt-get install zlib1g-dev
./configure
make
make install
samtools

We can now quit the container (CTRL + D). Alternatively, CTRL P+Q keeps the container running in the background. docker attach will put us back inside the container (you’ll need docker start first if you quit container with CTRL + D)

docker start <name-of-container-that-just-exited>
docker attach <name-of-container-that-just-exited>

We can create a new image based on the changes we made, giving it an appropriate name. If you intend to submit this to dockerhub, the name should be prefixed by your github / dockerhub username.

docker commit <name-of-container-that-just-exited> docker-test/samtools

The new image is now available to be used in the usual fashion.

docker images
docker run docker-test/samtools samtools view -H example/test.bam

One option for making this image available to others is with the docker export command, which will create a .tar.gz file.

docker export docker-test/samtools

The file can be imported with docker import. However, the true docker way is to create a file (a Dockefile) from which your image can be automatically re-built. We will demonstrate this in the next section