Skip to content

Latest commit

 

History

History
225 lines (179 loc) · 8.32 KB

README.md

File metadata and controls

225 lines (179 loc) · 8.32 KB

Lesson 1- Use Our First Containers

What are containers

Docker isn't the only container technology out there, but it is certainly the most popular. And while we often think of containers as "mini-VMs," they aren't. They run as programs on the host without the walls and separation that VMs give us. If a program is running as root on a Docker container, it is running as root on the host. They share the OS with the host which makes them smaller and faster to start up than their larger VM cousins.

An image is a software bundle that will run on a Docker host. A container is an instance of that image, running or stopped. Images are the cookie cutters; containers are the cookies.

An image is made up of multiple layers of software (each an image itself) along with the metadata about how it should be assembled. Containers are read-only copies of those images with a thin read-write layer on top for the ephemeral instance data. We'll see more about this later.

Ubuntu layers

Because of this, containers can be used as immutable infrastructure. The images can be cloned and spun up and restarted and destroyed as needed, knowing that a new copy can be instantiated as needed. Don't get too attached to any particular instance. They are cattle, not pets.

The Hello World Container

Instantiate your first Docker container with the docker run command.

$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:e7c70bb24b462baa86c102610182e3efcb12a04854e8c582838d92970a09f323
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

docker run does a lot behind the scenes:

  • looks in the image cache for the image
  • downloads the image from Docker Hub (if needed)
  • starts a container with the image
  • allocates a filesystem
  • adds the read-write layer
  • sets up the network interface
  • gets an IP address
  • executes the process
  • captures the output
  • exits the container

Interact with a Container

Run another container interactively.

$ docker run -it ubuntu /bin/bash
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
6a5697faee43: Pull complete
ba13d3bc422b: Pull complete
a254829d9e55: Pull complete
Digest: sha256:fff16eea1a8ae92867721d90c59a75652ea66d29c05294e6e2f898704bdb8cf1
Status: Downloaded newer image for ubuntu:latest
root@b000cd0e03d5:/#

You are left in a shell (/bin/bash) as root on the container, and the container is still running.

  • -i keeps STDIN open (short for --interactive)
  • -t allocates a terminal (short for --tty)
  • ubuntu is the image to use
  • /bin/bash specifies the command to run, rather than the default

At the root prompt, exit and then start another container with the same command. Then update Ubuntu's software index and install some packages.

root@b000cd0e03d5:/# exit
exit
$ docker run -it ubuntu /bin/bash
root@0e41b62958cc:/# apt-get update
...
Reading package lists... Done
root@0e41b62958cc:/# apt-get install -y wget cowsay recode jshon
...
done.
root@0e41b62958cc:/#

Leave this container running at the root prompt.

This time, Docker didn't have to download the ubuntu image again since it already had it cached.

Create an Image

In a second window (leaving the container running in the other), list the running containers with the docker ps command.

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
0e41b62958cc        ubuntu              "/bin/bash"         3 minutes ago       Up 3 minutes                            clever_wright

docker ps shows our running container. You could also run with -a (short for --all) to show all containers, running and stopped.

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
0e41b62958cc        ubuntu              "/bin/bash"         3 minutes ago       Up 3 minutes                                   clever_wright
b000cd0e03d5        ubuntu              "/bin/bash"         5 minutes ago       Exited (0) 3 minutes ago                       gracious_curie
f0dbe294ef5a        hello-world         "/hello"            5 minutes ago       Exited (0) 5 minutes ago                       musing_chaum

You can see our current container (0e41b62958cc), the first Ubuntu container we exited (b000cd0e03d5), and Hello World (f0dbe294ef5a), although your IDs will be different.

Each container has a Container ID and a Name. If you don't assign a name (we didn't) Docker assigns a random name. You can refer to a container by the at least the first 5 digits of the Container ID or by the Name.

Let's make an image of the read-write layer on the running image (the one with the software installed) by using the docker commit command. Then stop the first container (from the same, second window) using the docker stop command.

$ docker commit 0e41b62958cc ggotimer/chuck-norris-1
sha256:1821b7de33f04fb70bc6fc60ce69921f31542ac538b5b1333f9c3c511081ecc5
$ docker stop clever_wright
clever_wright

You could have used the Container ID (0e41b62958cc) or the Name (clever_wright) in either command. I just showed an example of using each.

Images are named with a single word (e.g., hello-world, ubuntu) if they are official Docker images. Otherwise they are named with your Docker Hub username (if you have one, mine is ggotimer), slash, an identifier (chuck-norris-1 in this case), colon, and then a tag (latest if you don't specify). Unless you plan to push to Docker Hub it doesn't matter, but get in the habit of naming them with the correct convention.

Notice that the container in the first window has stopped (we didn't type exit ourselves).

root@0e41b62958cc:/# exit

Check out the logs for the first container with the docker log command. You'll see a replay of all the input and output from that container, even after the container is stopped.

$ docker logs clever_wright
root@0e41b62958cc:/# apt-get update
...
Reading package lists... Done
root@0e41b62958cc:/# apt-get install -y wget cowsay recode jshon
...
done.
root@0e41b62958cc:/# exit

Run the Container

Let's look at the results of your interactive labor by starting your new image.

$ docker run ggotimer/chuck-norris-1 wget 'http://api.icndb.com/jokes/random?exclude=[explicit]' -qO-
{ "type": "success", "value": { "id": 549, "joke": "Chuck Norris killed two stones with one bird.", "categories": [] } }

Or you can try an even more unwieldy command.

$ docker run ggotimer/chuck-norris-1 /bin/bash -c "wget 'http://api.icndb.com/jokes/random?exclude=[explicit]' -qO- | jshon -e value -e joke -u | recode html | /usr/games/cowsay"
 _____________________________________
/ Chuck Norris always knows the EXACT \
\ location of Carmen SanDiego.        /
 -------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

We will make it easier to run, and to create, in Lesson 2- Build an Image with Code.