How To Interact With Docker Containers

This article extends the previous Docker article and shows how to interact with Docker containers by executing commands inside containers, installing software inside containers, inspecting container status, accessing containers using Bash, persisting changes into images and removing unused containers and images.

In this tutorial you will learn:

  • How to execute commands inside containers
  • How to install software inside containers
  • How to inspect container status
  • How to access containers using Bash
  • How to persist changes into images
  • How to remove unused containers and images

PHP installed

PHP installed.

Software Requirements and Conventions Used

Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Any Linux Distribution
Software Docker
Other Privileged access to your Linux system as root or via the sudo command.
Conventions # – requires given linux commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires given linux commands to be executed as a regular non-privileged user

How To Interact With Docker Containers

In the first article of this series, you learned Docker concepts and some basic commands and saw how you can easily run software in a compartmentalized way, without touching your host operating system configuration. Let’s now go deeper, getting inside a running container and executing some commands.



Executing commands inside a running container

In the previous article, you started an Apache container. The underlying image didn’t have PHP installed, so it was only capable of serving static HTML pages. Let’s get a container with Apache and PHP installed on it. In case you are wondering, there are images ready to be used with both Apache and PHP installed, and they can be found on Docker Hub. We are doing this just to demonstrate how an image can be customized to your needs.

So, let’s start a Debian instance using a similar command line of the previous article, but with two differences: let’s give it a name (--name debian_container), so we can refer to it later, and allocate a terminal for it to run (-it).

$ docker run -it --name debian_container -d -p 8000:80 -v "$PWD":/var/www/html debian

We can interact with a running Docker container. You’ve been told before that the containers share the same kernel as the host operating system. Let’s check.

$ docker exec debian_container uname -a

The command docker exec above executes the given command inside the container and show it’s output.

All docker commands have an associated help, therefore we can see the options docker exec accepts:

$ docker exec --help

Now you can play around with other commands:

$ docker exec debian_container ls -l
$ docker exec debian_container pwd
$ docker exec debian_container whoami
$ docker exec debian_container cat /etc/issue

In this last command, we learned that the container is running Debian 9, despite the operating system of your machine. As previously mentioned, the host operating system and the container share only the kernel.

If you tried but couldn’t execute a command inside the container, probably it’s not there. The image (as all other images) is built from a minimal Debian setup, so any additional tool has to be installed. It accomplishes two objectives: smaller disk size and improved security since less software means fewer bugs to be exploited.

Now, let’s get inside the container.

$ docker exec -it debian bash
root@b5c694a02248:/usr/local/apache2#

Notice that the prompt has changed and now you are user root inside the container (b5c694a02248 is the hostname inside the container) inside a bash shell.



Installing Software Into a Container

We now have a shell inside the container with user root. Since this is a trimmed down version of Debian, there aren’t even the commands top and ps. Let’s get them installed.

# apt update
# apt install procps

You can see what’s running with top and ps -ef.

root@f5b423465e03:/# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 19:46 pts/0    00:00:00 bash
root        42     0  0 19:49 pts/1    00:00:00 bash
root       310    42  0 19:53 pts/1    00:00:00 ps -ef
root@f5b423465e03:/#

Yes, it’s frugal. Docker containers usually have the absolute minimum number of processes executing. To leave the shell and return to your host operating system, just exit bash (type exit or ctrl+d).

Notice that many files have been downloaded by apt update and apt install. They all exist in the disk of the running container. They still exist if the container is stopped and started again (docker stop debian_container; docker start debian_container). But they don’t exist in the image. It means that, if you remove this container (docker rm debian_container) and start a new container, you’ll have to install package procps again. Also, if you start the Debian image in another host, you will also have to install procps again. We’ll see later how to persist the image with disk modifications, so next time you start a container, all software will be installed.

Now, let’s get Apache and PHP installed. The command below will take long to finish and will download and install all dependency packages, including Apache and PHP — it will take some minutes. In the end, start Apache and access localhost in port 8000 on your web browser (http://localhost:8000). You shall see the default Debian page for Apache.

# apt install libapache2-mod-php
# service apache2 start


Apache Debian default page

Apache Debian default page.

Now let’s confirm that PHP is there. You can either go to /var/ww/html inside the container, or exit the container shell and type from the current directory in your host operating system (remember we mapped current directory into /var/www/html inside the container?)

$ echo '' >phpinfo.php

And voilà (http://localhost:8000/phpinfo.php).

PHP information.

PHP information.

Committing To An Image

As mentioned earlier, the changes made to the container persist as long as the container persists, and containers are expected to be ephemeral — they are made to be destroyed. Durable modifications should be made into images.

The next article will show how to create a customized image in an elegant (and strongly recommended) manner, using a Dockerfile. For now, you will learn a hack that can be helpful in specific situations where it’s not possible or desirable to write a Dockerfile. Extending images with a Docker file if preferred because it can be easily edited while committing the container state to a new image leaves no trace of the changes made unless a laborious filesystem layer analysis is performed.

The command docker commit has two parameters: container name and new image name and it will create a new image on the local images cache based on the container. In the command below, debian_container is the container name and debian-apache-php is the new image name.

$ docker commit debian_container debian-apache-php
sha256:3f01c0c71539c4dc6dfd7483ff68c41143b7e9aeb52de4a9892c8cc136eda236

Listing images in the host cache.

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
debian-apache-php   latest              3f01c0c71539        10 minutes ago      235MB
debian              latest              be2868bebaba        11 days ago         101MB

Notice that there is a new image in your host. One interesting characteristic of image and container management is that Docker will only store the difference of disk state between the current image and the image it is based upon, so no redundant disk space is wasted. For this, Docker uses a layered filesystem that uses the copy-on-write approach: when a new container is created it inherits the same disk of the image and, as modifications are made to files, they are written in a new layer.



Inspecting Containers

Docker maintains lots of information about Docker objects. The command docker inspect is used to view them.

$ docker inspect debian_container

The command will retrieve a JSON object with tens of lines detailing the container status: container id, created date, state, image, log path, ports, volumes, networks, etc.

Pruning Containers and Images

After playing around with containers and images, the disk of the host will eventually fill up with abandoned entities that need to be cleared so you can reclaim disk space.

The command docker container prune will remove all stopped containers. Be careful: once the container is removed, any associated state is lost. Make a backup or commit changes to an image before.

The command docker image prune will delete all unused images. We haven’t yet built images, but this command will be useful in the next article.

Conclusion

In this article, you learned how to interact with containers and how to commit changes to images, although this approach is not recommended.

In the next article, you will create your own images with Dockerfile, the recommended way to customize Docker images.

More in this Docker article series



Comments and Discussions
Linux Forum