Skip to content
jacenfox edited this page Oct 30, 2019 · 8 revisions

Docker

Docker lets you deploy high-level virtual machines called containers. Containers are lightweight and fast to start as they don't virtualize the hardware like VMs but only the OS. In other words, your container will contain its own file-system, libraries and even linux distribution.

We use them extensively on the compute nodes: no need to install anything on the machine, just use a container. In the following sections we will explain how to make your own docker image (container build instructions) and run your container.

Why is this useful

You will be able to run your experiments in its own contained environment : once your container posses all your project dependencies, you can be sure that your setup will be the same forever and you will never have dependencies issues between your projects.

Docker Image/Container

The image represents a system that you can instantiate as a container. The image can be seen as a recipe of a system and docker lets you manage images as if they were code repository :

  • You can commit changes;
  • You can pull them from public databases;
  • You can clone, backup, share it. You can see all loaded images on your system with the following command:
docker images

The container is an instance of the image : while the image describes a state of your system, the container is the actual system running. There you can maintain a file-system, change the system (e.g. install/remove libraries) and more importantly execute software. You can see all running containers with the following command:

docker ps

Setup your Image

There are three main ways to have a docker image on your system :

  • Build it from a Dockerfile;
  • Pull it from a repository;
  • Load it from a local file;

Dockerfile

If you want to setup your own system, this might be the best way as you have a full control on what packages to include in your image. The Dockerfile is a recipe of your system, it is basically a list of instruction to install the packages that you want in your system. Here is an example for pytorch, read the documentation to know more about writing Dockerfiles. Once your file is written simply build it, run this command in the folder containing the Dockerfile :

docker build -t "<image name>:<image version>" .

Pulling an image

If you want to use an image already on the public database you can use this command:

docker pull repository:tag

Loading from a file

This is mostly useful if you want to transfer your image from host to host. Saving an existing image to a file:

docker save -o /path/to/file.tar <image name>:<image version>

Then on the other system load it:

docker load -i /path/to/file.tar

Run your container

Now you have an image and you want to execute it in a container, said differently, you want to start executing process in the system described by the image. You can run a terminal with:

nvidia-docker run -it --rm image-name /bin/bash

the it option will allocate a tty for the container (so you can use the terminal without returning) and rm will clean the container after you exit. You can use docker ps -a to check for the stopped container. Please delete them if you don't use them anymore as they take up memory on the system.

Once you are in the container you have root access in anything within it! You can install packages etc. Note that any change done to the container won't affect the image. If you want to update the image you need to commit it:

docker commit container-id image-name:tag

Troubleshooting

First, check your docker version: docker --version.

  • nvidia-docker: command not found: the nvidia-docker is deprecated after Docker version 19.03. If the docker version is higher than 19.03, you can start the container with docker run -it --rm --gpus all image-name /bin/bash or docker run -it --rm --gpus --gpus '"device=1,2"' image-name /bin/bash.

Accessing data

Now you can start a terminal in a system based on your own image, but how do you access your 5To dataset from within the container? You could copy them to your container, but this is not practical. The best option is to mount a path from the host machine into your docker. For this you need the -v option with the run command:

nvidia-docker run -it --rm -v $HOME/mycode:/mnt/code image-name /bin/bash

The -v command will mount the first path in the host file system and mount it as the second path. Note that you can use multiple -v. You can specify read/write permission (e.g. :ro at the end for reading only). Example where your dataset is read only:

nvidia-docker run -it --rm -v $HOME/mycode:/mnt/code \
                           -v $HOME/mydataset:/mnt/dataset:ro \
                           -v $HOME/myresults:/mnt/results \
                           image-name /bin/bash

Note that if you create files in your mount points, it will create them as owned by root and may not be able to access them on your host machine (if you don't have root access). You can pass your user id to the container to avoid this problem:

nvidia-docker run -u "id -u $USER" -it --rm image-name /bin/bash

Attach/Detach from container

What if you are running a long process and need to get out of your terminal without stopping your process?
You can detach from your terminal with :Ctrl-p + Ctrl-q.
You can attach to it with : docker attach container-id.

Running GUI application inside docker?

You can modify and run this script to enable display forward from docker to its host.

Cheat Sheet

Cheat sheet made by Marc-André Gardner:

Docker Cheat Sheet

credit

  • Inspired by Marc-André's slides.

Clone this wiki locally