Docker 0101 – How do I use Docker?

ℹ️ This is part of a series of internal Docker workshops for the Financial Times.

In this section, we are going to cover

Installing the Docker toolchain

You can download the Docker command line tools from the Docker Store, make sure to pick the right package for your operating system.

What is an image, what is a container?

An image is a thing you can run.

That thing could be a command line tool, a web server, or any other sort of task you might want to run on a computer.

A container, that’s just a running image.

Pulling images from the public Docker Registry

Images are often stored on a registry, this allows you to share an image between different computers.

For example, you could publish an image in your continuous integration pipeline, and then download and run that image on your web server.

Let’s download the hello-world image.

docker pull hello-world

We can then list all the images we have downloaded locally with…

docker images

You can have a look at what’s in the image on it’s Docker Hub page.

Running a basic hello-world image

OK, now we’ve downloaded the hello-world image lets run it!

docker run hello-world

Running an image that talks HTTP

Kinda cool, but it just exits. How about we start a longer running process?

Lets run the official nginx image. Nginx is a popular web server, similar to Apache httpd or lighttpd.

docker run nginx

Notice how you don’t actually need to run docker pull first? Docker will automatically pull an image from a registry if you haven’t already downloaded it.

If we have a look at what port the container uses we can see it expects requests on the standard HTTP port 80.

So in a new terminal lets try running curl localhost

Connection refused? Yeah, let’s debug that!

In the same terminal lets see what containers we have running.

docker ps

There should be a row that shows there’s a container running the nginx image.

There’ll also be a column for ports that lists 80/tcp.

What we actually need to see is something like 0.0.0.0:8080->80/tcp. This means that we’re actually doing some port forwarding, from our local machine on port 8080 to the container at port 80.

Ctrl + C in the terminal running the nginx container to kill it.

So how do we forward the port? Lets use the --help flag to figure it out!

docker run --help | grep port

Any guesses?

docker run -p 8080:80 nginx

Now we should be able to visit http://localhost:8080 in a browser and see the default nginx page.

So that’s all good, we’ve got nginx running locally. Notice that we didn’t need to worry about installing or configuring nginx or any of it’s dependencies? That’s all defined in the nginx image.

It’s just as easy for us to run Apache, let’s give that a spin too!

docker run -p 8080:80 httpd

If we refresh our page we should now see the default welcome for Apache httpd. Cool right? No software to install, just docker!

Building your own image with a Dockerfile

Let’s change the default page of that image!

Start by creating an empty file called Dockerfile.

Then lets start by just using the existing nginx image. We don’t need to reinvent the wheel. This is a really powerful feature of Docker.

FROM nginx

After that let’s add an Origami based page to a file called index.html in the same directory as the Dockerfile.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Docker 101</title>

    <link rel="stylesheet" href="https://build.origami.ft.com/v2/bundles/css?brand=internal&modules=o-grid@^4.3.8,o-header-services@^2.2.2,o-footer-services@^1.0.1" />

    <script src="https://build.origami.ft.com/v2/bundles/js?brand=internal&modules=o-grid@^4.3.8,o-header-services@^2.2.2,o-footer-services@^1.0.1"></script>

    <style>
        body {
            margin: 0;
        }
    </style>
  </head>
  <body>
    <header class="o-header-services" data-o-component="o-header">
        <div class="o-header-services__top o-header-services__container">
            <div class="o-header-services__ftlogo"></div>
            <div class="o-header-services__title">
                <h1 class="o-header-services__product-name"><a href="/">Docker 101</a></h1>
            </div>
        </div>
    </header>

    <!-- Constant column spans -->
    <div class="o-grid-container">
        <div class="o-grid-row">
            <div data-o-grid-colspan="one-third center">
                <h2>Docker is the Best</h2>

                <p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Docker_%28container_engine%29_logo.svg/800px-Docker_%28container_engine%29_logo.svg.png"></p>
            </div>
        </div>
    </div>

    <footer class="o-footer-services">
        <div class="o-footer-services__container">
            <p class="o-footer-services__copyright">&#xA9; THE FINANCIAL TIMES LTD. FT and &apos;Financial Times&apos; are trademarks of The Financial Times Ltd.</p>
        </div>
    </footer>
  </body>
</html>

To Dockerfile we can then append the following…

COPY index.html /usr/share/nginx/html/index.html

So that our final Dockerfile looks like…

FROM nginx
COPY index.html /usr/share/nginx/html/index.html

Now we need to build the image, tagging it with a sensible name…

docker build --tag docker-101 .

Then we can run the image as a container…

docker run -p 8080:80 docker-101

Refreshing our browser tab pointing at http://localhost:8080 should now show the new page 🚀.

Further Reading

There’s an awesome list on all things docker at https://github.com/veggiemonk/awesome-docker#what-is-docker.

You can also find a more comprehensive workshop at https://docker-curriculum.com.

One Last Thing

How about we run a more interesting task using Docker.

There once was a telnet server, which played Start Wars Episode IV in ASCII.

Now there’s a docker image, that does the very same!

docker run -p 8023:23 rohan/ascii-telnet-server

In another terminal we can now connect to 8023 with telnet.

telnet localhost 8023

➡️ Find the next post in this series at Docker 110 – Dockerfiles & Volumes 🐳.