Containers are the future, so I need to be able to work with Docker. On Windows, Docker runs inside a virtual machine and by default ships with VirtualBox. As a Windows developer, all of my virtual machines and emulators are Hyper-V images which conflicts with VirtualBox. In the past, I would dual boot to switch between Hyper-V and VirtualBox, but that is a huge pain, so I decided to figure out how to get Docker running in Hyper-V. It turns out that it isn’t difficult, but most of the instructions assume VirtualBox or are out of date.
We’re all Windows developers here, so I will assume that you are already using Hyper-V and that it is working.
Download Docker Toolbox for Windows
Run the installer. On the third screen, you cannot uncheck VirtualBox even though you don’t need it. Damn you Docker! No worries, we can get around that…
On the fourth screen, select all options, then continue to click through all of the screens.
At the end of the Docker Toolbox install, it will begin installing VirtualBox. A Windows Security dialog will pop up asking you if you want to install Oracle device software. Clicking Don’t Install will abort the VirtualBox install.
The Docker Quickstart Terminal and Kitematic (Alpha) shortcuts won’t work without VirtualBox, so skip them. We will install the Docker vm into Hyper-V manually.
Create a Boot2Docker Hyper-V Machine
If you have many virtual machines in Hyper-V, you will likely have several Virtual Switches. You must specify which Virtual Switch to use when you create the Docker VM, so open Hyper-V Manager and select Virtual Switch Manager from the actions on the right.
Select a Virtual Switch that is connected directly to an external network interface, ideally to an ethernet connection, not to a wireless card. Copy the name of the switch, you will use it when you create the virtual machine.
Open an Admin command prompt and run docker-machine create, substituting your virtual switch name. In this example, the Hyper-V machine will be called Boot2Docker. See the Docker Hyper-V documentation for more command line options.
D:\src Ω docker-machine create --driver hyperv --hyperv-virtual-switch "Intel(R) Ethernet Connection I217-LM Virtual Switch" Boot2Docker Creating CA: C:\Users\rob.prouse\.docker\machine\certs\ca.pem Creating client certificate: C:\Users\rob.prouse\.docker\machine\certs\cert.pem Running pre-create checks... Creating machine... (Boot2Docker) Copying C:\Users\rob.prouse\.docker\machine\cache\boot2docker.iso to C:\Users\rob.prouse\.docker\machine\machines\Boot2Docker\boot2docker.iso... (Boot2Docker) Creating SSH key... (Boot2Docker) Creating VM... (Boot2Docker) Using switch "Intel(R) Ethernet Connection I217-LM Virtual Switch" (Boot2Docker) Creating VHD (Boot2Docker) Starting VM... (Boot2Docker) Waiting for host to start... Waiting for machine to be running, this may take a few minutes... Detecting operating system of created instance... Waiting for SSH to be available... Detecting the provisioner... Provisioning with boot2docker... Copying certs to the local machine directory... Copying certs to the remote machine... Setting Docker configuration on the remote daemon... Checking connection to Docker... Docker is up and running! To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: C:\Program Files\Docker Toolbox\docker-machine.exe env Boot2Docker
As this is working, back in Hyper-V Manager, connect to your docker image to see what it is doing.
I don’t like working as an admin if I don’t need to, so close your admin command prompt and open a regular command prompt for the remaining work.
That’s it, you now have Docker installed and running in Hyper-V. Next up, let’s configure the Docker client to connect to your vm.
Working with docker-machine
From this point on, everything is standard Docker commands, so check out the docker-machine documentation. Whenever you want to work with Docker, you use docker-machine to start and stop your machines, to list running machines and to configure your shell to connect to a running Docker instance.
Listing Docker Machines
You use docker-machine ls to view registered Docker machines and their state.
D:\src λ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS Boot2Docker - hyperv Running tcp://192.168.0.113:2376 v1.10.2
Starting and Stopping Machines
Use docker-machine start [MachineName] and docker-machine stop [MachineName] to start and stop virtual machines.
λ docker-machine start Boot2Docker Starting "Boot2Docker"... (Boot2Docker) Waiting for host to start... Machine "Boot2Docker" was started. Waiting for SSH to be available... Detecting the provisioner... Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.
Configuring Your Shell
To connect your Docker client to a running vm, use the command docker-machine env [MachineName].
D:\src λ docker-machine env Boot2Docker $Env:DOCKER_TLS_VERIFY = "1" $Env:DOCKER_HOST = "tcp://192.168.0.113:2376" $Env:DOCKER_CERT_PATH = "C:\Users\rob.prouse\.docker\machine\machines\Boot2Docker" $Env:DOCKER_MACHINE_NAME = "Boot2Docker" # Run this command to configure your shell: # & "C:\Program Files\Docker Toolbox\docker-machine.exe" env Boot2Docker | Invoke-Expression
The last line tells you what you need to run to configure your shell. I am using PowerShell, so I need to run & docker-machine env Boot2Docker | Invoke-Expression to set the required environment variables.
Test Your Docker Installation
Now that you are setup and have your shell configured, run docker run hello-world to check that everything is working.
D:\src λ docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 03f4658f8b78: Pull complete ================================================>] 601 B/601 BB a3ed95caeb02: Pull complete ================================================>] 32 B/32 BB Digest: sha256:8be990ef2aeb16dbcb9271ddfe2610fa6658d13f6dfb8bc72074cc1ca36966a7 Status: Downloaded newer image for hello-world:latest Hello from Docker. This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker Hub account: https://hub.docker.com For more examples and ideas, visit: https://docs.docker.com/userguide/
From here, if you are new to Docker, I would suggest continuing with the Docker on Windows Getting Started Step 2 – Understanding images & containers which picks up from this point.