8 docker
-connect - Easily connect to Docker sockets over SSH
16 docker
-connect HOSTNAME
[SHELL_ARGS
]...
18 # launch a new shell wherein docker commands go to staging-01.acme.tld
19 docker
-connect staging
-01.acme.tld
21 # list the docker processes running on staging-01.acme.tld
22 docker
-connect staging
-01.acme.tld
-c 'docker ps'
24 # connect as a specific user and a specific port
25 docker
-connect myusername@staging
-01.acme.tld
:2222
29 This
script provides an alternative to Docker Machine
for connecting your Docker client to a remote
30 Docker daemon. Instead of connecting directly to a Docker daemon listening on an external TCP port
,
31 this
script sets up a connection to the UNIX socket via SSH.
33 The main use
case for this is when dealing with
"permanent" app servers
in an environment where you
34 have a team of individuals who all need access.
36 Machine doesn
't have a great way to support multiple concurrent users. You can add an existing
37 machine to which you have SSH access using the generic driver on your computer, but if your
38 colleague does the same then Machine will regenerate the Docker daemon TLS certificates, replacing
39 the ones Machine set up for you.
41 Furthermore, the Docker daemon relies on TLS certificates for client authorization, which is all
42 fine and good, but organizations are typically not as prepared to deal with the management of client
43 TLS certificates as they are with the management of SSH keys. Worse, the Docker daemon doesn't
44 support certificate revocation lists
! So
if a colleague leaves
, you must replace the certificate
45 authority and recreate and distribute certificates
for each remaining member of the team. Ugh
!
47 Much easier to just use SSH
for authorization.
49 To be
clear, this
script isn
't a full replacement for Docker Machine. For one thing, Machine has
50 a lot more features and can actually create machines. This script just assists with a particular
51 workflow that is currently underserved by Machine.
55 What this script actually does is something similar to this sequence of commands:
57 ssh -L$PWD/docker.sock:/run/docker.sock $REMOTE_USER@$REMOTE_HOST -p$REMOTE_PORT -nNT &
58 export DOCKER_HOST="unix://$PWD/docker.sock"
59 unset DOCKER_CERT_PATH
60 unset DOCKER_TLS_VERIFY
62 This uses L<ssh(1)> to create a UNIX socket that forwards to the Docker daemon's own UNIX socket on
63 the remote
host. The benefit that C
<docker
-connect> has over executing these commands directly is
64 C
<docker
-connect> doesn
't require write access to the current directory since it puts its sockets in
65 C<$TMPDIR> (typically F</tmp>).
67 If your local system doesn't support UNIX sockets
, you could use the following C
<ssh> command
68 instead
which uses a TCP socket
:
70 ssh -L2000:/run
/docker.sock
$REMOTE_USER@
$REMOTE_HOST -p$REMOTE_PORT -nNT &
71 export DOCKER_HOST
="tcp://localhost:2000"
73 An important drawback here is that any
local user on the machine will
then have unchallenged access
74 to the remote Docker daemon by just connecting to localhost
:2000. But this may be a reasonable
75 alternative
for use on non
-multiuser machines only.
81 =item
* a Bourne
-compatible, POSIX
-compatible shell
83 This program is written
in shell
script.
85 =item
* L
<OpenSSH
|https
://www.openssh.com
> 6.7+
87 Needed to
make the socket connection.
89 =item
* L
<Docker
|https
://www.docker.com
> client
91 Not technically required
, but this program isn
't useful without it.
97 =for markdown [![Build Status](https://travis-ci.org/chazmcgarvey/docker-connect.svg?branch=master)](https://travis-ci.org/chazmcgarvey/docker-connect)
99 To install, just copy F<docker-connect> into your C<PATH> and make sure it is executable.
101 # Assuming you have "$HOME/bin" in your $PATH:
102 cp docker-connect ~/bin/
103 chmod +x ~/bin/docker-connect
107 The following environment variables may affect or will be set by this program:
111 =item * C<DOCKER_CONNECT_SOCKET>
113 The absolute path to the local socket.
115 =item * C<DOCKER_CONNECT_HOSTNAME>
117 The hostname of the remote peer.
119 =item * C<DOCKER_CONNECT_PID>
121 The process ID of the SSH process maintaining the connection.
123 =item * C<DOCKER_HOST>
125 The URI of the local socket.
131 If you run many shells and connections, having the hostname of the host that the Docker client is
132 connected to in your prompt may be handy. Try something like this in your local shell config file:
134 if [ -n "$DOCKER_CONNECT_HOSTNAME" ]
136 PS1="[docker:$DOCKER_CONNECT_HOSTNAME] $PS1"
141 Charles McGarvey <chazmcgarvey@brokenzipper.com>
145 This software is copyright (c) 2017 by Charles McGarvey.
147 This is free software, licensed under:
149 The MIT (X11) License
155 prog=$(basename "$0")
158 socket="$DOCKER_CONNECT_SOCKET"
159 remote_socket=${REMOTE_SOCKET:-/run/docker.sock}
160 timeout=${TIMEOUT:-15}
164 $prog [OPTIONS]... HOSTNAME [SHELL_ARGS]...
165 Easily connect to Docker sockets over SSH.
168 -h Show this help info and exit.
169 -q Be less verbose; can be repeated to enhance effect.
170 -r STR Specify the absolute path of the remote socket.
171 -s STR Specify the absolute path of the local socket.
172 -v Show the program version.
179 if [ "$_l" -ge "$quiet" ]
185 while getopts "hqr:s:v" opt
189 quiet=$(expr $quiet + 1)
195 remote_socket="$OPTARG"
202 echo "docker-connect $version"
211 shift $(expr $OPTIND - 1)
216 echo >&2 "Missing HOSTNAME."
224 socket_dir="${TMPDIR:-/tmp}/docker-connect-$(id -u)"
225 mkdir -p "$socket_dir"
226 chmod 0700 "$socket_dir"
227 socket="$socket_dir/docker-$$.sock"
232 if [ -n "$DOCKER_CONNECT_HOSTNAME" ]
234 log 2 "Docker is already connected to $DOCKER_CONNECT_HOSTNAME in this shell."
237 log 2 "Docker socket already exists."
238 log 1 "To force a new connection, first remove the file: $socket"
241 elif [ -e "$socket" ]
243 log 2 "Cannot create socket because another file is in the way."
244 log 1 "To create a new connection, you may first remove the file: $socket"
252 if echo "$connect" |grep -q ':'
254 hostname=$(echo "$connect" |cut -d: -f1)
255 port=$(echo "$connect" |cut -d: -f2)
260 if echo "$hostname" |grep -q '@
'
262 user=$(echo "$hostname" |cut -d@ -f1)
263 hostname=$(echo "$hostname" |cut -d@ -f2)
266 ssh_connect="$hostname"
270 ssh_connect="$user@$ssh_connect"
275 ssh_connect="$ssh_connect -p$port"
278 ${SSH:-ssh} $ssh_connect -L"$socket:$remote_socket" \
279 -oControlPath=none -oConnectTimeout="$timeout" -nNT &
284 log 2 "The connection could not be established."
285 log 1 "Please ensure that you can execute this command successfully:"
286 log 1 " ${SSH:-ssh} $ssh_connect -oControlPath=none echo OK"
290 handle_disconnect() {
291 kill $ssh_pid 2>/dev/null || true
293 log 0 "Disconnected docker from $hostname."
296 # Wait for the socket connection to be made.
297 for i in $(seq 1 "${timeout}0")
304 if ! kill -s 0 $ssh_pid 2>/dev/null
311 if [ -z "$ssh_connected" ]
316 trap handle_disconnect EXIT
318 export DOCKER_CONNECT_HOSTNAME="$hostname"
319 export DOCKER_CONNECT_PID="$ssh_pid"
320 export DOCKER_CONNECT_SOCKET="$socket"
321 export DOCKER_HOST="unix://$socket"
323 # Remove incompatible variables set by Docker Machine.
324 unset DOCKER_MACHINE_NAME
325 unset DOCKER_CERT_PATH
326 unset DOCKER_TLS_VERIFY
328 log 1 "Executing new shell with docker connected to $hostname."
329 log 0 "This connection will be terminated when the shell exits."
330 ${SHELL:-/bin/sh} "$@"