Container
Exercise - List container and images
In order to look up whether you have any containers, execute the following command:
docker container ls
As you have just started with the lab, the list of containers is empty.
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESInfo
docker container ls and docker ps are identical commands
In order to check whether you already have any local images, execute the following command:
docker image ls
Again you will see an empty list:
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZEExercise - Your first container
Run your first container by executing:
docker run novatec/technologyconsulting-hello-container:v0.1
You will notice the following output:
$ docker run novatec/technologyconsulting-hello-container:v0.1
Unable to find image 'novatec/technologyconsulting-hello-container:v0.1' locally
v0.1: Pulling from novatec/technologyconsulting-hello-container
7c43afe89fe5: Already exists
2431b27052d8: Pull complete
95c210bc60c3: Downloading 3.271MB/7.607MB
e0df90639f4a: Verifying ChecksumWhat you can see above is the following scenario. Docker will try to run the image with the given tag
novatec/technologyconsulting-hello-container:v0.1. As it can’t be found locally (as it has never been run or
downloaded), the docker daemon will pull it from a remote registry (per default from Docker Hub
, i.e. the
“official” Container Image Registry as hardcoded in the standard Docker CLI tool) to download it:
sequenceDiagram
participant U as User
participant D as Docker Daemon
participant R as Remote Registry
U->>D: "docker run ..."
Note over D: image present?
D->>R: image pull
R-->>D: image
loop execute
D->>D: run container in foreground until terminated
end
Eventually the image will be there and the container is being run:
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2023-12-01 08:52:34,627 INFO [io.quarkus] (main) quarkus-hello 1.0.0-SNAPSHOT native (powered by Quarkus 3.1.3.Final) started in 0.052s. Listening on: http://0.0.0.0:8080
2023-12-01 08:52:34,630 INFO [io.quarkus] (main) Profile prod activated.
2023-12-01 08:52:34,630 INFO [io.quarkus] (main) Installed features: [cdi, resteasy-reactive, smallrye-context-propagation, vertx]Congratulations, you have just run your first container! Now what shall we do with it? At this point it is not particular exciting yet, because there is no interaction happening.
You will actually notice that your terminal does not take any commands from you any longer. Docker has run the container and put into the foreground. Hence your terminal is not accessible.
To get out of this scenario press Ctrl+C which will stop the container and give you the control over the terminal back.
Let’s recap what just happened. Execute the following command once again:
docker image ls
You will now see a first image in the list:
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
novatec/technologyconsulting-hello-container v0.1 c4550e0a7743 19 hours ago 137MBYou never downloaded this image explicitly, but it was pulled implicitly through the run command.
Now re-run the command to list the containers:
docker container ls
The output looks familiar:
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESThere is no active container running as it was stopped by pressing Ctrl+C
Modify the command slightly and call:
docker container ls -a
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
28bed265baad novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 2 minutes ago Exited (130) 54 seconds ago friendly_elbakyanThis command shows all containers. Started ones and stopped ones. The status will show that this container has been exited and is therefore stopped.
Exercise - Run container with options - detached mode
In order to improve our experience with running containers let’s walk through a couple of options of the docker run call.
To run a container of the same image type, but switched to the background you need the so-called detached mode:
docker run -d novatec/technologyconsulting-hello-container:v0.1
Milestone: DOCKER/CONTAINER/RUN-OPTIONS-DETACHED
Observe output similar to this:
$ docker run -d novatec/technologyconsulting-hello-container:v0.1
05179501b5e00d9959b1b25554568566a4253491dcfcaa30a79400564d3ace1fThree things are different compared to the first attempt.
- There is no more image download. The exercise uses the image of the same type. It is stored locally after a download and will be used directly then.
- There is no output log of the container visible. A long sequence of numbers and characters is displayed
- You get back control over the terminal after the start of the container
sequenceDiagram
participant U as User
participant D as Docker Daemon
participant R as Remote Registry
U->>D: "docker run ..."
Note over D: image present?
loop execute
D->>D: run container in background until terminated
end
D-->>U: release terminal
To validate if it is actually working, re-run this command:
docker container ls -a
And observe the difference in the output.
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
05179501b5e0 novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 18 seconds ago Up 15 seconds 8080/tcp charming_bhaskara
28bed265baad novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 3 minutes ago Exited (130) About a minute ago friendly_elbakyanThere are two containers listed. The original one, which is still stopped. And the new one which is up and running. For the running one you can also see the port information (8080/tcp).
This information is about the port on which the application listens internally. With our configuration it is not yet exposed to the outside of the container.
If we attempt to reach this port via:
curl localhost:8080/hello
There will be no server to respond
curl: (7) Failed to connect to localhost port 8080: Connection refusedTo validate if the server is actually there, try and check the logs. The command to do so is:
docker logs <container_id>
Now what is this container id?
There are multiple options to use:
- The container id as listed in the ls output. In my example case it would be: 05179501b5e0
- The container name as listed in the ls output. This is generated by docker as well. In my case: charming_bhaskara
- A subset of the container id. E.g. 051 in my case, which are the first three characters.
This will result to:
$ docker logs 051
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2023-12-01 08:55:38,627 INFO [io.quarkus] (main) quarkus-hello 1.0.0-SNAPSHOT native (powered by Quarkus 3.1.3.Final) started in 0.052s. Listening on: http://0.0.0.0:8080
2023-12-01 08:55:38,630 INFO [io.quarkus] (main) Profile prod activated.
2023-12-01 08:55:38,630 INFO [io.quarkus] (main) Installed features: [cdi, resteasy-reactive, smallrye-context-propagation, vertx]So the container started well, we just can’t reach it yet.
Exercise - Run container with options - port mapping
The easiest way to get an exposed port is to run another container with different configuration:
docker run -d -p 8080:8080 novatec/technologyconsulting-hello-container:v0.1
The difference in the command is the specification of the -p 8080:8080 part. The execution behavior will be very
similar to the previous run. An id will be returned.
Milestone: DOCKER/CONTAINER/RUN-OPTIONS-PORT
Re-run the listing of containers:
docker container ls -a
This will show the 3rd container:
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5fe72e974ee novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 15 seconds ago Up 14 seconds 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp keen_payne
05179501b5e0 novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 3 minutes ago Up 3 minutes 8080/tcp charming_bhaskara
28bed265baad novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 6 minutes ago Exited (130) 4 minutes ago friendly_elbakyanWhat is the significant difference between the two running containers?
Now try again to call the endpoint via curl:
curl localhost:8080/hello; echo
And get a response:
$ curl localhost:8080/hello; echo
Hello World (from f5fe72e974ee) to somebodySuddenly things are much more fun:
sequenceDiagram
participant U as User
participant D as Docker Daemon
participant C as Container
U->>D: "docker run ..."
Note over D: image present?
D->>C: creates
loop execute
D->>D: run container with port mapping
end
D-->>U: release terminal
U->>C: "curl ..."
C-->>U: "Hello World to somebody"
Exercise - Run container with options - Environment variables
The parameter “somebody” in the Hello World output is an environment variable within the container. If this is set to something different the output will change accordingly. Docker provides the “-e” option to set environmental options in the container.
Hence the command to get this confirmation is:
docker run -d -p 8080:8080 -e PROPERTY=Stuttgart novatec/technologyconsulting-hello-container:v0.1
The execution of this command will fail. Why?
To resolve this stop the running container or just map to another port. The second option is what we will be doing now by invoking:
docker run -d -p 8081:8080 -e PROPERTY=Stuttgart novatec/technologyconsulting-hello-container:v0.1
Milestone: DOCKER/CONTAINER/RUN-OPTIONS-ENV
After the execution list your containers and validate:
docker ps
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4b480045a033 novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 8 seconds ago Up 5 seconds 0.0.0.0:8081->8080/tcp, :::8081->8080/tcp wonderful_mcnulty
f5fe72e974ee novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 3 minutes ago Up 3 minutes 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp keen_payne
05179501b5e0 novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 6 minutes ago Up 6 minutes 8080/tcp charming_bhaskaraIt is also possible to format the output to focus on particular tabs:
docker ps --format "{{.ID}} {{.Ports}}"
which will show only
4b480045a033 0.0.0.0:8081->8080/tcp, :::8081->8080/tcp
f5fe72e974ee 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp
05179501b5e0 8080/tcpValidate if the set environment variable has worked as desired.
And get a response:
curl localhost:8080/hello; echo
Hello World (from f5fe72e974ee) to somebodycurl localhost:8081/hello; echo
Hello World (from 4b480045a033) to StuttgartThis example also shows you how easy it is to run multiple different versions or configurations side by side:
$ curl localhost:8081/hello; echo
Hello World (from 4b480045a033) to Stuttgart
$ curl localhost:8080/hello; echo
Hello World (from f5fe72e974ee) to somebodysequenceDiagram
participant U as User
participant D as Docker Daemon
participant C1 as Container 1
participant C2 as Container 2
U->>D: "docker run ..."
Note over D: image present?
loop execute
D->>D: run Container 1 with port 8080
end
D-->>U: release terminal
U->>D: "docker run ..."
Note over D: image present?
loop execute
D->>D: run Container 2 with port 8081
end
D-->>U: release terminal
U->>C2: "curl ...:8081/..."
C2-->>U: "Hello World to Stuttgart"
U->>C1: "curl ...:8080/..."
C1-->>U: "Hello World to somebody"
What a great time to be alive!
Exercise - Run container with options - Container name
You might have noticed that docker generates random (and arguably funny) names of container instances.
docker ps -a --format "Id: {{.ID}} Name: {{.Names}}"
which will result in:
$ docker ps -a --format "Id: {{.ID}} Name: {{.Names}}"
Id: 4b480045a033 Name: wonderful_mcnulty
Id: 1fcb204ef7c5 Name: musing_goldstine
Id: f5fe72e974ee Name: keen_payne
Id: 05179501b5e0 Name: charming_bhaskara
Id: 28bed265baad Name: friendly_elbakyanYou can specify a name when running a container, too:
docker run -d -p 8082:8080 -e PROPERTY=Stuttgart-Entwicklertag --name happy_container novatec/technologyconsulting-hello-container:v0.1
Milestone: DOCKER/CONTAINER/RUN-OPTIONS-NAME
To display only the recent container you can also use:
docker container ls -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6f4fc2fe956d novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 11 seconds ago Up 9 seconds 0.0.0.0:8082->8080/tcp, :::8082->8080/tcp happy_containerDone!
Exercise - Clean up
While walking through those exercises a lovely little container collection has been established on your machine.
Re-run the following command to show all the work already completed:
docker ps -a
Result should look somewhat like this:
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6f4fc2fe956d novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 43 seconds ago Up 41 seconds 0.0.0.0:8082->8080/tcp, :::8082->8080/tcp happy_container
4b480045a033 novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 4 minutes ago Up 3 minutes 0.0.0.0:8081->8080/tcp, :::8081->8080/tcp wonderful_mcnulty
1fcb204ef7c5 novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 4 minutes ago Created musing_goldstine
f5fe72e974ee novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 7 minutes ago Up 7 minutes 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp keen_payne
05179501b5e0 novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 10 minutes ago Up 10 minutes 8080/tcp charming_bhaskara
28bed265baad novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 13 minutes ago Exited (130) 12 minutes ago friendly_elbakyanYou may notice that it also created a container for the unsuccessful attempt to run two instances on the same port. A container instance exists even though it never got started at all.
To remove a container let’s start with the first one we built. In my example (28bed265baad/friendly_elbakyan). Just as before when logging, please do not use the names and IDs from the script, but from your real environment.
Invoke:
docker rm 28b (Replace “28b” with the first 3 characters of your container id!)
List all the containers again to validate.
If you try to remove the last running container you have built (top one in the list by now), will this work?
docker rm happy_container (Do not replace “happy_container” as you should have this container, too!)
So, let’s stop this container:
docker stop happy_container
and try again:
docker rm happy_container
This time things look better.
As you realize that can become a bit of a task if you have to clean up a certain container mess. You can use shell tooling and scripting to improve, but be careful when doing this in production.
The “-q” option returns only the IDs, which can be handy for that:
docker ps -q
4b480045a033
f5fe72e974ee
05179501b5e0To stop all running containers execute:
docker ps -q | xargs docker stop
This will call “docker stop” with all running container ids.
Milestone: DOCKER/CONTAINER/CLEANUP-STOP
Running docker ps -a again should show no containers with status “Up”.
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4b480045a033 novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 7 minutes ago Exited (143) 14 seconds ago wonderful_mcnulty
1fcb204ef7c5 novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 8 minutes ago Created musing_goldstine
f5fe72e974ee novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 11 minutes ago Exited (143) 14 seconds ago keen_payne
05179501b5e0 novatec/technologyconsulting-hello-container:v0.1 "./application -Dqua…" 14 minutes ago Exited (143) 14 seconds ago charming_bhaskaraTo remove all containers run:
docker ps -a -q | xargs docker rm
This will call “docker rm” with all container ids.
Warning
ONCE AGAIN: BE CAREFUL DOING THIS AT HOME!
Milestone: DOCKER/CONTAINER/CLEANUP-RM
No more containers should be there:
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESDo not remove the image yet as it is needed at a later step in the exercise.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
novatec/technologyconsulting-hello-container v0.1 c4550e0a7743 19 hours ago 137MBThe first part of the exercise concludes with this. Congratulations! You’ve done the first step into a larger container world!