Skip to main content

In Part 1 – Creating and Uploading Containers to Docker Hub , we went over what is required to setup our environment, as well as some basic docker creation and management, ending with uploading our custom container over to the Docker. Now, we will go head and start writing Puppet in Part 2 – Writing Puppet code to Manage Containers.

Deploying Docker with Puppet on the Host Server
On the host server that contains our Puppet agent, we will first login as root and then install the garethr-docker module:
root@ip-10-1-2-3:~# puppet module install garethr-docker
Notice: Preparing to install into /etc/puppetlabs/code/environments/production/modules ...
Notice: Downloading from https://forgeapi.puppetlabs.com ...
Notice: Installing -- do not interrupt ...
/etc/puppetlabs/code/environments/production/modules
└─┬ garethr-docker (v5.3.0)
├── puppetlabs-apt (v2.3.0)
├── puppetlabs-stdlib (v4.12.0)
└── stahnma-epel (v1.2.2)
Next, create the directory src/puppet/modules/docker_demo:
root@ip-10-1-2-3:~# mkdir -p src/puppet/modules/docker_demo
Change over to that directory and create a puppet manifest to install docker:
root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# vi install.pp 
Now, a typical use case for managing Docker with Puppet is to customize the Docker deployment to fit your organization’s needs. Therefore, let’s use the resource syntax to have Docker installed with a custom DNS server:
class { 'docker':
dns => '8.8.8.8',
}
Save the file, running puppet parser validate against the file to ensure that there are no syntax errors:
root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# puppet parser validate install.pp
Assuming that there are no errors, run puppet apply against the manifest:
puppet apply install.pp
The output should be similar to this:
root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# puppet apply install.pp 
Warning: Scope(Apt::Source[docker]): $include_src is deprecated and will be removed in the next major release, please use $include => { 'src' => false } instead
Warning: Scope(Apt::Source[docker]): $required_packages is deprecated and will be removed in the next major release, please use package resources instead.
Warning: Scope(Apt::Source[docker]): $key_source is deprecated and will be removed in the next major release, please use $key => { 'source' => http://apt.dockerproject.org/gpg } instead.
Warning: Scope(Apt::Key[Add key: 58118E89F3A912897C070ADBF76221572C52609D from Apt::Source docker]): $key_source is deprecated and will be removed in the next major release. Please use $source instead.
Notice: Compiled catalog for ip-10-1-2-3.monzell.com in environment production in 0.80 seconds
Notice: /Stage[main]/Apt/File[preferences]/ensure: created
Notice: /Stage[main]/Apt/Apt::Setting[conf-update-stamp]/File[/etc/apt/apt.conf.d/15update-stamp]/content: content changed '{md5}b9de0ac9e2c9854b1bb213e362dc4e41' to '{md5}0962d70c4ec78bbfa6f3544ae0c41974'
Notice: /Stage[main]/Docker::Repos/Apt::Source[docker]/Apt::Key[Add key: 58118E89F3A912897C070ADBF76221572C52609D from Apt::Source docker]/Apt_key[Add key: 58118E89F3A912897C070ADBF76221572C52609D from Apt::Source docker]/ensure: created
Notice: /Stage[main]/Docker::Repos/Apt::Source[docker]/Apt::Pin[docker]/Apt::Setting[pref-docker]/File[/etc/apt/preferences.d/docker.pref]/ensure: defined content as '{md5}a38a00ab77b0ee306eba00501245d384'
Notice: /Stage[main]/Docker::Repos/Apt::Source[docker]/Apt::Setting[list-docker]/File[/etc/apt/sources.list.d/docker.list]/ensure: defined content as '{md5}c2bd5681c1fd63e3e2630128a815f799'
Notice: /Stage[main]/Apt::Update/Exec[apt_update]: Triggered 'refresh' from 1 events
Notice: /Stage[main]/Docker::Repos/Package[cgroup-lite]/ensure: created
Notice: /Stage[main]/Docker::Install/Package[linux-image-extra-3.13.0-92-generic]/ensure: created
Notice: /Stage[main]/Docker::Install/Package[docker]/ensure: created
Notice: /Stage[main]/Docker::Service/File[/etc/init.d/docker]/ensure: ensure changed 'file' to 'link'
Notice: /Stage[main]/Docker::Service/File[/etc/default/docker]/content: content changed '{md5}ddb6348855959363f63b73853c21f4d0' to '{md5}1d959149e3fc18aff355ae5a823a5dbf'
Notice: /Stage[main]/Docker::Service/Service[docker]: Triggered 'refresh' from 2 events
Notice: Applied catalog in 31.10 seconds
Managing Docker Images
We’re now ready to test by downloading an image. Within the same directory, create a file called pull_image.pp with the following content:
docker::image { 'ubuntu':
ensure => 'present',
image_tag => 'trusty'
}
This downloads an Ubuntu 14.04 image (hence the tag “trusty”).
Validate the code to ensure that there are no syntax errors:
puppet parser validate pull_image.pp
And then run it to download the image. Again, the output should look similar to the following:
root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# puppet apply pull_image.pp
Notice: Compiled catalog for ip-10-1-2-3.monzell.com in environment production in 0.23 seconds
Notice: /Stage[main]/Main/Docker::Image[ubuntu]/File[/usr/local/bin/update_docker_image.sh]/ensure: defined content as '{md5}993edb514c9469e41aab570e278c04d2'
Notice: /Stage[main]/Main/Docker::Image[ubuntu]/Exec[/usr/local/bin/update_docker_image.sh ubuntu:trusty]/returns: executed successfully
Notice: Applied catalog in 11.12 seconds
We should now be able to see the image we downloaded by running docker images:
root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu trusty f2d8ce9fa988 3 days ago 187.9 MB
With that verified, let’s delete it. Create a file called rm_image.pp, which should have the identical code except that ensure is now absent:
docker::image { 'ubuntu':
ensure => 'absent',
image_tag => 'trusty'
}
Once again, verify that there are no errors with:
puppet parser validate rm_image.pp
And then run it with puppet apply rm_image.pp:
root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# puppet apply rm_image.pp 
Notice: Compiled catalog for ip-10-1-2-3.monzell.com in environment production in 0.21 seconds
Notice: /Stage[main]/Main/Docker::Image[ubuntu]/Exec[docker rmi ubuntu:trusty]/returns: executed successfully
Notice: Applied catalog in 0.30 seconds
Now if you run docker images, you should that the image we downloaded is no longer present:
root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Running and Removing Containers
Now that we have verified Docker functionality, let’s spin up a container. Create a file in the docker_demo directory called test_run_container.pp with the following code:
docker::run { 'mycontainertest':
ensure => 'present',
image=> 'ubuntu',
command => '/bin/sh -c "while true; do echo test container sleep 1; done"',
}
This will run a container called mycontainertest using the most recent Ubuntu image (it will download the image if it is not already on the machine); then it will run a basic loop within the image.
After validating that there are no syntax errors with:
puppet parser validate test_run_container.pp
Go ahead and execute the code:
puppet apply test_run_container.pp
The output should return with the container in a running state:
Notice: Compiled catalog for ip-10-1-2-3.monzell.com in environment production in 0.28 seconds
Notice: /Stage[main]/Main/Docker::Run[mycontainertest]/File[/etc/init.d/docker-mycontainertest]/content: content changed '{md5}ec6fcdf1488159431eca235a6773ae0e' to '{md5}4f31d5c215c3f210b472299658e8f76d'
Notice: /Stage[main]/Main/Docker::Run[mycontainertest]/Service[docker-mycontainertest]/ensure: ensure changed 'stopped' to 'running'
Notice: Applied catalog in 0.62 seconds
You should be able to verify that the container is running with the docker ps –a command:
root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a62a52181b57 ubuntu "/bin/sh -c 'while tr" 59 seconds ago Up 58 seconds mycontainertest
You should also notice that the container downloaded the Ubuntu image for us:
root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest c73a085dc378 6 days ago 127.1 MB
Now we will go and remove the container. Create a file called test_remove_container.pp and insert the following code:
docker::run { 'mycontainertest':
ensure => 'absent',
image => 'ubuntu',
command => '/bin/sh -c "while true; do echo test container sleep 1; done"',
}
As you can see, the only difference is that we are now ensuring that the container is “absent” or destroyed.
Again, validate the code with:
puppet parser validate test_remove_container.pp
And then run it with:
puppet apply test_remove_container.pp
It should now remove the container, changing the state to “stopped”:
root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# puppet apply test_remove_container.pp
Notice: Compiled catalog for ip-10-1-2-3.monzell.com in environment production in 0.84 seconds
Notice: /Stage[main]/Main/Docker::Run[mycontainertest]/Service[docker-mycontainertest]/ensure: ensure changed 'running' to 'stopped'
Notice: Applied catalog in 2.79 seconds
The container should no longer be running:
root@ ip-10-1-2-3:~/src/puppet/modules/docker_demo# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
With that done, we are ready to deploy our custom image, which we will do in the final article of our series Managing Docker Containers with Puppet –Download and Deploy Custom Containers from Docker Hub
Comments are disabled for this guide.