What we’re going to do
In this tutorial we’re going to illustrate what I consider to be Docker’s central and most magical ability: to let you run software on your computer that you don’t actually have installed on your computer.
The specific software we’re going to run is the Lisp REPL (read-evaluate-print loop). The reason I chose Lisp is because you’re unlikely to happen to have Lisp already installed. If I had chosen to use a language that you might already have installed on your computer, like Ruby or Python, the illustration would lose much of its sizzle.
Here are the steps we’re going to carry out. Don’t worry if you don’t understand each step right now because we’re going to be looking at each step in detail as we go.
1. Add a
2. Build an image from our
3. Run our image, which will create a container
4. Shell into that container
5. Start a Lisp REPL inside the container
6. Run a Lisp “hello world” inside the REPL
7. Exit the container
8. Delete the image
Before you follow this tutorial you’ll of course have to have Docker installed. You might also like to get familiar with basic Docker concepts and terminology.
Adding a Dockerfile
Dockerfileis a specification for building a Docker image. We’re going to write a
Dockerfile, use the
Dockerfileto build a custom image, create a container using the image, and finally shell into the container and start the Lisp REPL.
First I’m going to show you the
Dockerfileand then I’ll explain each individual part of it.
# Dockerfile FROM ubuntu:20.04 RUN apt update && apt install -y sbcl WORKDIR /usr/src
FROMdirective tells Docker what image we want to use as our base image. A base image, as the name implies, is the image that we want to use as a starting point for our custom image. In this case our base image is just providing us with an operating system to work with.
FROMdirective takes the form of
<image>:<tag>. In this case our image is
ubuntuand our tag is
20.04. When Docker sees
ubuntu:20.04, it will look on Docker Hub for an image called
ubuntuthat’s tagged with
RUN apt update && apt install -y sbcl
RUNcommand in a
Dockerfilesimply takes whatever it’s given and runs it on the command line.
In this case the command we’re running is
apt update && apt install -y sbcl. The
&&in between the two commands means “execute the first command, then execute the second command if and only if the first command was successful”. Let’s deal with each of these commands individually.
apt updatecommand is a command that downloads package information. If we were to skip the
apt updatecommand, we would get an error that says
Unable to locate package sbclwhen we try to install
sbcl. So in other words, running
apt updatemakes our package manager aware of what packages are available to be installed.
apt install -y sbclcommand installs a package called
sbcl. SBCL stands for Steel Bank Common Lisp which is a Common Lisp compiler. (Common Lisp itself is a popular dialect of the Lisp language.)
apt install -y sbclmeans “don’t give me a yes/no prompt”. If we were to leave off the
-ywe’d get an “are you sure?” prompt which would be no good because the
Dockerfileisn’t executed in an interactive way that would actually allow us to respond to the prompt.
WORKDIR /usr/srcdirective specifies which directory to use as the working directory inside the container. Imagine being logged into a Linux machine and running
cd /usr/src. After running that command, you’re “in”
/usr/srcis your working directory. Similar idea here.
Listing our existing images
Before we use our
Dockerfileto build our image, let’s list our existing Docker images. If this is your first time doing anything with Docker then the list of existing images will of course be empty.
In any case, let’s run the
docker image lscommand:
$ docker image ls
Listing our existing containers
In addition to the
docker image lscommand which lets us list any images we have, there’s an analogous command that lets us list our containers.
$ docker container ls
Building our image
We can use the
docker buildcommand to build our image. The
--tag lisppart says “give the resulting image a tag of
.part says “when you look for the
Dockerfileto build the image with, look in the current directory”.
$ docker build --tag lisp .
After you run this command you’ll see some entertaining output fly across the screen while Docker is building your image for you.
Confirming that our image was created
Assuming that the build was successful, we can now use the
docker image lscommand once again to list all of our existing images, which should now include the image we just built.
$ docker image ls
You should see something like the following:
REPOSITORY TAG IMAGE ID CREATED SIZE lisp latest 91f4fa2a754a 11 minutes ago 140MB
Creating and shelling into a container
Run the following command, which will place you on the command line inside a container based on your image. You should of course replace
<image id>with the image id that you see when you run
docker image ls.
$ docker run --interactive --tty <image id> /bin/bash
docker runcommand is what creates a container from the image. The
/bin/bashargument says “the thing you should run on this container is the
Viewing our new container
Now that we’ve invoked the
docker runcommand, we have a new container. Open a separate terminal window/tab and run
docker container ls.
$ docker container ls
You should see a new container there with an image ID that matches the ID of the image you saw when you ran
docker image ls.
CONTAINER ID IMAGE COMMAND CREATED STATUS 5cee4af0cfa9 91f4fa2a754a "/bin/bash" 4 seconds ago Up 3 seconds
Poking around in our container
Just for fun, run a few commands in the container and see what’s what.
$ pwd # show the current directory $ ls -la # show the contents of the current directory $ whoami # show the current user
Running the Lisp REPL
Finally, let’s run the Lisp REPL by running the
sbclcommand inside our container.
Once you’re inside the REPL, run this piece of “hello, world!” Lisp code.
(format t "hello, world!")
Exiting the container
Press CTRL+D to exit the Lisp REPL and then CTRL+D again to exit the container. The container will delete itself once exited.
Deleting the image
Run the following command to delete the image.
rmipart stands for “remove image” and the
-fflag stands for “force”.
$ docker rmi -f <image id>
You’ve completed this exercise. You’re now capable of the following things:
- Writing a
Dockerfilethat specifies an operating system to use and some software to install
- Listing Docker images and containers
- Building Docker images
- Shelling into a container
- Using the software that was installed on the container
If you possess these capabilities and have at least a little bit of a grasp of the underlying concepts, then you’re well on your way to being able to use Docker to accomplish real work.