How to SSH into a Docker Container

published
July 5, 2024
TABLE OF CONTENTS

When you're working in a corporate environment, there’s often a lot of moving parts. You might have multiple services running in various containers, all working together. While Docker provides a robust set of commands, there are moments when direct access to a container can save a ton of time.

Why would you SSH into a Docker container?

Connecting to a Docker container via SSH simplifies many networking tasks, saving you time. More than just a convenience, it’s a practical way to streamline workflows, aid in troubleshooting, enhance collaboration, and even align with corporate security measures.

An SSH (Secure Shell) lets you administer systems securely and transfer files over unsecured systems. A Docker container, on the other hand, is a software package that contains your application’s code, its dependencies, filesystem, and environment settings in a lightweight and standalone form that makes it easier to run. 

Debugging 

Imagine debugging a production issue. Logs aren't always enough. You might need to poke around the container's file system, check running processes, or run some ad-hoc commands. 

With SSH, you can get inside the container and interact with it just like you would with a regular server. It’s like opening the hood of a car to see what’s going on with the engine.

Configuring software

When you’re installing or configuring software directly inside a container, you sometimes need to test configurations or dependencies interactively. While you can rebuild the image repeatedly, it’s tedious and slow. SSH lets you tweak things on the fly, test them, and only update the Dockerfile once you know everything works.

Team collaboration

If you're in a team, having SSH access standardized can help with collaboration. You can guide a colleague through a process, or they can take over and troubleshoot an issue directly without miscommunications on what commands to run.

Enforcing security policies

In enterprise networks, security policies can also play a significant role. Sometimes setting up SSH is the only way to comply with these policies while maintaining direct access to containers. 

For example, IT might already have monitoring and access control systems based around SSH, making it easier to integrate Docker containers into existing infrastructure.

Security considerations when SSHing into a Docker Container

Use strong, unique SSH key

When SSHing into a Docker container within corporate networks, security is paramount. One of the first things you need to consider is the SSH key management. Always use strong, unique SSH keys. 

Avoid using password-based authentication as it's more vulnerable to brute-force attacks. Ensure that your private keys are securely stored and never shared. For instance, you can use tools like `ssh-agent` to manage your keys more securely on your local machine.

Restrict SSH access

Only authorized users should have SSH access to Docker containers. Use network policies to limit which IP addresses can access your container over SSH.

For example, configure your firewalls and security groups to allow SSH connections only from trusted IP addresses. This reduces the attack surface and helps prevent unauthorized access.

Keep your Docker images up to date

Using outdated images can expose you to known vulnerabilities. Regularly update your images and rebuild your containers to include the latest security patches. Tools like Dependabot or Snyk can help automate this process by notifying you of vulnerabilities in your dependencies.

Monitor and log SSH access

Implement logging to track who is accessing your containers and when. Use logging tools like `syslog` or centralized logging solutions such as the ELK stack (Elasticsearch, Logstash, and Kibana) to collect and analyze SSH logs. 

For example, you can configure your Docker container to send SSH access logs to a centralized logging server for easier monitoring and auditing.

Use a bastion host as an intermediary

Instead of allowing direct SSH access to your Docker containers, use a bastion host as an intermediary. This adds an additional layer of security by concentrating SSH access in a single, hardened entry point. Ensure that the bastion host itself is secure, with minimal software installed and regularly updated.

Encrypt sensitive data

Any data transmitted over SSH should be encrypted. This is inherently handled by the SSH protocol, but ensures that your SSH server configuration enforces strong encryption standards. 

Avoid deprecated algorithms and ciphers. For instance, configure your SSH server to use only the strongest algorithms, like `aes256-gcm` for encryption and `sha2-512` for data integrity.

Don’t expose SSH in your Dockerfile

Hardcoding SSH server configurations or keys in your Dockerfile can lead to security risks. Instead, handle these configurations at runtime using environment variables or Docker secrets. This way, sensitive information is not stored in your image and is less likely to be exposed.

Remove SSH access when it’s not needed

If you don't need to SSH into your containers, it's best to disable SSH access altogether. This minimizes potential entry points for attackers. For troubleshooting and management, consider using Docker exec for command-line access instead of SSH, as it provides a more controlled and secure way to interact with your containers.

How to SSH into a Docker container

Step 1: Create a Dockerfile

Creating a Dockerfile is straightforward. The first step is to choose a base image. This is the foundation of your Docker image. It typically includes an operating system and essential tools.

In our working example, we will use the official Node.js image. You will specify Node version 14 as your base. Here’s how you start your Dockerfile:

dockerfile
FROM node:14

‍

This command tells Docker to use Node.js version 14 as the base image for your application. It's like setting up the initial environment that my application will run on.

Next, set a working directory. This helps structure your Docker image and specifies where the application code will reside inside the container. Do this by adding the following line to the Dockerfile:

dockerfile
WORKDIR /app

With these two commands, you have created a solid foundation. Your Docker image now has Node.js installed and a working directory set up to /app. This setup makes it easier to manage and navigate through my application’s files when I build and run the Docker container.

Remember, a well-defined base image and working directory are crucial. They ensure consistency and structure in your Docker container, which is essential for smooth application development and deployment.

Step 2: Build the Docker Image

With the Docker file you created above, you will now install SSH. In the Dockerfile, add a few lines to update the package list and install the OpenSSH server:

Dockerfile
RUN apt-get update \
    && apt-get install -y openssh-server

You also need to create a directory for the SSH daemon to run in. This ensures that the SSH service has the necessary environment:

Dockerfile
RUN mkdir /var/run/sshd

Now, set a root password. This step is crucial for SSH access. For simplicity, we'll use "root" as the password:

Dockerfile
RUN echo 'root:root' | chpasswd

Security is important, especially in a corporate network. To help with that, tweak the SSH configuration to allow root login. Add the following lines to the Dockerfile:

Dockerfile
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config

You need to open port 22 for SSH connections. In Docker, you specify that using the `EXPOSE` instruction:

Dockerfile
EXPOSE 22

Finally, you need a command to start the SSH service when the container runs. Add this to the end of your Dockerfile:

Dockerfile
CMD ["/usr/sbin/sshd", "-D"]

Save the Dockerfile. You now have all the instructions needed to build the Docker image. To build it, open your terminal, navigate to the directory containing the Dockerfile, and run:

sh
docker build -t my-ssh-image.

This command tells Docker to build an image using the Dockerfile in the current directory and tag it as `my-ssh-image`. The build process will take a few moments. Once it's done, you'll have a Docker image ready for SSH access.

Step 3: Run the Docker container

Before you spin up your container, ensure the Docker image is ready. We are assuming you’ve either pulled an image from a repository or built your own. For this example, let's say you are using the Ubuntu image. First, pull the Ubuntu image by running:

docker pull ubuntu

Once you have the image, you can run the Docker container. This is where the magic starts. To run the container, use the following command:

docker run -d -P --name my_ubuntu_container ubuntu

Here’s how it breaks down: `-d` runs the container in detached mode, so it runs in the background. The `-P` flag tells Docker to map any required network ports inside the container to our host system. `--name` assigns a name to the container, in this case, `my_ubuntu_container`.

After running this command, the container will start up and run in the background. You can verify it's running with:

docker ps

This will list all active containers, and you should see `my_ubuntu_container` listed there. If you want to get into the container to check things out, you can use:

docker ps

This command opens up an interactive terminal inside the running container. Now you’re inside the container, and you can run commands just like you would on any other Linux system. It's a pretty cool experience if you haven't done it before.

Since our goal is to SSH into the Docker container, there's an extra step. We need to install an SSH server inside the container. While inside the container, update the package list and install `openssh-server`:

apt-get update && apt-get install -y openssh-server

Once it's installed, we need to start the SSH service:

service ssh start

Next, we need to set a password for the root user, so run:

passwd

Enter a password when prompted. Now, we need to find the port on which SSH is running. Open another terminal window and run:

docker port my_ubuntu_container 22

This will show you the mapped port on your host. For example, it might show `0.0.0.0:32768`.

At this point, you’re ready to SSH into your container from your host machine. Use the port provided in the previous step:

ssh root@localhost -p 32768

Enter the password you set earlier, and you should be in. It’s as simple as that. Now you have SSH access to your Docker container running within your corporate network.

Step 4: Connect to the Docker Container via SSH

So, you have done all the groundwork, and now it's time to connect to your Docker container via SSH. First, ensure you know the container's ID or name. You can get this info by running `docker ps` in your terminal. This command lists all your running containers. You'll see details like container ID, names, status, and more.

Let's say the container you're targeting has an ID of `abc123def456`. Next, you'll want to start an SSH session. If you've already set up SSH as we discussed in earlier steps, this should be straightforward. Open your terminal and use the following command:

ssh root@<container-ip-address> -p <port>

Replace `<container-ip-address>` with the actual IP address of your Docker container. Typically, you can find this by running `docker inspect abc123def456` and looking for the `IPAddress` field under the `NetworkSettings` section. Let's assume the IP address you found is `172.17.0.2`, and you configured SSH to listen on port `2222`. The command would then look like this:

ssh root@172.17.0.2 -p 2222

Hit Enter, and if everything is set up correctly, it will prompt you for the root password. Enter the password you configured earlier. Voila! You should now be inside the Docker container via SSH.

You might run into some network restrictions, especially in a corporate environment. Firewalls or security groups might block your SSH traffic. If you encounter connection issues, double-check your network settings and ensure the necessary ports are open.

Also, keep in mind this SSH connection is not persistent. If you restart the Docker container, you'll need to reconnect using the same steps. It might seem tedious, but it's essential for maintaining secure and controlled access.

Alright, you're in! Now you can manage your Docker container as if it were a standalone Linux server. You can run commands, edit files, and even install additional software if needed. Just remember to exit the SSH session when you're done to maintain good security practices.

Step 5: Configuring SSH Keys (Optional)

Although it’s optional, configuring SSH keys will make your life easier and will save you time. Instead of typing your password every time you SSH into the Docker container, you can use SSH keys for seamless access.

First, you need to generate an SSH key pair on our local machine. If you don’t already have one, open your terminal and type:

sh
ssh-keygen -t rsa -b 2048

Follow the prompts. You can accept the default file location and leave the passphrase empty if you prefer quicker access.

Once your key pair is ready, you'll find two files: `id_rsa` (private key) and `id_rsa.pub` (public key). The private key stays with you. Never share it. The public key, however, is meant to be shared. We'll now copy this public key to our Docker container.

First, make sure your container is running. You can check this with:

sh
docker ps

Take note of the container ID or name. Now, use `docker exec` to access the container and set up the authorized keys:

sh
docker exec -it <container_id_or_name> /bin/bash

Once inside the container, let's create a `.ssh` directory in the home folder if it doesn't exist:

sh
mkdir -p ~/.ssh
chmod 700 ~/.ssh

Now, we need to add our public key to the `authorized_keys` file. You can either create it if it doesn’t exist or append to it if it does. Open or create `authorized_keys` with your favorite text editor inside the container:

sh
nano ~/.ssh/authorized_keys

Back on your local machine, you need to copy the content of your `id_rsa.pub` file. Open it with:

sh
cat ~/.ssh/id_rsa.pub

Copy the entire contents of this file and paste it into the `authorized_keys` file open in the container. Save and exit the editor. Make sure the permissions are set correctly:

sh
chmod 600 ~/.ssh/authorized_keys

Exit the container by typing `exit` or pressing `Ctrl+D`. Now, you should be able to SSH into your Docker container without being prompted for a password.

Just use the following command from your local machine:

sh
ssh -i ~/.ssh/id_rsa username@container_ip

Replace `username` and `container_ip` with your actual user and IP address of the Docker container. This simplifies your workflow tremendously, especially when working within a corporate network where security and convenience are critical.

Best practices to follow when SSHing into a Docker Container

Use key-based authentication

Key-based methods are more secure since they eliminate the need for passwords, which can be easily compromised. Additionally, always limit SSH access to necessary users and use non-default usernames. 

For instance, instead of using the default "root" user, create a new user by adding a RUN command to your Dockerfile like this: `RUN useradd -m newuser && echo "newuser:newpassword" | chpasswd`. This will create a user with a home directory and a password.

Properly configure your SSH server for security

Ensure your SSH server inside the container is properly configured for security. Edit the `sshd_config` file to disable root login and set other security parameters. 

Also, it's crucial to monitor and log SSH access. Use tools like `fail2ban` to protect against brute-force attacks. Then, configure `fail2ban` to monitor SSH login attempts, ensuring you’re notified and able to respond to suspicious activities.

Minimize the SSH server’s footprint in your container

Use lightweight base images and only install essential packages needed for SSH access. This keeps the image size down and reduces potential attack vectors.

Keep your containers updated. 

Regularly pull the latest secure images and rebuild your Docker containers. If vulnerabilities are discovered in the SSH server, you'll want to update them promptly.

By following these best practices, you can ensure a more secure and efficient SSH experience within Docker containers. Remember, the goal is to minimize attack surfaces and ensure that only authorized users can gain access.

More posts

GET STARTED

A WireGuard® VPN that connects machines securely, wherever they are.
Star us on GitHub
By clicking “Accept”, you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts. View our Privacy Policy for more information.