Docker Containers
Overview
Teaching: 0 min
Exercises: 0 minQuestions
What motivates the creation of containers?
How do container work?
Objectives
Understand the operational model of Docker containers
Understand the concept of layers
Being able to launch, monitor, and modify Docker containers/images
0. Setup
- Go to your GitHub project repository (on the first day), create a new branch called
docker
from themain branch
, and modify to add the following components from this link:
- The
docker_config
directory and its content (daemon.json
).- The
install_docker.sh
file.- The
profile.py
file.- Check and make sure all the contents are correctly copied!
- Go to CloudLab, open your profile, switch to
Edit
mode and clickUpdate
. The newdocker
branch should show up.- Instantiate an experiment from this branch.
- Only login after the Startup column becomes Finished and type the following command:
sudo docker info | grep "Docker Root Dir"
- Confirm that you have something similar to the screenshot below
1. Why do we want container?
2. The issue: who does what?
3. Inspiration for Docker
4. Inspiration for Docker: intermodal shipping containers
5. Modern shipping ecosystem
6. A shipping container system for applications
7. Who does what? We don’t care …
8. Cloud-native applications on container
9. Hands-on: Getting started
- SSH into your CloudLab experiment.
- Check version of Docker:
$ docker version
- Docker is client-server application.
- Docker daemon (Engine): receives and processes incoming Docker API request and requires root privilege.
- Docker Hub registry: collection of public images (https://hub.docker.com/).
- Docker client : Talks to the Docker daemon via the docker API and the registry API.
10. Hands-on: Hello world
- Docker
containers
are instantiated from Dockerimages
.- You can check availability of local
images
andcontainers
.$ docker image ls $ docker container ls
- We can issue the following to start a service that will echo
hello world
to the screen.- This requires a Linux container to run the
echo
command.$ docker run alpine echo hello world
docker
: invoke the container engine.run
: subcommand to run a container.alpine
: name of the image based on which a container will be launched.echo hello world
: the command to be executed in the container environment.$ docker image ls $ docker container ls $ docker container ls --all $ docker run alpine echo hello world $ docker container ls --all
11. Hands-on: Interactive container
- We can launch a container and get into the shell of the container.
$ docker run -it ubuntu bash
- You are now in a new prompt: a shell inside the container
-it
: combination of-i
and-t
.
-i
tells Docker to connect to the container’s stdin for interactive mode-t
tells Docker that we want a pseudo-terminal
12. Hands-on: run something interactively
- The following commands are done inside the container.
- Let’s attempt to run
figlet
# figlet hello
- There will be an error.
- The current container does not have the
figlet
program yet.
13. Hands-on: installing and then running
- The following commands are done inside the container.
# apt-get update # apt-get install -y figlet # figlet hello
14. Exercise
- Type
exit
to shutdown the container and back to your normal terminal.- Repeat the process of launching an interactive container from start and try running
figlet
again.- Is the program still there?
15. Hands-on: Background container
- You should have already exited out of the container shell and back to the CloudLab environment.
- Run the following command
- Press
Ctrl-C
to stop after a few time stamps.$ docker run jpetazzo/clock
16. Hands-on: Background container
- Run the following command
$ docker run -d jpetazzo/clock $ docker ps
17. Hands-on: View log of your background container
- Use the first four characters of your container ID to view the log of the running Docker container
- Use
--tail N
to only look at the tail of the log.~~~ $ docker container ls $ docker logs –tail 5 YOUR_CONTAINER_ID
~~~
18. Exercise
- Find out how to kill a running container by using
docker kill
.
19. Docker images
- Image = files + metadata
- The files form the root filesystem of the container
- The metadata describes things such as:
- The author of the image
- The command to execute in container when starting it
- Environment variables to be set
- …
- Images are made of layers, conceptually stacked on top of each other.
- Each layer can add, change, and remove files and/or metadata.
- Images can share layers to optimize disk usage, transfer times, and memory use.
20. Example of a Java webapp
- CentOS base layer
- Packages and configuration files added by our local IT
- JRE
- Tomcat
- Our application’s dependencies
- Our application code and assets
- Our application configuration
21. The read-write layer
22. Containers versus images
- An image is a read-only filesystem.
- A container is an encapsulated set of processes running in a read-write copy of that filesystem.
- To optimize container boot time, copy-on-write is used instead of regular copy.
docker run
starts a container from a given image.
- Object-oriented analogy
- Images are conceptually similar to classes
- Layers are conceptually similar to inheritance
- Containers are conceptually similar to instances
23. How do we change an image?
- It is read-only, we don’t.
- We create a new container from the image
- We make changes to the container.
- When we are satisfied with the changes, we transform them into a new layer.
- A new image is created by stacking the new layer on top of the old image.
24. Image namespaces
- Official images (ubuntu, busybox, …)
- Root namespace.
- Small, distro images to be used as bases for the building process.
- Ready-to-use components and services (redis, postgresl …)
- User (and organizations) images:
<registry_name>/<image_name>:[version]
- jpetazzo/clock:latest
- linhbngo/csc331:latest
- Self-hosted images
- Images hosted by third party registry
URL/<image_name>
25. Hands-on: show current images
- If this is a new experiment, go ahead and run the following commands to get some images loaded.
$ docker run hello-world $ docker run alpine echo This is alpine $ docker run ubuntu echo This is ubuntu $ docker image ls
26. Hands-on: search images
- We can search for available images in the public Docker Hub
$ docker search mysql
27. General steps to create an image
- Create a container using an appropriate base distro
- Inside the container, install and setup the necessary software
- Review the changes in the container
- Turn the container into a new image
- Tag the image
28. Hands-on: create a container with a base distro
- Remember to note your container ID.
$ docker run -it ubuntu
29. Hands-on: install software inside the container
# apt-get update # apt-get install -y figlet # exit
30. Hands-on: check for differences
- Remember to note your container ID.
$ docker diff 16b0
- A: A file or directory was added
- D: A file or directory was deleted
- C: A file or directory was changed
31. Hands-on: commit changes into a new image
- Remember to note your container ID.
$ docker commit 16b0 ubuntu_figlet_$USER $ docker image ls $ docker history fe101
- From the screenshot:
- The
docker commit ...
command created a new image namedubuntu_figlet_lngo
that has the following unique id:fe101865e2ed
.- The
docker image ls
command shows this image.- The
docker history fe101
shows the layers making up this image, which include the layer that is the base ubuntu image54c9d
.
32. Exercise
- Test run the new
ubuntu_figlet
image by launching an interactive container using this image, then immediately runfiglet hello world
.
33. Automatic image construction: Dockerfile
- A build recipe for a container image.
- Contains a series of instructions telling Docker/Podman how an image is to be constructed.
- The
docker build
command builds an image from a Dockerfile.
34. Hands on: writing the first Dockerfile
- The following commands are done in the terminal (Ubuntu WSL on Windows/Mac Terminal).
$ cd $ mkdir myimage $ cd myimage $ nano Dockerfile
- Type the following contents into the nano editor
FROM
: the base image for the buildRUN
: represents one layer of execution.RUN
commands must be non-interactive.Save and quit after you are done.
- To build the image
35. Hands on: build the image
- The following commands are done in the terminal (Ubuntu WSL on Windows/Mac Terminal).
- Check that you are still inside
myimage
$ pwd $ docker build -t figlet_$USER .
-t
indicates a tag namedfiglet
will be applied to the image..
indicates that theDockerfile
file is in the current directory.
- The build context is the
Dockerfile
file in the current directory (.
) and is sent to the container engine. This context allows constructions of images with additional resources from local files inside the build context.- The base image is
Ubuntu
.- For each
RUN
statement, a container is created from the base image for the execution of the- commands. Afterward, the resulting container is committed into an image that becomes the base for the next
RUN
.
36. Exercise
- Use
docker image ls
anddocker history ...
to check which layer is reused for this image.- Test run the new
ubuntu_figlet
image by launching an interactive container using this image, then immediately runfiglet hello world
.
37. Hands on: CMD
- Edit your Dockerfile so that it has the following content
CMD
: The command to be run if the container is invoked without any command.- Rebuild the image with the tag
figlet_cmd_$USER
.- Run the following command
$ docker run figlet_cmd_$USER
- Question: Did we use any additional storage for this new image?
38. Hands on: Overriding CMD
- With CMD, the
-it
flag does not behave as expected without a parameter.- To override CMD, we can provide a command
$ docker run -it figlet_cmd_$USER $ docker run -it figlet_cmd_$USER bash
39. Hands on: ENTRYPOINT
-
ENTRYPOINT
defines a base command (and its parameters) for the container.
- The command line arguments are appended to those parameters.
- Edit
Dockerfile
as follows:
- Rebuild the image with the tag
figlet_entry_$USER
.- Run the followings:
$ docker run figlet_entry_$USER golden rams
40. Hands on: Why not both
ENTRYPOINT
andCMD
can be used together.- The command line arguments are appended to those parameters.
- Edit
Dockerfile
as follows:
- Rebuild the image with the tag
figlet_both_$USER
.- Run the followings:
$ docker run figlet_both_$USER golden rams $ docker run figlet_both_$USER
41. Hands on: Caveat
/bin/bash
does not work as expected.$ docker run -it figlet_both_$USER bash $ docker run -it --entrypoint bash figlet_both_$USER # exit
42. Hands on: Importing and building external code
- Create the following file called
hello.c
:
- Create the following Dockerfile called
Dockerfile.hello
:
- You can build an image with a specific Dockerfile
$ docker build -t hello_$USER -f Dockerfile.hello . $ docker run hello_$USER
43. Challenge
- Create an account on Docker Hub.
- Find out how to login from the command line and push the recently created
hello
image to your Docker Hub account.
44. Networking for container
- How can services provided by a container become available to the world?
45. Hands on: a simple web server
$ docker run -d -P nginx $ docker ps
-P
: make this service reachable from other computers (--publish-all
)-d
: run in background- Where is the port?
![]()
47. Hands on: How does the container engine know which port to map?
- This is described in the
Dockerfile
and can be inspected.- The keyword for this action is
EXPOSE
.
- Why do we have to map ports?
- Containers cannot have public IPv4 addresses.
- We are running low on IPv4 addresses anyway.
- Internally to host, containers have their own private addresses
- Services have to be exposed port by port.
- These have to be mapped to avoid conflicts.
48. Hands on: manual allocation of port numbers
$ docker run -d -p 8000:80 nginx $ docker run -d -p 8080:80 -p 8888:80 nginx
- Convention:
port-on-host:port-on-container
- Check out the web servers at all of these ports
49. Integrating containers into your infrastructure
- Manually add the containers to the infrastructure via container-generated public port.
- Predetermine a port on the infrastructure, then set the corresponding port mapping when run the containers.
- Use a network plugin to connect the containers with network tunnels/VLANS …
- Deploy containers across a physical cluster using Kubernetes.
50. Container network model
- Provide the notion of a
network
to connect containers- Provide top level command to manipulate and observe these networks:
docker network
$ docker network $ docker network ls
- What’s in a container network?
- Conceptually, it is a virtual switch
- It can be local to a single Engine (on a single host) or global (spanning multiple hosts).
- It has an associated IP subnet.
- The container engine will allocate IP addresses to the containers connected to a network.
- Containers can be connected to multiple networks.
- Containers can be given per-network names and aliases.
- The name and aliases can be resolved via an embedded DNS server.
51. Hands on: create a network
$ docker network create ramnet $ docker network ls
52. Hands on: placing containers on a network
$ docker run -d --name es --net ramnet elasticsearch:2 $ docker run -it --net ramnet alpine sh # ping es # exit
Key Points