SSH in Docker

Published onby Iron

Docker has revolutionized how we build, ship, and run applications by allowing us to package everything into containers. But what if you need to SSH into a Docker container? While Docker’s design generally discourages this, there are situations where it might be useful.

Let's Dive In!

Table of Contents

Why You (Usually) Don’t Need SSH in Docker

Docker is all about simplicity and efficiency. Containers are designed to be lightweight and isolated, running only the necessary processes for your application. Because of this, Docker doesn’t encourage using SSH inside containers.

Instead, Docker provides commands like "docker exec", which let you run commands inside a running container without the need for SSH.

So, why would you still consider using SSH?

Here are some scenarios where SSH might be handy:

  • Complex debugging: When troubleshooting intricate issues, a full SSH session gives you more control. You can navigate the filesystem, inspect files, and run multiple commands in an environment you’re familiar with.

  • Legacy workflows: If your team has workflows built around SSH, transitioning away from it might be challenging. Setting up SSH in Docker can be a quick solution to maintain these workflows without disrupting productivity.

  • Remote container access: If you need to securely access a container on a remote server, SSH provides a straightforward and secure method.

These scenarios are exceptions rather than the norm. For most cases, Docker’s built-in commands, like "docker exec", will meet your needs.

Setting Up SSH in a Docker Container

If you’ve decided that SSH is necessary, here’s how to set it up in a Docker container step by step.

  1. Create a Dockerfile

    Start by creating a "Dockerfile" that includes SSH setup. Here’s an example using Ubuntu:
    FROM ubuntu:20.04
    
    # Install OpenSSH Server
    
    RUN apt-get update && apt-get install -y openssh-server
    
    # Create directory for the SSH daemon
    
    RUN mkdir /var/run/sshd
    
    # Set a root password (change this for production use!)
    
    RUN echo 'root:rootpassword' | chpasswd
    
    # Enable SSH to accept root login (not recommended for production)
    
    RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
    
    # Expose port 22
    
    EXPOSE 22
    
    # Start SSH service
    
    CMD ["/usr/sbin/sshd", "-D"]
    
    This "Dockerfile" installs the OpenSSH server, sets up SSH for root access, and starts the SSH service when the container runs. Note that allowing root login is not recommended for production environments due to security risks.
  2. Build the Docker Image

    Once your "Dockerfile" is ready, build the Docker image:
    docker build -t ssh-docker-image .
    
    This command creates an image named "ssh-docker-image" from your "Dockerfile".
  3. Run the Docker Container

    After building the image, run a container from it:
    docker run -d -p 2222:22 ssh-docker-image
    
    This command starts the container in detached mode and maps port 2222 on your host machine to port 22 in the container.
  4. SSH into Your Container

    Finally, to access your container via SSH, run:
    ssh root@localhost -p 2222
    
    When prompted, enter the password you set earlier (in this case, "rootpassword"). And there you go! You’re now SSHed into your Docker container.

The Downsides of Using SSH in Docker

While SSH in Docker can be convenient, it comes with trade-offs:

  • Increased Image Size: Installing SSH and its dependencies increases the size of your Docker image, which can slow down builds, pushes, and pulls.

  • Security Risks: Running an SSH server in your container opens up potential security vulnerabilities, especially if you’re allowing root access. It’s essential to secure your SSH setup to prevent unauthorized access.

  • Breaks Immutability: One of Docker’s core principles is immutability—containers should be stateless and reproducible. SSH access allows for changes that aren’t reflected in the Dockerfile, potentially making your environments harder to replicate.

These drawbacks highlight why Docker doesn’t encourage the use of SSH by default. However, if you find yourself in a situation where SSH is needed, there are ways to mitigate these risks.

Best Practices When Using SSH in Docker

If SSH is necessary, here are some best practices to follow:

  • Use Non-Root Users: Avoid logging in as root. Create a non-root user and set up SSH to allow this user to log in. This reduces the risk of accidental changes to critical system files.

    Update your "Dockerfile" like this:
    RUN useradd -m -s /bin/bash user && echo 'user:userpassword' | chpasswd
    
  • Disable Root Login: To further enhance security, disable root login after setting up your non-root user.

    RUN sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
    
  • Use SSH Keys: Instead of relying on passwords, use SSH keys for authentication. This method is more secure and eliminates the need to manage passwords.

    RUN mkdir /home/user/.ssh && chmod 700 /home/user/.ssh
    
    COPY id_rsa.pub /home/user/.ssh/authorized_keys
    
    RUN chmod 600 /home/user/.ssh/authorized_keys && chown -R user:user /home/user/.ssh
    
  • Monitor SSH Access: Use tools like Fail2ban to monitor SSH access and ban IPs showing suspicious behavior. This helps protect your container from brute-force attacks.

  • Automate the Setup: If you need SSH in multiple containers, automate the setup using scripts or configuration management tools like Ansible or Puppet. This ensures consistency across your environments.

Alternatives to SSH in Docker

Before resorting to SSH, consider these alternatives, which might better align with Docker’s philosophy:

  1. docker exec The "docker exec" command lets you run commands inside a running container without needing SSH. It’s the most straightforward method for interacting with your container:

    docker exec -it <container_id> /bin/bash
    
    This command opens a Bash shell inside the container, providing similar functionality to SSH without the overhead.
  2. Docker Attach

    The "docker attach" command attaches your terminal to the container’s main process, allowing you to interact with it directly:
    docker attach <container_id>
    
  3. Docker Entrypoint Scripts

    Modify your entrypoint script to accept specific debugging or administrative commands, allowing you to pass commands directly when starting the container:
    docker run mycontainer debug
    
  4. Docker APIs Docker’s REST API allows you to interact with containers programmatically, making it possible to automate tasks or integrate Docker with other systems.

Final Thoughts

Using SSH in Docker containers is like wielding a powerful tool—use it wisely. While Docker provides plenty of ways to interact with containers, SSH can still be useful in specific scenarios, especially for debugging and remote access.

However, with great power comes great responsibility. Always consider the security implications and stick to best practices to minimize risks. And, whenever possible, use Docker’s built-in tools to keep your containers lightweight, secure, and consistent.

And hey, if you’re managing a lot of containers or Dockerized applications, it might be time to think about automating and simplifying your setup. After all, why do manually what you can automate?

We host UniFi Controllers in the Cloud

Are you ready to take your UniFi Network to the next level? Deploy a UniFi Cloud Controller in minutes and manage your network from anywhere.

Deploy Now

Free tier available

Get the best support

Join 1660+ customers

No credit card required