- Protect the Docker daemon socket
- Use SSH to protect the Docker daemon socket
- SSH Tips
- Use TLS (HTTPS) to protect the Docker daemon socket
- Create a CA, server and client keys with OpenSSL
- Secure by default
- Other modes
- Daemon modes
- Client modes
- Connecting to the secure Docker port using curl
- Using SSH Connections in Docker Contexts
- Couple of Extra Tips
- Why connect to your remote machines this way?
- Name already in use
- vscode-docs / docs / containers / ssh.md
- Connect to remote Docker over SSH
- Set up SSH Tunneling
Protect the Docker daemon socket
Estimated reading time: 10 minutes
By default, Docker runs through a non-networked UNIX socket. It can also optionally communicate using SSH or a TLS (HTTPS) socket.
Use SSH to protect the Docker daemon socket
The given USERNAME must have permissions to access the docker socket on the remote machine. Refer to manage Docker as a non-root user to learn how to give a non-root user access to the docker socket.
The following example creates a docker context to connect with a remote dockerd daemon on host1.example.com using SSH, and as the docker-user user on the remote machine:
After creating the context, use docker context use to switch the docker CLI to use it, and to connect to the remote engine:
Use the default context to switch back to the default (local) daemon:
Alternatively, use the DOCKER_HOST environment variable to temporarily switch the docker CLI to connect to the remote host using SSH. This does not require creating a context, and can be useful to create an ad-hoc connection with a different engine:
SSH Tips
For the best user experience with SSH, configure
/.ssh/config as follows to allow reusing a SSH connection for multiple invocations of the docker CLI:
Use TLS (HTTPS) to protect the Docker daemon socket
If you need Docker to be reachable through HTTP rather than SSH in a safe manner, you can enable TLS (HTTPS) by specifying the tlsverify flag and pointing Docker’s tlscacert flag to a trusted CA certificate.
In the daemon mode, it only allows connections from clients authenticated by a certificate signed by that CA. In the client mode, it only connects to servers with a certificate signed by that CA.
Using TLS and managing a CA is an advanced topic. Please familiarize yourself with OpenSSL, x509, and TLS before using it in production.
Create a CA, server and client keys with OpenSSL
Note: Replace all instances of $HOST in the following example with the DNS name of your Docker daemon’s host.
First, on the Docker daemon’s host machine, generate CA private and public keys:
Now that you have a CA, you can create a server key and certificate signing request (CSR). Make sure that “Common Name” matches the hostname you use to connect to Docker:
Note: Replace all instances of $HOST in the following example with the DNS name of your Docker daemon’s host.
Next, we’re going to sign the public key with our CA:
Since TLS connections can be made through IP address as well as DNS name, the IP addresses need to be specified when creating the certificate. For example, to allow connections using 10.10.10.20 and 127.0.0.1 :
Set the Docker daemon key’s extended usage attributes to be used only for server authentication:
Now, generate the signed certificate:
Authorization plugins offer more fine-grained control to supplement authentication from mutual TLS. In addition to other information described in the above document, authorization plugins running on a Docker daemon receive the certificate information for connecting Docker clients.
For client authentication, create a client key and certificate signing request:
Note: For simplicity of the next couple of steps, you may perform this step on the Docker daemon’s host machine as well.
To make the key suitable for client authentication, create a new extensions config file:
Now, generate the signed certificate:
After generating cert.pem and server-cert.pem you can safely remove the two certificate signing requests and extensions config files:
With a default umask of 022, your secret keys are world-readable and writable for you and your group.
To protect your keys from accidental damage, remove their write permissions. To make them only readable by you, change file modes as follows:
Certificates can be world-readable, but you might want to remove write access to prevent accidental damage:
Now you can make the Docker daemon only accept connections from clients providing a certificate trusted by your CA:
To connect to Docker and validate its certificate, provide your client keys, certificates and trusted CA:
Run it on the client machine
This step should be run on your Docker client machine. As such, you need to copy your CA certificate, your server certificate, and your client certificate to that machine.
Note: Replace all instances of $HOST in the following example with the DNS name of your Docker daemon’s host.
Note: Docker over TLS should run on TCP port 2376.
Warning: As shown in the example above, you don’t need to run the docker client with sudo or the docker group when you use certificate authentication. That means anyone with the keys can give any instructions to your Docker daemon, giving them root access to the machine hosting the daemon. Guard these keys as you would a root password!
Secure by default
If you want to secure your Docker client connections by default, you can move the files to the .docker directory in your home directory — and set the DOCKER_HOST and DOCKER_TLS_VERIFY variables as well (instead of passing -H=tcp://$HOST:2376 and —tlsverify on every call).
Docker now connects securely by default:
Other modes
If you don’t want to have complete two-way authentication, you can run Docker in various other modes by mixing the flags.
Daemon modes
- tlsverify , tlscacert , tlscert , tlskey set: Authenticate clients
- tls , tlscert , tlskey : Do not authenticate clients
Client modes
- tls : Authenticate server based on public/default CA pool
- tlsverify , tlscacert : Authenticate server based on given CA
- tls , tlscert , tlskey : Authenticate with client certificate, do not authenticate server based on given CA
- tlsverify , tlscacert , tlscert , tlskey : Authenticate with client certificate and authenticate server based on given CA
If found, the client sends its client certificate, so you just need to drop your keys into
/.docker/
Connecting to the secure Docker port using curl
To use curl to make test API requests, you need to use three extra command line flags:
Using SSH Connections in Docker Contexts
Edit (2019-09-03): Added comments for the different ways to use the context commands and an example of using the DOCKER_CONTEXT env var
Docker Context is a new feature (as of 19.03) that allows you to change what Docker engine you are working against without needing to use the DOCKER_HOST environment variable. Since it’s persistent on the local machine, switching between contexts is quite easy.
PRE-REQ NOTICE: The remote server you are connecting to needs to be running Docker 18.09 or later. In order to use contexts, your local machine needs to be using Docker 19.03 or later.
To connect over SSH, create the context by doing the following:
Then, to use the context, use the normal context commands:
Couple of Extra Tips
- Docker will use your local SSH agent, so any keys loaded into your agent will be accessible for the connection
- Since the local SSH agent is being used, you can shorten the context by putting username, port, and other config into your
Why connect to your remote machines this way?
A couple of ideas:
- You most likely already have SSH setup, so why not leverage it?
- You don’t have to setup Docker to listen on a publicly accessible port, which becomes one more thing to watch and monitor. If you do this, pleasesecure the daemon socket.
- If there ever were a vulnerability in the API Docker exposes, you have an additional layer of security by not having it exposed directly on the internet. An attacker would still need to get on the remote server to take advantage of it.
Name already in use
vscode-docs / docs / containers / ssh.md
- Go to file T
- Go to line L
- Copy path
- Copy permalink
Copy raw contents
Copy raw contents
Connect to remote Docker over SSH
We recommend using the Visual Studio Code Remote — SSH extension to connect to a remote machine running Docker engine. You can use the Remote — SSH and Dev Containers extensions together. You may review the steps in the Dev Containers documentation.
It is also possible to connect to the remote Docker engine directly using SSH tunneling, which you can read more about below.
Set up SSH Tunneling
Use ssh-keygen or similar to get and configure a public/private key pair for SSH authentication. Password authentication is not supported by Docker and not possible with a DOCKER_HOST -based configuration. If a key pair has already been set up, it can be used.
Configure ssh-agent on the local system with the private key file produced above.
Windows (OpenSSH): The latest version(s) of Windows 10 include OpenSSH by default. There is a Windows service, ssh-agent that is disabled by default, and needs to be re-enabled and set to automatic start. From an admin PowerShell prompt, run Set-Service ssh-agent -StartupType «Automatic» and Start-Service ssh-agent . Then, do ssh-add .
Windows (Pageant): You can use Pageant instead of OpenSSH, in which case it is necessary to set the environment variable SSH_AUTH_SOCK=pageant . Making that a user or system environment variable will be easiest.
Linux: ssh-agent is present by default. Do ssh-add . Ubuntu was tested; you might have different results on other distributions.
macOS: ssh-agent is present by default, but ssh-add does not persist across logins. Do ssh-add . We recommend configuring VS Code to run this command on terminal startup with terminal.integrated.profiles.osx args value or otherwise configuring a startup script. You can also manually run that command each login.
Verify that your identity is available to the agent with ssh-add -l . It should list one or more identities that look something like 2048 SHA256:abcdefghijk somethingsomething (RSA) . If it does not list any identity, you will not be able to connect. Also, it needs to have the right identity. The Docker CLI working does not mean that the Explorer window will work. The Explorer window uses dockerode (which in turn uses ssh2), whereas the Docker CLI uses the ssh command, and benefits from an automatically inferred configuration.
Create a Docker context that points to the remote machine running Docker. Use ssh://username@host:port as the Docker endpoint (replace «host» with your remote machine name, or the remote machine IP address). Issue the following command from terminal window:
Always include the user name in the Docker endpoint address, even if it is the same as the local user name. If you omit the port, it defaults to 22.
Use the Command Palette ( kb(workbench.action.showCommands) ) to issue the Docker Context: Use command to activate the Docker context pointing to the remote machine. This command causes both VS Code and Docker CLI to use the remote machine context.
It is recommended to change the refresh rate to something longer than the default with the docker.explorerRefreshInterval setting. The connection over SSH is slow, and it can result in trying to refresh again before the previous refresh even finished. We recommend at least 3000 ms.
The «host» part in the Docker endpoint string ( ssh://username@host:port ) must be either a globally-resolvable DNS machine name, or an IP address. Docker extension will not be able to use host aliases defined in the SSH configuration file.
Make sure the remote machine host key is already memorized in the known_hosts file. The simplest way to ensure this is to connect to the machine via ssh client program (run ssh username@host:port from the command line). Upon first-time connection, the ssh program will display the host key and let you approve it, updating the known_hosts file automatically.
There is an issue with ssh-keygen utility that comes with Windows 10 build 1909 and older that prevents it from working properly with newer SSH daemons (for example, the one that comes with Ubuntu 20.04 LTS and newer). The workaround is to use ECDSA-type key, not RSA-type key, for the SSH connection. You can generate an ECDSA SSH key and add it to SSH agent with following commands:
Windows 10 build 1909 and older are affected by an issue that prevents SSH from getting to your identities after Windows OS update. The workaround is to add a dummy service entry to system configuration. Run the following from administrative PowerShell window:
Connect to remote Docker over SSH
We recommend using the Visual Studio Code Remote — SSH extension to connect to a remote machine running Docker engine. You can use the Remote — SSH and Dev Containers extensions together. You may review the steps in the Dev Containers documentation.
It is also possible to connect to the remote Docker engine directly using SSH tunneling, which you can read more about below.
Set up SSH Tunneling
Use ssh-keygen or similar to get and configure a public/private key pair for SSH authentication. Password authentication is not supported by Docker and not possible with a DOCKER_HOST -based configuration. If a key pair has already been set up, it can be used.
Configure ssh-agent on the local system with the private key file produced above.
Windows (OpenSSH): The latest version(s) of Windows 10 include OpenSSH by default. There is a Windows service, ssh-agent that is disabled by default, and needs to be re-enabled and set to automatic start. From an admin PowerShell prompt, run Set-Service ssh-agent -StartupType «Automatic» and Start-Service ssh-agent . Then, do ssh-add .
Windows (Pageant): You can use Pageant instead of OpenSSH, in which case it is necessary to set the environment variable SSH_AUTH_SOCK=pageant . Making that a user or system environment variable will be easiest.
Linux: ssh-agent is present by default. Do ssh-add . Ubuntu was tested; you might have different results on other distributions.
macOS: ssh-agent is present by default, but ssh-add does not persist across logins. Do ssh-add . We recommend configuring VS Code to run this command on terminal startup with terminal.integrated.profiles.osx args value or otherwise configuring a startup script. You can also manually run that command each login.
Verify that your identity is available to the agent with ssh-add -l . It should list one or more identities that look something like 2048 SHA256:abcdefghijk somethingsomething (RSA) . If it does not list any identity, you will not be able to connect. Also, it needs to have the right identity. The Docker CLI working does not mean that the Explorer window will work. The Explorer window uses dockerode (which in turn uses ssh2), whereas the Docker CLI uses the ssh command, and benefits from an automatically inferred configuration.
Create a Docker context that points to the remote machine running Docker. Use ssh://username@host:port as the Docker endpoint (replace «host» with your remote machine name, or the remote machine IP address). Issue the following command from terminal window:
Always include the user name in the Docker endpoint address, even if it is the same as the local user name. If you omit the port, it defaults to 22.
Use the Command Palette ( ⇧⌘P (Windows, Linux Ctrl+Shift+P ) ) to issue the Docker Context: Use command to activate the Docker context pointing to the remote machine. This command causes both VS Code and Docker CLI to use the remote machine context.
It is recommended to change the refresh rate to something longer than the default with the docker.explorerRefreshInterval setting. The connection over SSH is slow, and it can result in trying to refresh again before the previous refresh even finished. We recommend at least 3000 ms.
The «host» part in the Docker endpoint string ( ssh://username@host:port ) must be either a globally-resolvable DNS machine name, or an IP address. Docker extension will not be able to use host aliases defined in the SSH configuration file.
Make sure the remote machine host key is already memorized in the known_hosts file. The simplest way to ensure this is to connect to the machine via ssh client program (run ssh username@host:port from the command line). Upon first-time connection, the ssh program will display the host key and let you approve it, updating the known_hosts file automatically.
There is an issue with ssh-keygen utility that comes with Windows 10 build 1909 and older that prevents it from working properly with newer SSH daemons (for example, the one that comes with Ubuntu 20.04 LTS and newer). The workaround is to use ECDSA-type key, not RSA-type key, for the SSH connection. You can generate an ECDSA SSH key and add it to SSH agent with following commands:
Windows 10 build 1909 and older are affected by an issue that prevents SSH from getting to your identities after Windows OS update. The workaround is to add a dummy service entry to system configuration. Run the following from administrative PowerShell window: