Have you ever asked? Can I run Docker into a Docker container (dockerize Docker)? The answer is yes.
And now, can I run Docker using a container started used a Docker client on my Mac that use a Docker server on my Mac running in a VM? The answer is yes, but not so simple!
So first you must create an image containing Docker, pretty easy, we create the Dockerfile:
FROM ubuntu:14.04 # Update and upgrade RUN apt-get update -y && apt-get upgrade -y # Install curl RUN apt-get install -y curl # Install the last version of Docker RUN curl -sSL https://get.docker.com/ubuntu/ | sh # Use Docker as entrypoint
Now we build the image, let's name it "tiny-docker":
docker build -t tiny-docker .
And now we will run Docker! Let's try to display the version.
docker run tiny-docker version
Client version: 1.3.2 Client API version: 1.15 Go version (client): go1.3.3 Git commit (client): 39fa2fa OS/Arch (client): linux/amd64 2014/12/05 15:23:28 Get http:///var/run/docker.sock/v1.15/version: dial unix /var/run/docker.sock: no such file or directory
You can notice the following error:
http:///var/run/docker.sock/v1.15/version: dial unix /var/run/docker.sock: no such file or directory
Yes Docker is just a client so it needs a Socker to connect.
If you are on Linux, you are lucky (for once that you are, be happy). You just have to mount your UNIX socket and it will work, the command is:
docker run -v /var/run/docker.sock:/var/run/docker.sock tiny-docker version
If you are on a Mac, you can start to cry.
On a Mac, the socket is a TCP socket, the TCP socket of boot2docker VM. For this, Docker has a great feature: DOCKER_HOST environment variable.
It should be easy, we will just use expose the environement variable in the container, let's try:
docker run -e "DOCKER_HOST=$DOCKER_HOST" tiny-docker version
The error has changed, now you will get
2014/12/05 15:30:05 Get http://192.168.59.103:2376/v1.15/version: malformed HTTP response "\x15\x03\x01\x00\x02\x02". WTF what is this? This is the error of Docker when it requires TLS and that TLS is not activate (just trust me on this one).
To enable TLS on Docker you need to set up several environment variables, two in fact: "DOCKERCERTPATH" and "DOCKERTLSVERIFY". The first must contain the path of the certs and the second must contains "1".
So we will mount certs path and add these environment variables:
docker run -v $DOCKER_CERT_PATH:/certs -e "DOCKER_HOST=$DOCKER_HOST" -e "DOCKER_CERT_PATH=/certs" -e "DOCKER_TLS_VERIFY=1" tiny-docker version
Client version: 1.3.2 Client API version: 1.15 Go version (client): go1.3.3 Git commit (client): 39fa2fa OS/Arch (client): linux/amd64 Server version: 1.3.0 Server API version: 1.15 Go version (server): go1.3.3 Git commit (server): c78088f
Success! It works!
If you want to be compatible with Linux guys, you can add the mount of the local socket, it will do nothing on Mac but will make it works on Linux.