How to get started with Docker

Running a Docker image

Docker is way to run a specific application without having to install it, or compile it and deal with all the dependencies. In Ubuntu, it was very easy to install the docker software from the command line. On Mac, you can look at that post. Once this is done, you need to identify the image you want to run. A Docker image is a container a certain set of applications. To run that image, you can type in the command line docker run <image> If you have never run that image before, the first time you execute that command, docker will download the image and all other stuff it needs. If you want to download the image without running it, you can instead do docker pull <image>.

A few options make the whole Docker experience a lot more useful. In particular, you typically want that image to be opened in an interactive shell. For that, you need the options -it. Another useful feature is to be able to access some folders of your local hard drive from within the image; this can be done with the option -v LOCAL_FOLDER:DOCKER_FOLDER.

For example, when running the Fenics Docker image, I would do

docker run -t -i -v /home/ben/Work/fenicstools:/home/fenics/fenicstools -v /home/ben/Work/hippylib:/home/fenics/hippylib fenics20171

to have access to my local fenicstools and hippylib folders. In another example, to run a tensorflow Docker image, I did

docker run -t -i -v
/home/ben/Work/Programmation/Python/mlds/tensorflow/:/home/tf/
tensorflow/tensorflow bash

The bash was required here as by default the tensorflow image starts a notebook. Actually you start in the /notebook folder, and need to navigate to the folder you defined cd ../home/tf. But once you figure this out, everything works great.

Running a jupyter notebook using a Docker image

I found the solution in this StackOverflow post. First you need to publish a port of the container to the host (your laptop),

docker run <...> -p 8888:8888 <your_image> bash

Inside your Docker image, you can start the jupyter notebook,

jupyter-notebook --ip 0.0.0.0 --no-browser --allow-root

Now on your local machine, from your browser, navigate to localhost:8888/tree. You will be prompted with a menu asking for a token. After starting the jupyter notebook, you’ll get a http adress which contains the sequence :8888/?token=<...>. Your token is made of all the alphanumeric characters following the equal sign.

Creating a Docker image

You can save all the characteristics of the image you want to create in a Dockerfile, then build the corresponding image by doing, if you’re in the same directory as the Dockerfile,

docker build -t <name>:<tag> .

For instance docker build -t local/ben:latest .. You can also specify the modules you want installed in a Pipfile that you load as part of your Docker file, then install with pipenv. In that case, you need to first generate the lock file, then install all the modules. For instance,

# Python dependencies
RUN pip install pipenv==2018.11.26
ADD ./Pipfile ./
RUN pipenv lock
RUN pipenv install --system

Another way to build the image which may be more flexible is to use a docker-compose.yml file (see here) and execute it through

docker-compose up <name_specified_in_yml>

The up, by default will start the container after building and creating it. To prevent this from happening, you can pass the option --no-start. Note: I had a lot of trouble with docker-compose.

Dockerfile and absolute path

Sometimes you want to create a docker image with files that are in a different directory. However, you can’t do that with docker. When you define an absolute path inside your Dockerfile, this refers to the absolute path in the build context. A work-around is to create your docker image from a place where you can access (in relative path) all the files you need. And if you want your Dockerfile to be somewhere else, you can use the -f option,

docker build -f /home/Dockerfile -t mytag .

Pruning Docker

Docker have a very conservative approach to garbage collection, it seems, and keep everything unless you asked it to delete it. The problem is that if you’re not careful, you can end up filling up all your available memory, and you can’t build/pull any images. The solution is to either (1) increase the amount of memory Docker can use, or (2) prune all the images/containers/… that you don’t need anymore. To prune everything at one, just do

docker system prune --volumes
[ docker  linux  notebook  ]