Quick intro to Docker Machine
After switching from boot2docker (deprecated) to Docker Machine (or should I rather say the Docker Toolbox on mac) on my laptop, and after playing around with Google Cloud Engine through Docker Machine, I was curious to see if I could manage all my Docker hosts, running on VPS or dedicated servers, from Docker Machine.
Docker Machine is a convenient tool to choose which Docker daemon you want to use : that could be a Docker daemon running in a Virtual box VM, or a Docker daemon running on EC2, GCE, Digital Ocean, etc. or a Docker daemon running on a Linux box (it is just a matter of which driver is being used)
The virtualbox driver allows you to create a new VM in Virtual Box, starts it and configures the client / daemon tcp link with tls (over port 2376 by default); cloud drivers such as google allow you to do the same thing but within the « cloud », whereas the generic driver does not create a new host, instead uses ssh to configure the client / daemon tcp link with tls on an existing host.
Once set up, « docker-machine ls » gives you the list of Docker daemons to interact with :
1 2 3 4 5 |
$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM my.host.com generic Running tcp://my.host.com:2376 default virtualbox Running tcp://192.168.99.104:2376 docker-vm * virtualbox Running tcp://192.168.99.102:2376 |
To talk to the my.host.com daemon, just issue this command :
1 |
$ eval "$(docker-machine env my.host.com)" |
and you’re now talking to your my.host.com daemon :
1 2 3 |
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 77aa96cf6db9 flexget "/usr/local/bin/flexg" 46 hours ago Up 21 hours flexget |
Convenient isn’t it ?
Integrating all my docker hosts (daemons) with docker-machine on my laptop would give the following benefits :
- No need to ssh anymore to my (remote) Docker boxes
- All my docker image work (Dockerfiles) could stay on my laptop, I could start new containers from local Dockerfiles on my remote hosts from the comfort of my laptop
Docker Machine : the generic driver
To integrate hosts you access through ssh, such as my.host.com, into Docker Machine list of daemons, you need to use the generic driver. (this driver will take care of configuring your remote daemon to listen on port 2376 and generate and distribute the necessary keys for tls)
As of Docker Machine 0.4.2 with Docker 1.8.2, you need to respect some constraints to integrate your ssh enabled Docker host; here’s a list (obtained the hard way….) :
- make sure you can connect, from your laptop to your remote Docker host using public key authentication (it means you generated a public key on your laptop and added to the list of authorized keys on the remote host : ssh-keygen, ssh-copy-id would help for that)
- If you are using « sudo » on the host, make sure you configure passwordless sudo :
1 2 |
# visudo %sudo ALL=(ALL) NOPASSWD:ALL |
if you don’t, well unless this issue is closed, that’s not going to work
- make sure the Docker daemon version on the server is the same one as the Docker client on the laptop
- open the port 2376 (« ufw allow 2376 » on Debian / Ubuntu) on your remote host : your laptop Docker client will connect via TCP on port 2376 to talk to remote daemons
Those verifications made, I suggest you now add your remote Docker daemon (running on my.host.com) to Docker Machine :
1 2 3 4 |
$ docker-machine create --driver generic \ --generic-ip-address my.host.com \ --generic-ssh-user anthony \ my.host.com |
It did not work ? well I got you covered with next chapter !
Docker machine generic driver common issues
On Mac OS X, it keeps asking me for my secret key passphrase
Well, that’s not _that_ bad, but still there’s a workaround described here
sudo: no tty present and no askpass program specified
1 2 3 4 5 6 |
SSH cmd error! command: sudo hostname my.host.com && echo "my.host.com" | sudo tee /etc/hostname err : exit status 1 output : Saving password to keychain failed Identity added: /Users/anthony/.docker/machine/machines/my.host.com/id_rsa (/Users/anthony/.docker/machine/machines/my.host.com/id_rsa) sudo: no tty present and no askpass program specified |
Make sure your remote user has passwordless sudo configured, as described in the previous chapter :
1 |
%sudo ALL=(ALL) NOPASSWD:ALL |
Follow this issue for more info
docker-machine will wait forever
Probably it’s trying to connect to port 2376 and it’s blocked; have a look at the syslog on your remote host,
1 |
sudo tail -f /var/log/syslog |
and check if there are no lines similar to this one :
1 |
Oct 7 01:26:54 my.host kernel: [1859460.411738] [UFW BLOCK] IN=eth0 OUT= MAC=XX:XX SRC=199.99.99.99 DST=92.12.12.12 LEN=64 TOS=0x00 PREC=0x00 TTL=52 ID=37574 DF PROTO=TCP SPT=49855 DPT=2376 WINDOW=65535 RES=0x00 SYN URGP=0 |
Hum, UFW BLOCK and 2376 on the same line ? Sounds like you need to update your firewall configuration :
1 |
$ sudo ufw allow 2376 |
Triple check the docker versions on your laptop and the remote host are aligned
Could not load host key: /etc/ssh/ssh_host_ecdsa_key
If you are running into trouble, you might be looking into the ssh log
1 |
sudo tail -f /var/log/auth.log |
and maybe you saw those 2 lines :
1 2 |
Oct 7 01:04:41 host sshd[29920]: error: Could not load host key: /etc/ssh/ssh_host_ecdsa_key Oct 7 01:04:41 host sshd[29920]: error: Could not load host key: /etc/ssh/ssh_host_ed25519_key |
You just need to generate those keys, on the remote host :
1 |
$ sudo ssh-keygen -A |
and they will be generated
1 |
ssh-keygen: generating new host keys: ECDSA ED25519 |
Failed to execute operation: File exists
1 2 3 4 5 6 7 |
SSH cmd error! command: sudo systemctl enable docker err : exit status 1 output : Synchronizing state for docker.service with sysvinit using update-rc.d... Executing /usr/sbin/update-rc.d docker defaults Executing /usr/sbin/update-rc.d docker enable Failed to execute operation: File exists |
Apparently this is a Debian 8 specific issue, the good news is : it did not prevent the addition of your remote host to Docker Machine
Unimportant warnings
1 2 3 |
Importing SSH key... Warning: got an invalid line error parsing /etc/os-release: %sExpected Saving password to keychain failed to split by '=' char into two strings, instead got 1 strings Warning: got an invalid line error parsing /etc/os-release: %sExpected Identity added: /Users/anthony/.docker/machine/machines/my.host.com/id_rsa (/Users/anthony/.docker/machine/machines/my.host.com/id_rsa) to split by '=' char into two strings, instead got 1 strings |
You can safely ignore those warnings
Victory !
1 2 3 |
$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM my.host.com * generic Running tcp://my.host.com:2376 |
You can now enjoy docker running on your remote host from your laptop !
One last thing ! docker-machine, remote hosts (not VirtualBox), and volumes
Do not expect volumes mounting (-v local_folder:container_folder) to work… Because the « local_folder » in question can only be a path on the remote host for now… Not a path on your laptop.
So you can either
- wait for this proposal to be integrated, or
- stop using a volume, because anyway that’s maybe not the answer to your problem, or, as a workaround
- use docker-machine scp to copy a file (or folder) from your laptop to the remote host, for example :
1 2 |
$ docker-machine scp config.yml my.host.com:config.yml $ docker run -v /path_on_my_host_com/config.yml:/usr/src/app --name my_container -d anthonydahanne/my_container |