Once you’ve installed Docker, there a few basic features to know. In this post you’ll learn about running containers. If you haven’t gotten started with Docker yet, checkout this quick start guide.
You can run Docker containers with a command that takes the following form:
docker run [options] <image name> [command]
The only required element is the image name. So for example, to run Jupyter’s
minimal-notebook image in a container, use the image name
docker run jupyter/minimal-notebook
This runs the default command in the image and streams logs to stdout (you can quit by pressing
ctrl+c), which can sometimes be useful. But in this case, the default command is starting a Jupyter notebook server, which is not useful if we don’t have access to port 8888 on the container.
Fortunately, we can expose this port using the
-p flag (p is for “publish”).
docker run -p 8888:8888 jupyter/minimal-notebook
Now we’ve done something useful. The notebook command prints out a URL in the logs with a token parameter. If you visit that link, you will be in a Jupyter notebook hosted on the container.
If we were already using port 8888 on our local machine or in another container, we could pick a different port to map to 8888 on the container.
docker run -p 8889:8888 jupyter/minimal-notebook
Now we will need to modify the URL printed to stdout, by substituting 8889 for 8888. This means you’ll need to navigate to a URL like
http://localhost:8889?token=<some token> even though the container will print
Overriding the default command
It’s a pain to have to get the URL from the logs before we can use it. The
minimal-notebook container is running an executable script called
start-notebook.sh (see the script here). This will take arguments and pass them to the
jupyter notebook command. This gives us the opportunity to disable token-based authentication.
docker run -p 8888:8888 jupyter/minimal-notebook start-notebook.sh --NotebookApp.token=''
Now we can visit the notebook server by simply navigating to
localhost:8888. But we still have a problem. Any work we do in a notebook will not be saved after we exit the container. This is probably not what you want.
The best way to save code you write in a container is to mount a data volume from your host machine. For this, you use the
-v flag (v is for “volume”). The working directory in the container is
/home/jovyan/work, which is where the notebook will be launched. A good bet is to give the host access to this directory. I like keeping code in my
~/code directory so I’ll create a folder called
~/code/minimal-notebook-scratch. Feel free to make a folder wherever you want and substitute it in your run command.
docker run -v ~/code/minimal-notebook-scratch:/home/jovyan/work -p 8888:8888 jupyter/minimal-notebook start-notebook.sh --NotebookApp.token=''
Now if you start a notebook and write some code, the notebook will live on in
~/code/minimal-notebook-scratch when you quit the container. In fact, anything you change in the
/home/jovyan/work directory within the container will also change in the
~/code/minimal-notebook-scratch folder on your machine. Pretty handy.
Running the container in different modes
There’s one more irritating thing about this setup to take care of. The container will die if we close the Terminal tab, or if we accidentally hit
ctrl+c. When you’re running something like a server in a container, it’s usually nice to run it in detached mode. This is done with the
-d flag (d is for “detach”).
docker run -d -v ~/code/minimal-notebook-scratch:/home/jovyan/work -p 8888:8888 jupyter/minimal-notebook start-notebook.sh --NotebookApp.token=''
This time, you will see a container ID on the screen but no logs from the container. That’s because the container is running in the background. You can watch the logs of a detached container with
docker logs -f <container ID> and you can kill and delete a container with
docker rm -f <container ID>. If you forget the container ID, just run
docker ps to see the IDs of all the running containers.
If you’re debugging an image, you can run the container in interactive mode using the
-t flags together:
-it (i is for “interactive”, but I’m not really sure about the t).
docker run -it -v ~/code/minimal-notebook-scratch:/home/jovyan/work -p 8888:8888 jupyter/minimal-notebook start-notebook.sh --NotebookApp.token=''
You now know enough about
docker run to be dangerous. Go forth and containerize all the things.