Running and stopping containers
Next we will start using a more useful image than hello-world. We can run Ubuntu just with
docker run ubuntu.
$ docker run ubuntu
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
83ee3a23efb7: Pull complete
db98fc6f11f0: Pull complete
f611acd52c6c: Pull complete
Status: Downloaded newer image for ubuntu:latest
Anticlimactic as nothing really happened. The image was downloaded and ran and that was the end of that. It actually tried to open a shell but we will need to add a few flags to interact with it.
-t will create a tty.
$ docker run -t ubuntu
Now we're inside the container and if we input
ls and press enter... nothing happens. Because our terminal is not sending the messages into the container. The
-i flag will instruct to pass the STDIN to the container. If you're stuck with the other terminal you can just stop the container.
$ docker run -it ubuntu
bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
Great! Now we know at least 3 useful flags.
-t (tty) and
Let's throw in a few more and run a container in the background:
$ docker run -d -it --name looper ubuntu sh -c 'while true; do date; sleep 1; done'
If you are command prompt (Windows) user you must use double quotes around the script i.e.
docker run -d -it --name looper ubuntu sh -c "while true; do date; sleep 1; done". The quote or double-quote may haunt you later during the course.
The first part,
docker run -d. Should be familiar by now, run container detached.
-itis short for
-t. Also familiar,
-itallows you to interact with the container by using the command line.
Because we ran the container with
--name looper, we can now reference it easily.
The image is
ubuntuand what follows it is the command given to the container.
And to check that it's running, run
docker container ls
-f the output of logs with
$ docker logs -f looper
Thu Mar 1 15:51:29 UTC 2023
Thu Mar 1 15:51:30 UTC 2023
Thu Mar 1 15:51:31 UTC 2023
Let's test pausing the looper without exiting or stopping it. In another terminal run
docker pause looper. Notice how the logs output has paused in the first terminal. To unpause run
docker unpause looper.
Keep the logs open and attach to the running container from the second terminal using 'attach':
$ docker attach looper
Thu Mar 1 15:54:38 UTC 2023
Thu Mar 1 15:54:39 UTC 2023
Now you have process logs (STDOUT) running in two terminals. Now press control+c in the attached window. The container is stopped because the process is no longer running.
If we want to attach to a container while making sure we don't close it from the other terminal we can specify to not attach STDIN with
--no-stdin option. Let's start the stopped container with
docker start looper and attach to it with
Then try control+c.
$ docker start looper
$ docker attach --no-stdin looper
Thu Mar 1 15:56:11 UTC 2023
Thu Mar 1 15:56:12 UTC 2023
The container will continue running. Control+c now only disconnects you from the STDOUT.
To enter a container, we can start a new process in it.
$ docker exec -it looper bash
root@2a49df3ba735:/# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.2 0.0 2612 1512 pts/0 Ss+ 12:36 0:00 sh -c while true; do date; sleep 1; done
root 64 1.5 0.0 4112 3460 pts/1 Ss 12:36 0:00 bash
root 79 0.0 0.0 2512 584 pts/0 S+ 12:36 0:00 sleep 1
root 80 0.0 0.0 5900 2844 pts/1 R+ 12:36 0:00 ps aux
ps aux listing we can see that our
bash process got PID (process ID) of 64.
Now that we're inside the container it behaves as you'd expect from Ubuntu, and we can exit the container with
exit and then either kill or stop the container.
Our looper won't stop for a SIGTERM signal sent by a stop command. To terminate the process, stop follows the SIGTERM with a SIGKILL after a grace period. In this case, it's simply faster to use kill.
$ docker kill looper
$ docker rm looper
Running the previous two commands is basically equivalent to running
docker rm --force looper
Let's start another process with
-it and add
--rm in order to remove it automatically after it has exited. The
--rm ensures that there are no garbage containers left behind. It also means that
docker start can not be used to start the container after it has exited.
$ docker run -d --rm -it --name looper-it ubuntu sh -c 'while true; do date; sleep 1; done'
Now let's attach to the container and hit control+p, control+q to detach us from the STDOUT.
$ docker attach looper-it
Mon Jan 15 19:50:42 UTC 2018
Mon Jan 15 19:50:43 UTC 2018
^P^Qread escape sequence
Instead, if we had used ctrl+c, it would have sent a kill signal followed by removing the container as we specified
docker run command.
Now that we've warmed up it's time to get inside a container while it's running!
devopsdockeruh/simple-web-service:ubuntu will start a container that outputs logs into a file.
Go inside the container and use
tail -f ./text.log to follow the logs.
Every 10 seconds the clock will send you a "secret message".
Submit the secret message and command(s) given as your answer.
Ubuntu in a container is just... Ubuntu
A container that is running a Ubuntu image works quite like a normal Ubuntu:
$ docker run -it ubuntu
bin dev home media opt root sbin sys usr
boot etc lib mnt proc run srv tmp var
PID TTY TIME CMD
1 pts/0 00:00:00 bash
13 pts/0 00:00:00 ps
Wed Mar 1 12:08:24 UTC 2023
An image like Ubuntu contains already a nice set of tools but sometimes just the one that we need is not within the standard distribution. Let us assume that we would like to edit some files inside the container. The good old Nano editor is a perfect fit for our purposes. We can install it in the container by using apt-get:
$ docker run -it ubuntu
root@881a1d4ecff2:/# apt-get update
root@881a1d4ecff2:/# apt-get -y install nano
root@881a1d4ecff2:/# cd tmp/
root@881a1d4ecff2:/tmp# nano temp_file.txt
As can be seen, installing a program or library to a container happens just like the installation is done in "normal" Ubuntu. The remarkable difference is that the installation of Nano is not permanent, that is, if we remove our container, all is gone. We shall soon see how to get a more permanent solution for building images that are perfect to our purposes.
Start a Ubuntu image with the process
sh -c 'while true; do echo "Input website:"; read website; echo "Searching.."; sleep 1; curl http://$website; done'
If you're on Windows, you'll want to switch the
sh -c "while true; do echo 'Input website:'; read website; echo 'Searching..'; sleep 1; curl http://$website; done".
You will notice that a few things required for proper execution are missing. Be sure to remind yourself which flags to use so that the container actually waits for input.
Note also that curl is NOT installed in the container yet. You will have to install it from inside of the container.
helsinki.fi into the application. It should respond with something like
<title>301 Moved Permanently</title>
<p>The document has moved <a href="http://www.helsinki.fi/">here</a>.</p>
This time return the command you used to start process and the command(s) you used to fix the ensuing problems.
Hint for installing the missing dependencies you could start a new process with
- This exercise has multiple solutions, if the curl for helsinki.fi works then it's done. Can you figure out other (smart) solutions?