1. Overview

We know Docker is a powerful tool for creating, deploying, and running applications easily.

In the images vs containers tutorial, we discussed how Docker images are built using layers. We also discussed that the first layer is usually the operating system.

So, is it possible to connect to the container’s operating system? Yes, it is. And now we’re going to learn how to do it.

2. Connecting to an Existing Container

If we want to connect to an existing container, we should have any container in running status. For that, we must check the container status in our system with the docker ps command:

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                  PORTS               NAMES
4b9d83040f4a        hello-world         "/hello"            8 days ago          Exited (0) 8 days ago                       dazzling_perlman

As we have no running containers, let’s start a RabbitMQ container as an example:

$ docker run -d rabbitmq:3

Once the container is started, we’ll see it from another call to docker ps:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                NAMES
b7a9f5eb6b85        rabbitmq:3          "docker-entrypoint.s…"   25 minutes ago      Up 25 minutes       4369/tcp, 5671-5672/tcp, 25672/tcp   trusting_bose

Now connecting to this container is as easy as executing:

$ docker exec -it b7a9f5eb6b85 sh

At this point, we have an interactive shell inside the container:

  • docker exec tells Docker that we want to execute a command into a running container
  • The -it argument means that it will be executed in an interactive mode – it keeps the STIN open
  • b7a9f5eb6b85 is the container ID
  • sh is the command we want to execute

Let’s explore the operating system of our newly created container:

$ cat /etc/*-release
VERSION="18.04.4 LTS (Bionic Beaver)"
PRETTY_NAME="Ubuntu 18.04.4 LTS"

It seems to be a Bionic Beaver Ubuntu. If we check the FROM instruction in the RabbitMQ Dockerfile we realize that this image is built using Ubuntu 18.04.

We can disconnect from the container with the exit command or just CTRL+d.

This example was easy because, when we start a RabbitMQ container, it keeps running until we stop it. On the other hand, sometimes we have to deal with containers that don’t stay alive, like for example operating system containers. Let’s see how to get into them.

3. Running Containers in Interactive Mode

If we try to start a new operating system container, for example, an 18.04 Ubuntu, we’ll see that it doesn’t stay alive:

$ docker run ubuntu:18.04
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                                NAMES
08c26636709f        ubuntu:18.04        "/bin/bash"              10 seconds ago      Exited (0) 7 seconds ago                                        heuristic_dubinsky
b7a9f5eb6b85        rabbitmq:3          "docker-entrypoint.s…"   About an hour ago   Up About an hour           4369/tcp, 5671-5672/tcp, 25672/tcp   trusting_bose

While RabbitMQ container is still running, the Ubuntu one is stopped. Consequently, we can’t connect to this container using the docker exec command.

A way to avoid that would be to run this container in an interactive mode:

$ docker run -it ubuntu:18.04

So now that we are inside the container we can check the shell type:

$ echo $0

Actually, it’s handy to use the –rm argument when we start a container in interactive mode. It’ll make sure to remove the container when we exit:

$ docker run -it --rm ubuntu:18.04

4. Keep a Container Running

Sometimes we’ll run into weird situations where we need to start and connect to a container, but the interactive mode doesn’t work.

If we run into one of these situations is probably because something is wrong and it should be corrected.

But, if we need a fast workaround we can run the tail command in the container:

$ docker run -d ubuntu:18.04 tail -f /dev/null

With this command, we are starting a new container in detached/background mode (-d) and executing the tail -f /dev/null command inside the container. As a result, this will force our container to run forever.

Now we just need to connect using the docker exec command in the same way we have seen before:

$ docker exec -it CONTAINER_ID sh

Remember that this is a workaround and it should be only used in development environments.

5. Conclusion

In this tutorial, we have seen how we can connect to a shell of a running container and also how to start containers interactively.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.