

By Patrick Daigle, Sr. Technical Marketing Architect, Cloud-Native Apps
Introduction
In version 1.2, vSphere Integrated Containers (VIC) introduced the concept of the native Docker Container Host (DCH). This is a built-in Docker image containing a full-fledged Docker engine that runs using VIC. DCH is packaged as a container and can be instantiated on VIC like any regular container.
The DCH image is distributed through Docker Hub and, as part of the VIC product distribution, in the registry. As of this writing, we offer three versions of the Docker engine: 1.12, 1.13 and 17.06. All of the official DCH images maintained by VMware are based on Photon OS. The source, Dockerfiles and documentation are available at github.com/vmware/vic-product.
DCH is well-suited for development use cases. Here are some examples:
- As part of a CI/CD pipeline, VIC can be used to enhance end-to-end dev-build-push-deploy workflows. VIC with DCH can be used as a (self-service) private cloud for CI/CD by enabling the easy deployment and tear down of Docker hosts.
- VIC and DCH allow you to treat Docker Hosts as ephemeral compute. This has the benefit of eliminating snowflakes (individually managed Docker Hosts), which reduces Operating System OpEx costs. For example, as part of a CI pipeline, you could instantiate ephemeral Docker Hosts that exist only for the purpose of building and pushing images, and only for the time it takes to complete that task.
- An example of how VIC can be used to deploy Jenkins is given here.
In this article, I will demonstrate how flexible this DCH abstraction is. I will walk you through how a developer can leverage VIC and DCH to easily instantiate a Docker swarm using only well-known native Docker commands. I’ll also show how easy it is to create a complete cluster of ephemeral compute using DCH.
To illustrate this, we’ll look at the following script. This is a simple shell script that deploys a Docker swarm manager node and then creates and joins a user-defined number of worker nodes to the swarm.
#!/bin/bash
## USER-DEFINED VARIABLES
# Number of swarm workers desired
NUM_WORKERS=3
# name of routable (external) network
# this needs to be defined on your VCH using the ‘--container-network’ option
# use ‘docker network ls’ to list available external networks
CONTAINER_NET=routable
# Docker Container Host (DCH) image to use
# see https://hub.docker.com/r/vmware/dch-photon/tags/ for list of available Docker Engine versions
DCH_IMAGE=”vmware/dch-photon:17.06″
## NO NEED TO MODIFY BEYOND THIS POINT
# pull the image
docker pull $DCH_IMAGE
# create a docker volume for the master image cache
docker volume create --opt Capacity=10GB --name registrycache
# create and run the master instance
docker run -d -v registrycache:/var/lib/docker \
--net $CONTAINER_NET \
-name manager1 -hostname=manager1 \
$DCH_IMAGE
# get the master IP
SWARM_MASTER=$(docker inspect -f ‘{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}’ manager1)
# create the new swarm on the master
docker -H $SWARM_MASTER swarm init
# get the join token
SWARM_TOKEN=$(docker -H $SWARM_MASTER swarm join-token -q worker)
sleep 10
# run $NUM_WORKERS workers and use $SWARM_TOKEN to join the swarm
for i in $(seq “${NUM_WORKERS}”); do
# create docker volumes for each worker to be used as image cache
docker volume create --opt Capacity=10GB --name worker-vol${i}
# run new worker container
docker run -d -v worker-vol${i}:/var/lib/docker \
--net $CONTAINER_NET \
--name worker${i} --hostname=worker${i} \
$DCH_IMAGE
# wait for daemon to start
sleep 10
# join worker to the swarm
for w in $(docker inspect -f ‘{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}’ worker${i}); do
docker -H $w:2375 swarm join --token ${SWARM_TOKEN} ${SWARM_MASTER}:2377
done
done
# display swarm cluster information
printf “\nLocal Swarm Cluster\n=========================\n”
docker -H $SWARM_MASTER node ls
printf “=========================\nMaster available at DOCKER_HOST=$SWARM_MASTER:2375\n\n”
Let’s break this down to better understand what this script does.
User-defined variables
## USER-DEFINED VARIABLES
# Number of swarm workers desired
NUM_WORKERS=3
# name of routable (external) network
# this needs to be defined on your VCH using the ‘--container-network’ option
# use ‘docker network ls’ to list available external networks
CONTAINER_NET=routable
# Docker Container Host (DCH) image to use
# see https://hub.docker.com/r/vmware/dch-photon/tags/ for list of available Docker Engine versions
DCH_IMAGE=”vmware/dch-photon:17.06″
As a user of the script, this is the only section you need to modify.
- NUM_WORKERS – this is the number of worker nodes that will be added to the swarm, in addition to the manager node.
- CONTAINER_NET – this is the network to be used by our Docker Container Hosts. Here we leverage the ability of vSphere Integrated Containers to connect containers directly to vSphere Port Groups rather than through the Container Host. This will allow for easier interaction with our swarm.
- DCH_IMAGE – here you can specify a different version of the Docker engine by modifying the tag (e.g. ‘vmware/dch-photon:1.13′). You can see the list of available tags/versions here.
The script will use these parameters to pull the images, instantiate the swarm manager, initiate the swarm and instantiate and join the user-defined number of worker nodes.
Creating the master, initiating the swarm and getting the join token
# create a docker volume for the master image cache
docker volume create --opt Capacity=10GB --name registrycache
# create and run the master instance
docker run -d -v registrycache:/var/lib/docker \
--net $CONTAINER_NET \
--name manager1 --hostname=manager1 \
$DCH_IMAGE
# get the master IP
SWARM_MASTER=$(docker inspect -f ‘{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}’ manager1)
# create the new swarm on the master
docker -H $SWARM_MASTER swarm init
This is where we begin to see the DCH magic in action. Specifically, look at the following command:
> docker run -d -v registrycache:/var/lib/docker \
--net $CONTAINER_NET \
--name manager1 --hostname=manager1 \
$DCH_IMAGE
This starts up a full-fledged docker engine (running version 17.06) instantiated as a containerVM, using only a simple ‘docker run’ command. As you can see, DCH makes it very easy for developers to start up docker engines on-demand, thus creating new self-service possibilities.
Once the manager is created, we initialize the swarm (‘docker -H $SWARM_MASTER swarm init’), and then we grab the join token (‘docker -H $SWARM_MASTER swarm join-token -q worker’) that will allow us to join the worker nodes to the swarm in the next step.
Creating the workers and adding them to the swarm
# run $NUM_WORKERS workers and use $SWARM_TOKEN to join the swarm
for i in $(seq “${NUM_WORKERS}”); do
# create docker volumes for each worker to be used as image cache
docker volume create --opt Capacity=10GB --name worker-vol${i}
# run new worker container
docker run -d -v worker-vol${i}:/var/lib/docker \
--net $CONTAINER_NET \
--name worker${i} --hostname=worker${i} \
$DCH_IMAGE
# wait for daemon to start
sleep 10
# join worker to the swarm
for w in $(docker inspect -f ‘{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}’ worker${i}); do
docker -H $w:2375 swarm join &ndash&ndashtoken ${SWARM_TOKEN} ${SWARM_MASTER}:2377
done
done
This simple ‘for’ loop repeats NUM_WORKERS times. For each iteration, it:
- creates a volume to be used as the image cache for the worker
- instantiates a worker using the ‘vmware/dch-photon:17.06’ image
- joins the worker to the swarm using the join token (‘SWARM_TOKEN’) we fetched in the previous step
Once again, because we are using DCH with VIC, we see that it requires only a very simple ‘docker run’ command to create and run our Docker Hosts that will be used as the swarm worker nodes.
Running the script and result
Before running the script, you need to point your Docker client to a VIC Virtual Container Host endpoint. This is done by setting ‘DOCKER_HOST=<endpoint-ip>:<port>’. This script requires a Virtual Container Host endpoint — a requirement to run the DCH image, which enables all of the above automation. You can find this information in the vSphere Client portlet:

You can use the following commands (replace with your own endpoint IP address and make sure the script is in the current directory):
> export DOCKER_HOST=192.168.100.144:2375
> ./dch-swarm.sh
Upon completion, the script prints information about the newly created swarm:

We can also see our newly created containerVMs hosting the swarm manager and the swarm workers in vSphere Client:

Finally, we can test the swarm by running the Docker Example Voting App. We deploy the app against our swarm by using the ‘docker stack deploy’ command:

We can see above that all of the required services were started. Testing the application in the browser, we can see it is indeed running and functional:

Conclusion
You should now have a better understanding of how the newly introduced VIC DCH feature helps address developer use cases. We have shown how easy it is to automate the deployment of Docker hosts using DCH. VIC provides end-users and developers with a Docker dial tone and a very flexible consumption model on top of vSphere, while DCH enables a new level of self-service.
If you’re interested in getting more hands-on knowledge around VIC, check out our tutorials on GitHub: https://github.com/vmware/vic-product/tree/master/tutorials
Acknowledgements
Thanks to Nathan Ness for contributing to the creation and testing of the script featured here (https://github.com/nvpnathan/vic). Special thanks to Ben Corrie for his review and sound advice.