Skip to content

Images & Containers

Manage Images and Containers via Docker cli.

What you will learn:

  • Handling of Images through Docker cli
  • Handling of Containers through Docker cli

1. Browse an Image

Now let us walk through the process of handling Images with Docker cli. First, we will pull an Image from an online registry (~ repository).

Docker Hub is the official Docker Registry. You can browse through available Images in your browser or via Docker cli. So let us look for the nginx image on Docker Hub!

First, find the correct name of the official Docker Hub Image for nginx via cli commands!


HINT

1. Look through the help page of Docker cli:

$ docker --help
2. You should find the correct search term and look for nginx:
Solution

$ docker search nginx

Look for the "OFFICIAL" column and take note of the image name.


Now that we know the name of the correct image, let us navigate to Docker Hub in the browser. Look for the nginx image with the alpine tag and write down the image size for a linux/amd64 OS.


Solution

1. Search for nginx on Docker Hub.
2. Click on the tags tab.
3. Look for the alpine distribution.
4. Check the OS/ARCH column and look for linux/amd64.



2. Pull an Image

Pulling images means that you save an image from an online registry locally on your machine.

In the next few sections we will go through several steps before actually starting a container. This is just for a better understanding of the terms. If you simply want a head start, you may jump to section 3.

Now, pull we will pull another image. Pull the alpine image with the latest tag from Docker Hub. It’s a lightweight linux distribution image that contains some basic utilities. That makes it great for testing!


Question

What is difference between the nginx:alpine image and the alpine:latest image?

HINT

1. You can search for the image first. Either on Docker Hub or via cli:

Solution

$ docker search alpine


2. Lookup the docker command for pulling the image
Solution

$ docker pull alpine


3. Take the latest tag for the correct version.
Solution

$ docker pull alpine:latest
If you do not specify a tag in the pull command, the tag always defaults to latest!


When you are done, inspect your local images and look for the alpine image you just downloaded. What’s the size of the alpine:latest image?


Solution

$ docker images


3. Create and Start a Container

The image we just pulled can now be used to create a container from it. The container will be the application environment for the image to run in.

Lookup the correct command and create a container called container1 from the alpine:latest image!


Solution

$ docker create --name container1 alpine


Now, get a list of all the containers on your local machine!


Solution

$ docker ps -a


The container is created but not running. That’s why we can only find it with the –all option! We can start the container now. Lookup the correct command, start the container and see if it is in running state now. Briefly discuss your findings!


Solution

$ docker start container1
$ docker ps
$ docker ps -a
The container starts but no task is running. That's why it completes without any command and exits. This shows, how quick containers can be started and exited again. It's a very good fit for short running tasks.


4. Run an Image

Running an image / container also results in starting the container. But it’s a way to combine several commands in one. To see what’s all happening behind the scenes, let’s jump right into it and run the nginx:alpine image from Docker Hub!

Take note of the output in your console and try to explain what’s happening along the way!


Solution

$ docker run nginx:alpine

The docker run command combines a few steps in one. It pulls the image, if it's not present on the machine. Next, it will build the container and then start the container.


That worked just fine. As you notice, the container is still running though. The nginx image does not complete and exit the container like the alpine image did. The container is running in your current terminal window now! On thing you could do is to create a new terminal window and inspect your containers from there.

We want to try something else though. Namely, we want to start the container in detached mode! That allows us to still use the same terminal window, while the container is running in the background.

Lookup the correct option that we need to combine with the docker run command in order to start the nginx image in detached mode.


Solution

$ docker run -d nginx:alpine


Now, list all running containers on your machine with one command.


Solution

$ docker ps


You see that the nginx image does keep the container running. When you run the docker ps -a command again, you will see the running containers along with all stopped containers.



5. Cleaning up

In this chapter we will first add another container and then come to clean up our machine.

To set up the task, run another instance of the nginx image in detached mode and name it buggy-nginx. List all containers again and see if you can tell the difference between instances of the nginx image.


Solution

$ docker run -d --name buggy-nginx nginx
$ docker ps


Ok, now it’s time to clean up a bit. We want to get rid of old, unused resources and make space for our future projects.

Before we begin, take a look at the Docker environment on your machine via docker info. How many containers and images are currently present?

First, we want to delete the alpine container that we created in section 3. Lookup which command and container information you need to delete the alpine container.


HINT

1. Lookup the command to remove a container:

Solution

$ docker --help | grep -i remove


2. Combine the deletion prompt with the name of the container:
Solution

$ docker ps -a      # get the name of the container
$ docker rm container1


3. Finally make sure, that the container doesn't appear in the list of all stopped containers anymore:
$ docker ps -a


In the next step we want to remove the “buggy” instance of the nginx image and only hold on to the regular one. Delete the buggy-nginx container. Describe the steps that are necessary.


HINT

1. Lookup the command to remove a container.

Solution

$ docker --help | grep -i remove
$ docker rm buggy-nginx


2. Read the output after the delete prompt. Fulfill the requirements to delete the buggy container.
Solution

$ docker stop buggy-nginx
$ docker rm buggy-nginx
or
$ docker rm buggy-nginx -f    # Careful with this prompt as it will cancel all tasks within running containers!


1. When checking all containers now, the buggy-nginx shouldn't appear in the list anymore:
$ docker ps -a


Very good, the list of our containers should be down to one now.


Finally we will clean up more space by removing unused images from our machine.

List all images and take note of the space the images take up on your disc.


Solution

$ docker images


Next, delete the alpine image. It’s not very big but we won’t be needing it anytime soon.


Solution

$ docker rmi alpine


That’s how you do it - very nice!

Now, what do you expect to happen, if you wanted to delete the nginx image?

Go ahead and try it, using the remove prompt. Discuss what’s happening.


6. Build an Image

So far we have been working with Images from Docker Hub. You may also use Images from other registries, including private ones.

Authorization and authentication processes may differ for each private registry provider, which is why we will not cover private registries here. You should always find a detailed documentation from the provider itself.

One more thing we want to cover here though, is how to create own Images. Further you can upload your Image to a registry - e.g. Docker Hub. As we are not building production ready Images, we will skip this step though and only show the flow how to do it.


A Dockerfile is a text file that holds instructions for Docker to automatically generate an Image. For this chapter we will build an Image from a given Dockerfile. To get more insight on how to write Dockerfiles, look into Chapter 3 - Dockerfile.


Now, inspect the directory under exercise/docker/reference/2-static-html-project. It’s a very basic example with just one HTML file and a Dockerfile. Look at the Dockerfile in particular and try to make sense of the two lines of instructions.


Hint

# this first line declares nginx as our base image layer
# note, that nginx:alpine already is an image itself and consists of several layers
# you can see the layers, when pulling or running the nginx:alpine image like we described in the previous sections
FROM nginx:alpine

# this part copies the files from the current directory over to the directory on the base image (nginx:alpine)
# it will put our files into the right place to be served by nginx
COPY . /usr/share/nginx/html


We want to build the image from the given Dockerfile now. Name the image static-html and tag it with the version 1.0.

buildx is the new build

The classic docker build command is going to be deprecated and replaced by buildx. In this session we will offer solutions of both methods. Please note that if you are using a compatible container engine (like podman), the commands can differ.


Hint

1. Navigate to the project folder in your terminal:

Solution

$ cd exercise/docker/reference/2-static-html-project


2. Run the Docker build command with the tag option:
Solution with build

$ docker build -t static-html:1.0 .

Solution with buildx

$ docker buildx build -t static-html:1.0 .


3. Check the result by listing all your images:
Solution

$ docker images



Very good, we can see that the image static-html:1.0 has been created successfully. In your stdout you can trace the steps that have been undertaken by Docker to build the image. You should also find the two lines of instructions from the Dockerfile!

You can also read that the image has been named to docker.io/library/static-html:1.0. In the beginning we said that it’s possible to push the image we just created to an online registry. We will only show the command to do it here but not execute it as it is just a plain html page example.

When running $ docker image push static-html:1.0, Docker would look for the image named static-html:1.0 locally and push it to docker.io, as it was defined in the full name, as we saw in the stdout from the build command. Find out more about the commands of docker image by running it with the --help flag.


One thing we want to do with our image, is creating and running a container from it! So, figure out how you can run a container, named test-page, in detached mode and expose it on localhost port 8090!

For first orientation and help, read through the nginx Image docs on Docker Hub!


HINT

1. It's the same procedure as when running an Image from Docker Hub or other online registries. Because you have built the image locally, it's already present on your machine.
2. The command we are looking for will build and run the container. Additionally, we need the option flags for the port-mapping and naming of the container:

Solution

$ docker run --help
$ docker run --name test-page -p 8090:80 -d static-html:1.0


3. Alternatively you could separately create and subsequently start the container, like we did in section 3 . This will automatically start the container in detached mode.
Solution

$ docker create --name test-page -p 8090:80 static-html:1.0
$ docker start test-page


Great! You are fully capable of managing Docker containers now!

For some more practice and to reduce artifacts, finally clean up your environment.


Discussion

What could we improve when building our container for a web server?

HINT

Should all files in our directory be included in our image?

Additional HINT

Take a look at .dockerignore files.


7. Push an Image

Now let’s push our static-html image to a registry. We need to add a tag for this purpose.

Login details will be provided

Your instructor will provide the necessary docker login information to you.

$ docker login -u user -p XXXXXXXX XXXXXXX.azurecr.io
Your task: Add the required tag to the image and push it to the repository. Use your first name as version.

Hint

$ docker tag --help

Solution

$ docker tag static-html:1.0 <registry>/static-html:<your_name>
Replace <registry> and <your_name> appropriately.

Solution

docker push <registry>/static-html:<your_name>
Replace <registry> and <your_name> appropriately.

END