Trying Stuff in Docker

The Docker project is revolutionizing the way many teams deliver software, by making it possible to package up virtual machines into lightweight, portable containers. But even if your project isn’t using Docker for delivery, there are ways Docker can make your life easier as an individual developer.

In today’s episode, guest chef Jessica Kerr joins us. She’s going to show you how you can get immediate benefit from Docker by using it to quickly try out new programming languages and tools. You’ll learn some basic Docker usage, and a little about how to keep your Docker environment tidy. Enjoy!

Prefer reading to watching? You can read the script below…


## You want to try out a programming language

Let’s say we want to try out a new programming language.

Like… Elixir!

We’ll go to the Elixir site and see what it says about getting started…

Ugh! What computer am I running… I don’t want to think about this!

## But you don’t want to modify your developer environment

And I don’t want to change my computer just to try out a programming language! I have too many old versions of programming languages already!

## The language ecosystem provides a docker container

Is there a less invasive way to try this out? Can I have Elixir over for dinner without putting it up in my guest room?!

I just want to run a computer with the thing already installed! Fortunately, there’s a way to run computers in my computer! They stay within their boundaries, and they go away when I’m done with them.

It’s called… Docker. Docker is like a manager of pretend miniature computers. Each pretend mini computer is called a “container”.

Oh look! The Elixir site lists a demo Docker image. That’s just what I want. Because a Docker image is a definition of a starting point for a container.

The thing I like about clicking on this is that it doesn’t matter what computer I’m running. I can use this on my Mac. I can use this on Windows. I can use this on Linux within Windows if I want to!

Assuming I have Docker installed. Which is not trivial, but from here we assume Docker is installed and running.

This is what that looks like on Windows.

## Start by checking what containers are currently running

First, I’m going to see that I have no containers running right now.

I can do that at the command line with `docker ps`.

These are some column headings… there are no rows. No containers are running. But! I can tell that Docker is running. Otherwise this command wouldn’t work.

## I want to run their container.

Back on the Elixir site… We find the name of the container image in the documentation. Looks like it’s called simply, “elixir”.

I don’t like typing command-line options that I don’t know yet.

But I know I want docker to run a container using the “elixir” image.

“`
> docker run elixir
Unable to find image ‘elixir:latest’ locally
latest: Pulling from library/elixir
“`

## Their container is on DockerHub

Oh look! It’s pulling from “library/elixir”. That means it’s somewhere docker knows about… usually hub.docker.com. In fact, while this is downloading…

…let’s check that out. This is DockerHub.

Let’s search for Elixir.

Oh yeah, there it is.

Docker Official images, indeed!

A lot of versions are available, latest is the default.

Back to our console, see that docker says it’s looking for an image named `elixir` at the tag `latest`. The stuff *after* the colon is the name of the tag.

## The container runs and exits

Oh look! It finished. Oh look! It ran the image. It gave us an interactive Elixir prompt! And then it exited! What?

“`
> docker run elixir
Unable to find image ‘elixir:latest’ locally
latest: Pulling from library/elixir
844c33c7e6ea: Pull complete
ada5d61ae65d: Pull complete
f8427fdf4292: Pull complete
f025bafc4ab8: Pull complete
7a9577c07934: Pull complete
73d44522986b: Pull complete
67e5d74f0783: Pull complete
db286e90fbac: Pull complete
50d6ee204e45: Pull complete
Digest: sha256:56e8f963b496caa7b72cd9d7dc24ba30876a3074df9418e09fee3608552462e1
Status: Downloaded newer image for elixir:latest
Interactive Elixir (1.9.4) – press Ctrl+C to exit (type h() ENTER for help)
iex(1)>
>
“`

Why did it exit?

## -it means “interactive terminal”

This is why they told us to type `docker run -it`. I think of that as standing for “interactive terminal”.

This is actually two flags, `-i` for interactive and `-t` for TTY. That’s why there’s only one dash in `-it`.

“`
> docker run -i -t
“`

But we can pass them together as `-it`.

And I have no idea why you would ever use them separately.

Then we supply the image name.

This time it doesn’t have to re-download the image. It already has it. And, thanks to `-it`, it doesn’t exit!

“`
> docker run -it elixir
Erlang/OTP 22 [erts-10.6] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [hipe]

Interactive Elixir (1.9.4) – press Ctrl+C to exit (type h() ENTER for help)
iex(1)>
“`

## Play around inside the demo container!

Now we can play with the Elixir REPL!

What is Elixir for hello world? It is `IO.puts`.

“`
iex(1)> IO.puts(“Hello jessitron!”)
Hello, jessitron!
:ok
“`

## List the running containers

This interactive Elixir prompt is running inside a pretend mini-computer, inside a container, inside Docker, on my laptop.

In another terminal, let’s list the running containers again.

“`
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bce749acd511 elixir “iex” 5 minutes ago Up 5 minutes romantic_nash
“`

Aha! We have a container.

It has an ID.

It comes from the `elixir` image.

It’s running the `iex` command.

It’s been up for a few minutes.

And it has a silly name.

Docker makes up names for our containers if we don’t specify one.

## Shut down the demo container

OK, let’s say we’ve played around with IEX enough, and we’re done.

So we exit IEX with double control-C. (That’s an IEX thing, not a Docker thing.)

Now we’re out of the container, and back at our computer’s prompt.

Let’s check to see whether the container is still running.

“`
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
C:\Users\jessi >
“`

Docker ps says no… except … here’s something to know about docker ps. By default, it shows running containers. But these are not all the containers.

## Note that the image is still around

If we run with -a, it says, show me all the containers, including the stopped ones.

“`
> docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bce749acd511 elixir “iex” 12 minutes ago Exited (0) 3 minutes ago romantic_nash
5c46173929a5 elixir “iex” 41 minutes ago Exited (0) 41 minutes ago modest_mahavira
“`

Here are two containers that have exited! There’s the one we just exited, and also the one that we ran without -it so it exited itself.

## Clean up by removing the image

We don’t need these stopped containers lying around taking up space on the filesystem. To get rid of them,

we use `docker rm`

with either the container ID

or its catchy name.

“`
> docker rm 5c46173929a5
> docker rm romantic_nash
“`

Now when we run `docker ps -a`, the list of containers is really empty.

“`
> docker ps -a

“`

## Starting with –rm cleans up automatically

It would be nice if Docker would clean up after itself, and we didn’t have to do this. It can, but we have to pass it the do-things-right flag.

This is why the instructions said to run with `–rm`,

because that tells Docker to delete the container after it stops.

Note that `–rm` has two dashes, because it is one command-line option. `rm` is its long name, sadly.

“`
docker run -it –rm elixir
“`

Now when I run a container from the Elixir image, and then exit

There is no container lying around afterwards.

“`
docker ps -a
“`

## Conclusion

Now the next time you want to try a programming language, or tool, or whatever, you know how to run a container from a provided Docker image. You know how to see what Docker containers are running, shut them down, and clean up after yourself.