SSH into a Docker Container? How to Execute Your Commands

7 min read

If you're reading this, you’re probably just getting your head around this Docker thing. I’ll take a bold guess here and bet that, until recently, your local dev environment involved some sort of virtual machine engine—Vagrant, maybe?

If that’s the case (or close to it), then I have good news for you: I was in your shoes not so long ago.

Now I have to tell you something that might be a little shocking: There’s most likely no need to SSH into your Docker containers.

Just ask yourself: Why would you SSH into a container? Simply to execute some commands within it, right?

After reading this article, you’ll have a much clearer picture of why you don’t need to SSH into the container to do that.

I’ll start by explaining the main differences between a virtual machine and a Docker container. Then I’ll show you some alternatives for how you can achieve your goal the Docker way. And finally, I’ll show you how you could SSH into the Docker container should you absolutely need to.

Ready? Let’s go.

To SSH or Not to SSH into a Docker Container

As I said, I’m assuming you come from a background where virtual machines are a common thing.

In this scenario, you’re used to starting your work by getting into the VM and running a bunch of commands within it. Now you’re switching to Docker, and you’re looking for a way to do the same and be on your way.

The problem is, Docker containers are not VMs.

The main difference is that, to the operating system, a VM is not really distinguishable from another physical computer on your LAN. Your VM engine is simulating a whole hardware set and then running a potentially different OS on top of it.

Docker containers are not simulated hardware. They are self-contained execution environments.

You could think of Docker as a generalization of the Java Virtual Machine. Think about it this way: What does it take to run a Java program? A JVM. With Docker, this same principle is extended to any language you want.

Differences Between Virtual Machines and Docker Containers

Another way to start grasping the difference between Docker and a VM is to look at the Dockerfile. Let’s take this one as a typical example:

FROM ubuntu:13.10
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update -qq -y &&
     apt-get install curl -qq -y &&
     apt-get clean
RUN curl -sSL https://get.rvm.io | bash -s stable –ruby=2.1.1

Notice how you don’t specify anything about the underlying hardware.  That’s no coincidence; it’s by design. So, what hardware is being virtualized then? None!

What’s being virtualized is the execution environment: basically an OS in its own space. This is what makes Docker images so lightweight and fast.

Now that we’ve covered the basics, the question almost answers itself: SSH into a Docker container would be very much like SSH into localhost.

Docker containers can basically be used in two ways:

  • To execute a given command and finish

  • As daemons

The second usage is what can be confusing at first: Docker containers can be alive in the background, which makes them similar to a running VM, but in reality they’re more like a service (Apache, MySQL, etc.).

So now you have a clearer picture, but you’re still facing the same problem: How do you run commands inside your Docker container?

An Alternative to SSH: Running Commands Within a Docker Container

Let’s say you want to simply check whether your container has been configured correctly—for instance, is a particular file accessible from within it?

If you were using a VM, all it would take to be sure would be to SSH into it and run a simple ls $filename, right?

The trick here is to take a little step back and realize that, when you SSH into a VM, you’re actually connecting to a running daemon within the VM (sshd), which offers you a nice shell interface, usually Bash.

Bash is a command interpreter, a program running within the VM that is designed to take user input, interpret it and run commands by interacting with the underlying OS.

So what you’re actually looking for is a way to run a Bash interpreter within the container.

The container is created from a Docker image. Every Docker image has an OS in it. And, if your image is based around any Linux distribution, chances are Bash is already present there.

And now the magic begins.

Introducing Docker Exec

Docker offers you a very interesting tool: docker exec. With docker exec you can have the container run any command you want.

So, why not run the bash command?

That’s right, you can simply run something like: docker exec -it <CONTAINER_NAME> bash and, voilà, you’re greeted with a nice TTY running further commands inside the container:

And once in there, you’re free to run any command you like. For instance:

There you go.

An Alternative to Docker Exec: Docker Attach

Another way to achieve a similar goal is to use the command docker attach. In this case, Docker will connect the container’s standard input, output and error streams to the hosts’, effectively having you interact with the running container as if it were a regular program running directly on the host.

This seems like a much simpler solution, doesn’t it? Well, there’s a minor caveat: The attach command can only connect the host streams to those of the command defined as ENTRYPOINT or CMD in the container.

Make Sure There’s an SSH Daemon Running Within the Container

The first thing you need to SSH into any computer is an SSH server running in it. When it comes to a Docker container, the same is true.

How can you make sure there is a daemon running inside the container? Well, with what you’ve just learned, it should be fairly easy.

All you have to do is run a command such as: docker exec -it <CONTAINER_NAME> service ssh status. (The exact command depends on the OS present in your image. Assuming it’s an Ubuntu derivative, this command will do.)

You’re ready to move to the next section if you get a response similar to:

You need to set up the SSH daemon as you would in any other scenario if you get something like this:

Given you’re working with Docker, you can do two things:

  1. Update your Dockerfile (and rebuild the image)

  2. Install the SSH daemon in the running container, in which case the changes you make will not be preserved once the container is stopped

How to Include an SSH Daemon in Your Dockerfile

Let’s say your Dockerfile looks like this:

FROM ubuntu:13.10
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update -qq -y &&
     apt-get install curl -qq -y &&
     apt-get clean
RUN curl -sSL https://get.rvm.io | bash -s stable –ruby=2.1.1

All you’d have to do is add the following lines at the end:

RUN apt install openssh-server && 
     systemctl ssh start &&
     systemctl ssh enable

Then rebuild your image and restart your container.

How to Install an SSH Daemon in Your Running Docker Container

In this scenario, you could use the docker exec command to get ahold of a terminal within it, as we already discussed: docker exec -it <CONTAINER_NAME> /bin/bash. Once inside, you’d run:

apt install openssh-server && systemctl ssh start

How to Get the IP of a Running Docker Container

No matter which option you chose from the previous step, by now you should have a running SSH daemon inside your running container. Now, to connect via a secure shell, you need to know where you’re going to connect (i.e., what’s the container’s IP address?).

Docker networking is a little complicated to explain in this post. If you’re interested in learning more about it, I recommend you read this.

For the time being, the command docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' CONTAINER_NAME will do exactly what you need:

How to Connect to a Running Docker Container Using SSH

All right. Now that you have all the pieces in place, it all comes down to running a simple:

ssh root@CONTAINER_IP

And there you are, right into the container to do what you want.

Summary

In this article, you learned:

  • The main difference between a Docker container and a virtual machine

  • Why SSH isn’t the preferred choice when it comes to running commands within your containers and what to do instead

  • What it takes to get inside the container using SSH if you need to

I hope you have a clear understanding of how Docker works and how you can get the best out of it.

This post was written by Mauro Chojrin. Mauro helps PHP developers hone their craft through his trainings, books, workshops and other tools. He's been in the IT industry since 1997 and has held roles such as developer, architect and leader of technical teams. Mauro also likes to write and vlog.

Stay up to date

We'll never share your email address and you can opt out at any time, we promise.