Print
Hits: 5398

I recently had to help a technology high growth business with the installation of Docker across their mixed Operating System estate. I figured that it would be useful to set up a small environment in my lab, to assist with the process, the inevitable debugging and potentially, the documentation. This post lists the steps that I took and hopefully, others might benefit from it too.

So, what is Docker?

To quote Docker.com "In 2013, Docker introduced what would become the industry standard for containers. Containers are a standardized unit of software that allows developers to isolate their app from its environment, solving the 'it works on my machine' headache." This is really important when shipping software between environments. It is all too common to hear "it worked in UAT but it doesn't work in Production". Containers make that scenario much less likely and give a layer of abstraction so that Developers do not need to work about the underlying IT Infrastructure (and vice versa).
 
The Docker docs are extremely helpful in gaining a deeper understanding of the architecture and how to implement Docker. Additionally, there are further helpful posts Docker architecture, a Beginners Guide to Docker and an interview with a Docker executive here.
 
This post is specifically focussed at a mixed Operating System environment, where the clients are Windows based and the servers are running Linux (in this case, Ubuntu).

Installing the Docker client on Windows 10 laptop/desktop 

Since I do not have Hyper V on my Windows devices, I am opting for the legacy Docker Toolbox for Windows. This will install the Docker client so that I can control the Docker server/daemons out on my lab network. The Windows boxes are 64 bit (x64) so this is fine as it is a prerequisite.
 
You can get the .exe at https://docs.docker.com/toolbox/toolbox_install_windows/
 
It will also install VirtualBox so be careful that it is not already installed.
 
It creates a local Docker machine on the Windows device.

Installing the Docker server installation on Ubuntu 16.04

Log onto the box and the run the following commands:
sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install docker-ce (CE stands for Community Edition, as opposed to Enterprise Edition)
 
Test that it installed ok by doing:
sudo docker run hello-world
docker --version
 
Start docker as a daemon and get it to start at startup next time:
sudo systemctl start docker
sudo systemctl enable docker
 
One last test to check all is well:
sudo docker run --rm -ti ubuntu:latest /bin/bash

Connect the Windows Docker client to the Ubuntu Docker server

This requires that you are able to ssh to the remote host (Ubuntu server) and sudo without entering a password:
 
Run and look at output from:
C:\Windows\System32\OpenSSH\ssh.exe
 
If it is not set up already then run C:\Windows\System32\OpenSSH\ssh-keygen to generate a public key (id_rsa.pub) which is located in the same directory while the public key is stored in C:\Users\<user>\.ssh
 
Now add the contents of id_rsa.pub to authorized_keys in .ssh on the Ubuntu server using cat.
 
Once complete, you should be able to ssh to the Ubuntu server from the Windows client:
ssh [email protected]<IP of Ubuntu server>
and can log in without a password.
 
As Docker needs to be able to sudo without a password also do on the Ubuntu server:
sudo visudo
and add the below line to the file
{username}  ALL=(ALL) NOPASSWD:ALL

To provision a remote Docker host machine

In a cmd window on the Windows 10 box
Go to C:\Program Files\Docker Toolbox
 
and run
docker-machine create --driver generic --generic-ip-address=<IP address of Ubuntu server> --generic-ssh-user=pgroom <hostname of Ubuntu server> where pgroom is an user on the Ubuntu server
docker-machine env <hostname of Ubuntu server>
 
Produces:
SET DOCKER_TLS_VERIFY=1 
SET DOCKER_HOST=tcp://<IP address of Ubuntu server>:2376 
SET DOCKER_CERT_PATH=C:\Users\net_k\.docker\machine\machines\remote-docker-host 
SET DOCKER_MACHINE_NAME=<hostname of Ubuntu server>
SET COMPOSE_CONVERT_WINDOWS_PATHS=true 
REM Run this command to configure your shell: 
REM     @FOR /f "tokens=*" %i IN ('docker-machine env remote-docker-host') DO @%i 
 
then run this
@FOR /f "tokens=*" %i IN ('docker-machine env nklserv02') DO @%i
 
to check which machine connected to:
docker-machine ls
 
Finally, check all is ok on the Ubuntu server:
docker run ubuntu /bin/echo hello world

Some helpful hints/commands when operating Docker containers

Removing a Docker container
 
If a Docker container is no longer required then you can remove it by:
docker rmi <image id>
where the <image id> is part of the output from docker images command
 
or by:
docker-machine rm <hosntame of Ubuntu server>
 
Debugging a Docker container
 
To debug and get to a shell inside the container do (assuming it was started by something like the below):
docker run -d -t ubuntu /bin/bash
 
Can look for the container ID by running docker ps and looking for the command /bin/bash - in this case 5b8c64046b71 (or use the name if you gave the container one when you created it)
 
Then do
docker exec -t -i 5b8c64046b71 /bin/bash
 
and you get a prompt of
[email protected]:/#
 
you can now debug the Docker container interactively

Creating and starting a Docker container
 
Below are the steps that I went through to create a Docker container that runs a simple Curl PHP script. It lists all recruitment agencies by UK county and is normally run as per below:
/usr/bin/php /home/pgroom/agencies.php Devon
 
Option 1 - interactive Bash shell
docker run --name=curl -d -v -i /home/pgroom:/home ubuntu:latest /bin/bash
 
However the name has to be unique so can't have 2 containers with the same name, even if one is stopped
 
Option 2 - Using a Dockerfile then run a machine that runs curl and exits
This is the Dockerfile
FROM ubuntu:latest
RUN apt-get update && \
apt-get install -y tzdata
RUN ln -fs /usr/share/zoneinfo/Europe/London /etc/localtime
RUN dpkg-reconfigure --frontend noninteractive tzdata
RUN apt-get install -y php && \
apt-get install -y curl

COPY agencies.php /home/pgroom
 
Then build the image
docker build -t jrncurl:0.1 "C:\Program Files\Docker Toolbox\dockerfiles"
where C:\Program Files\Docker Toolbox\dockerfiles is the directory that has the Dockerfile listed above and note the lowercase for the tag.
 
Although php install needs to know which country and city in order to proceed as it used tzdata so need to put 2 extra lines, one for /etc/localtime and the other for dpkg-reconfigure
 
The last couple of lines look something like this:
Removing intermediate container 4fb2c32171b3
 ---> 82df8e0dd07d
Successfully built 82df8e0dd07d
 
Now need to start a container based on the build so:
docker run -it jrncurl:0.1 /bin/bash
 
Problem: Can't access the file system so can't get to agencies.php
 
Tried to copy the script but no luck as could not find the file agencies.php
COPY failed: stat /var/lib/docker/tmp/docker-builder658320030/agencies.php: no such file or directory
 
Found a copy command that worked but this generates an error as it is outside of the Docker context i.e. directory
COPY ../../../../../home/pgroom/agencies.php /home/agencies.php
 
In the end, had to copy agencies.php to C:\Program Files\Docker Toolbox\dockerfiles
 
Then run:
docker build -t jrncurl:0.6 "C:\Program Files\Docker Toolbox\dockerfiles"
 
This now builds the image but need to remember that the file has to be in the same directory as the Dockerfile.
 
Now need to start a container based on the build so:
docker run -it jrncurl:0.6 /bin/bash
 
Can now run the below and get the results back
/usr/bin/php /home/pgroom/agencies.php Devon
 
I hope that the above may prove useful. Please feel free to add your own thoughts in the comments section below.
 
All the best.
 
Pete