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
Software Requirements and Conventions Used
|Category||Requirements, Conventions or Software Version Used|
|System||Any Linux Distribution|
|Other||Privileged access to your Linux system as root or via the
# – requires given linux commands to be executed with root privileges either directly as a root user or by use of
$ – 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 (
$ 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
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
ps. Let’s get them installed.
# apt update # apt install procps
You can see what’s running with
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
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
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à (
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.
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.
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.
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.
docker image prune will delete all unused images. We haven’t yet built images, but this command will be useful in the next article.
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.