← cd ../blog

Connect to Docker Container on a Remote Server over SSH

Enable SSH tunneling from a remote Docker container and connect directly with VS Code.

Contents

The problem

↑ back to contents ↑

I work a lot with Machine Learning and Deep Learning algorithms wrote in Python. Because of the various framework available (such asPyTorch,Tensorflow,RAPIDS,TPOT …) I useDockera lot, usually along with aJupyter-enabled image (see my other article if you are interested) which allows me to do all the prototyping I need in a fast and clean way. It is common to put such containers on a remote server with the required hardware (mostly GPUs) rather than developing on the local machine.

Sometimes, though, JupyterLab is not enough, and some good oldVSCodecoding is the best thing I can hope for, especially when dealing with Python packages developmentwhich I will then have to test with Jupyter. And here we encounter our problem:

VSCode does not allow to connect to a remote container on a remote server. In fact, it just allows you to connect to a remote machine or to your local containers. If we attach VSCode to our remote server:VSCode Attach via SHHand then we try to attach VSCode to a running container on the remote server:VSCode Attach via Dockerwe get the following error:VSCode Error

The best solution, in this case, is to enable SSH tunneling directly from the Docker container, allowing VSCode to seamlessly connect to the container as if it was a standalone remote machine:

SSH Tunnel

Mounting a Docker container

↑ back to contents ↑

Let’s use the Jupyter-enabled image we mentioned before as the base image for our container. After pulling it fromdockerhub:

docker pull davidelanz/jupyter

we can mount it exposing the container’s Jupyter port 8888 on, for example, my.server.local:2345 using the option --publish <SERVER-PORT>:<CONTAINER_PORT> (or -p), which publish a container’s port (8888) to the server’s specified one (2345):

docker run\ -p 2345:8888 \ --name my-jupyter-workspace \ davidelanz/jupyter

Now we can access Jupyter at my.server.local:2345, but can’t attach VSCode nor connect via SSH to my-jupyter-workspace container.

Mounting a Docker Container with SSH enabled

↑ back to contents ↑

In order to enable the SSH tunnel, we first have to expose the container’s SSH port 22 to a server port. In our case, we will use my.server.local:2344:

docker run\ -p 2344:22 \ -p 2345:8888 \ --name my-jupyter-workspace \ davidelanz/jupyter

Now, we have to enter the container. First, we enter the server via SSH:

ssh my.server.local

Then, we attach to the container with:

docker container exec -it my-jupyter-workspace /bin/bash

Now we are finally inside our running container, and we can install a SSH server directly in it:

apt-get update && \ apt-get upgrade -y && \ apt-get -y install openssh-server && \ mkdir -p /var/run/sshd && \ service ssh start

If it was not already set, we have to change then the root’s password in order to log in during SSH authentication process:

echo "root:<NEW_PASSWORD>"|chpasswd

Now we are able to start the SSH server process via service ssh restart, but we still can’t log in. In fact, we have to authorize SSH connection with a root account. In order to do that, we need to go to /etc/ssh/sshd_config and modify the optionPermitRootLogin from prohibit-password to yes. Moreover, if it is not commented, comment the UsePam yes line. We can open the text file with GNU nano:

apt-get install nano && nano /etc/ssh/sshd_config
BeforeAfter
# PermitRootLogin prohibit-passwordPermitRootLogin yes
UsePAM yes#UsePAM yes

Then we just need to restart our ssh process:

service ssh restart

Connect via command line

↑ back to contents ↑

Now we can connect via command line at ports 2344 of docker server using the address of the remote server (my.address.local) specifying the port in SSJ with -p <port>:

ssh -p 2344 my.address.local

Connect via VSCode

↑ back to contents ↑

We can now add my.address.local:2344 to the SSH configuration file:

Host my-remote-container HostName my.address.local User root Port 2344 ForwardAgent yes

and we can use the VSCode Remote Explorertool to attach VSCode directly to the container running on the remote server.