Managing Docker with Puppet Series – Download and Deploy Custom Containers from Docker Hub

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. Then, we wrote some puppet code to deploy images and containers, Puppet in Part 2 – Writing Puppet code to Manage Containers. Now we will finish what we started in Part 3 – Download and Deploy Custom Containers from Docker Hub.


Deploying and Destroying Custom Docker Containers

A notable use case with Puppet and Docker is to configure the host server to use alternate repositories. This makes it very useful to deploy internal applications that should remain private. This is one way you can do it.

Create a file called pull_from_private_registry.pp with this code:

docker::registry { ' https://index.docker.io/v1/:
username => ‘myusername’,
password => ‘mypassword’,
email => ‘myusername@example.com’,
}

docker::image { ‘rilindo/myapacheweb’:
ensure => ‘present’,
image_tag => ‘v1’,
}

What this will do is configure Docker to login to Docker Hub and then download the image we customized and stored in our private repository.

IMPORTANT: As an aside, credentials should not be stored in plaintext within code. We suggest that you should use secrets tool to encrypt your credentials within Puppet. Here is one tool based on hiera:

https://github.com/TomPoulton/hiera-eyaml

In any case, once you are done, verify that the there are no syntax errors with:

puppet parser validate pull_from_private_image.pp

Run puppet apply against the code:

root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# puppet apply pull_from_private_registry.pp 

The resulting output should look like this:

Notice: Compiled catalog for ip-10-1-2-3.monzell.com in environment production in 0.22 seconds
Notice: /Stage[main]/Main/Docker::Registry[https://index.docker.io/v1/]/Exec[https://index.docker.io/v1/ auth]/returns: executed successfully
Notice: /Stage[main]/Main/Docker::Image[rilindo/myapacheweb]/Exec[/usr/local/bin/update_docker_image.sh rilindo/myapacheweb:v1]/returns: executed successfully
Notice: Applied catalog in 24.03 seconds

You should be able to verify that the image is downloaded by running docker images:

root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
rilindo/myapacheweb v1 238570161601 3 days ago 485.4 MB
ubuntu latest c73a085dc378 3 days ago 127.1 MB

At this point, we will now create a new container from that image and expose access on port 80 with the following code:

docker::run { 'mywebserver':
ensure => 'present',
image => 'rilindo/myapacheweb:v1',
ports => '80',
expose => '80',
}

Save the code in the file run_container.pp and after verifying that there are no syntax errors, run it with:

puppet apply run_container.pp

The output should look like this:

root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# puppet apply run_container.pp
Notice: Compiled catalog for ip-10-1-2-3.monzell.com in environment production in 0.24 seconds
Notice: /Stage[main]/Main/Docker::Run[mywebserver]/Service[docker-mywebserver]/ensure: ensure changed 'stopped' to 'running'
Notice: Applied catalog in 0.29 seconds

Run docker ps –a to verify that it is running:

root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7d0ac5730696 rilindo/myapacheweb:v1 "/bin/sh -c 'apachect" 4 seconds ago Up 3 seconds 0.0.0.0:32770->80/tcp mywebserver

Retrieve the IP of the container with docker inspect:

root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# docker inspect mywebserver | grep -i ipaddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
"IPAddress": "172.17.0.2",

And then use curl or another http utility to verify that you can view the custom page

root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# curl 172.17.0.2:80
This is a custom index file built during the image creation

With that done, we can now finish by tearing down the container. Create a file called remove_container.pp with the following code:

docker::run { 'mywebserver':
ensure => 'absent',
image => 'rilindo/myapacheweb:v1',
ports => '80',
expose => '80',
}

Once again, verify that there are no syntax errors, then run it. The output should look like this:

root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# puppet apply remove_container.pp 
Notice: Compiled catalog for ip-10-1-2-3.monzell.com in environment production in 0.24 seconds
Notice: /Stage[main]/Main/Docker::Run[mywebserver]/Service[docker-mywebserver]/ensure: ensure changed 'running' to 'stopped'
Notice: Applied catalog in 0.18 seconds

At this point, you should be able to verify that the container has been destroyed:

root@ip-10-1-2-3:~/src/puppet/modules/docker_demo# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
root@ip-10-1-2-3:~/src/puppet/modules/docker_demo#

This is how you can manage Docker Containers with Puppet.

Looking for team training?