Adaptive Logo
Adaptive Logo
Get Started
Tutorial6 min read

How to SSH into Docker Container?

RatinMay 19, 2023
How to SSH into Docker Container?

How to SSH into Docker Container?

Docker containers can simplify the deployment of small services or monoliths. Docker, mostly, provides a lightweight and portable solution that can run on any system. But sometimes either to debug or fix a mess, one might have to access the container directly. While containers are designed to be self-contained and isolated, there are ways to access the container’s shell. To know more about docker, you can read here.

Can you ssh into a docker container? Yes, but should you?

That will depend on the constraint levied on your system. Each solution has its mix of security and ease of access. In this article, we will cover 3 ways to ssh into a docker container.

Accessing a docker container, using docker exec

The easiest way to access a live container would be to use docker exec.

$ docker exec -it <container-id> /bin/bash
root@<container-id>:/#

# If you do not know the container id your container
# list out the running container like so:
$ docker container ls
CONTAINER ID   IMAGE           COMMAND                  CREATED      STATUS             PORTS                                       NAMES
85d84ef9dc32   postgres:11.3   "docker-entrypoint.s…"   2 days ago   Up About an hour   0.0.0.0:5432->5432/tcp, :::5432->5432/tcp   article_test_1

This is the recommended method for accessing the container. It's secure, simple, and traceable via Docker logs. However, in some cases, a container may disable access via bash or sh, or you may not have access to the docker-host. In such situations, you can always fall back on the traditional method of using ssh.

Accessing a docker container, using SSH

While docker exec is the recommended way, SSH also has its place. Access via SSH is necessary for testing infrastructure automation or provisioning scripts before running them on production. There are many ways to authenticate with an SSH server, including simple username-password, public-key authentication, Kuberos, and two-factor authentication. We will cover two of these methods:

1. Using Username and Password

If the ssh-agent in your docker container, accepts password access then ssh access to the container is as simple as:

# `remotehost` is the host/ip of your docker container instance
$ ssh <username>@<container-ip>

You can find an example Dockerfile that runs an ssh-agent with a specified username/password

FROM ubuntu:latest

RUN apt-get update && \
    apt-get install -y openssh-server sudo && \
    rm -rf /var/lib/apt/lists/*

RUN useradd -rm -d /home/ubuntu -s /bin/bash -g root -G sudo -u 1000 test && \
    echo 'test:supersecretpassword' | chpasswd

RUN mkdir /var/run/sshd

EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

You can access this container using ssh like:

$ docker run -p 2023:22 -d sshtestcclear
$ ssh -p 2023 test@localhost
test@localhost's password: ********
# you will be prompted to enter password for user `test`
# `supersecretpassword`

If the container is not deployed on your localhost, you can query its IP using the following command:

$ docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container_id>
172.18.0.2

2. Using Public Key

You will need to generate a ssh key pair. The public key will be added to the container and the private key would be used by you to authenticate your identity to the container’s ssh-agent. Let’s suppose the names of those are, key.pub and key (to learn more about generating these keys check this article).

FROM alpine:latest

RUN apk add --update --no-cache openssh
RUN addgroup -S test_user_group && adduser -S -G test_user_group test_user

RUN mkdir -p /root/.ssh

# Build image with public key added to authorized_keys file
# of the container
COPY key.pub ./root/.ssh/authorized_keys
# Restrict access for keys to owners of file only
RUN chown test_user:test_user_group /root/.ssh/authorized_keys && chmod 600 /root/.ssh/authorized_keys

RUN ssh-keygen -A

EXPOSE 22

# log to stderr using "-e"
CMD ["/usr/sbin/sshd","-D"]
# build the docker image
$ docker build -t ssh-agent-in-docker .
# run the docker image, exposing port 2023 on host to ssh port in container
$ docker run -p 2023:22 ssh-agent-in-docker
# now you can access the container using ssh by using private key
$ ssh -i /location/to/key -p 2023 test_user@localhost

But what if you don’t have access to docker-daemon and the container is running on a network not exposed to you?

Accessing a docker container, via another docker container

Imagine a situation where you want to access a container running on your home lab from an airport or another location. If you lack a public and static IP for your home network, and the airport Wi-Fi network is not part of your home network, you cannot access the container from outside without a complex private network or VPN setup. Exposing your entire home network via a public IP would also attract negative attention.

Instead of directly exposing the external interface of your home network, you can use a public server as a bridge between you and the container running on your home network. This is because a public server will have a public IP that can be accessed from anywhere.

An example of this is rsshd, which provides a minimal implementation of this. To use it, follow these steps:

1. On a public server (e.g. server.public), run the Docker container

$ docker run -it --rm \
    -p 2222:22 \
    --name rsshd \
    -p 10000-10100:10000-10100 \
    -e PASSWORD=secret \
    -v /opt/keys/host:/etc/ssh/keys \
    -v /opt/keys/clients:/root/.ssh \
    efrecon/rsshd

chpasswd: password for 'root' changed
Server listening on 0.0.0.0 port 22.
Server listening on :: port 22.

2. Creating a Reverse Tunnel

This will run bridge on your public server. To access the container remotely via the reverse tunnel, you would first need to create a reverse tunnel on it, by:

$ ssh -fN -R 10000:localhost:22 -p 2222 root@server.public

3. SSH access via the reverse tunnel

Now a reverse tunnel (on the port) exists from the container (in the home network) with the container/bridge running on the public server. You can now just ssh to the public server on the port.

$ ssh -p 10000 root@server.public
The authenticity of host '[server.public]:10000 ([::1]:2222)' can't be established.
ED25519 key fingerprint is SHA256:HagFEp3Lxjk4DY/8Xm3gRuMvuYiXchlNZSWKXLGfJlU.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[server.public]:2222' (ED25519) to the list of known hosts.
root@localhost's password:
Welcome to Alpine!

The Alpine Wiki contains a large amount of how-to guides and general
information about administrating Alpine systems.
See <http://wiki.alpinelinux.org/>.

You can setup the system with the command: setup-alpine

You may change this message by editing /etc/motd.

Note: If you manage your container using Podman or Portainer, you can find more information about their exec functions here and here, respectively.

Accessing docker containers using Adaptive

As teams get bigger, accessing containers within private networks can become increasingly challenging due to heightened access restrictions. It's possible to encounter situations where direct access to the network or the necessary keys to connect to a container is limited. Adaptive makes it easier to access containers in all such cases.

With Adaptive's JIT Access Management platform, you can SSH or access a container's shell using a simple command:

$ adaptive connect <endpoint_name>

where <endpoint_name> is an Endpoint connected to your Container or VM.

Enterprise Grade
A Unified Approach to Data Security and Privileged Access
Agentless Architecture
Zero Network Reconfiguration
Deploy in Cloud or On-Prem