{"id":28829,"date":"2015-10-25T00:41:15","date_gmt":"2015-10-24T19:11:15","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=28829"},"modified":"2016-01-19T13:29:21","modified_gmt":"2016-01-19T07:59:21","slug":"automated-docker-deployment-using-jenkins","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/automated-docker-deployment-using-jenkins\/","title":{"rendered":"Automated Docker Deployment using Jenkins"},"content":{"rendered":"<p>Building a Docker image from a Dockerfile, creating a latest tag and pushing it on DockerHub are equivalent to executing three different commands manually. This could be automated by creating a bash script.<\/p>\n<p>Well, that was not a big deal until I had a requirement where I needed to perform above actions and additional task of immediately triggering a &#8220;deployment job&#8221; already configured on Jenkins. The deployment job performs <a title=\"Docker DevOps\" href=\"http:\/\/www.tothenew.com\/devops-chef-puppet-docker\">application deployment using recently updated Docker<\/a> image on desired servers running in my pre-production environment. So I needed something with which I could perform my task through Jenkins rather than running commands\/scripts on a shell. Since I am already using some Jenkins plugins in the current deployment job, so rather than creating a new deployment job I want to leverage the existing job.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-28850 aligncenter\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/docker-jenkins.png\" alt=\"docker-jenkins\" width=\"627\" height=\"302\" \/><\/p>\n<p>In this quest, I came across a couple of Jenkins plugins provided by CloudBees which seemed perfect for this task. These plugins install\u00a0\u201c<strong>Docker Commons Plugin<\/strong>\u201d which provides a base functionality for Docker related plugins.<\/p>\n<p><strong>CloudBees Docker Build and Publish plugin<\/strong>: It enables us to build images from the Dockerfile present on the server and publishing them on the DockerHub.<br \/>\n<strong>CloudBees DockerHub Notification<\/strong>: It enables us to trigger one or more Jenkins job by making use of DockerHub\u2019s web hook, thus creating a continuous delivery pipeline. Whenever a new image\u00a0is pushed, the configured Jenkins job will receive\u00a0notification as web hook and triggers the job.<\/p>\n<hr \/>\n<p><strong>Scenario:<\/strong> One click automation of a process of building image from Dockerfile, pushing it on DockerHub and immediately triggering a Jenkins deployment job based on the pushed docker image.<\/p>\n<hr \/>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-28849 aligncenter\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Jenkins-CloudBees.png\" alt=\"Jenkins-CloudBees\" width=\"506\" height=\"295\" \/><\/p>\n<p>&nbsp;<\/p>\n<ol>\n<ol>\n<li><strong>Installing Plugins:<\/strong><br \/>\nInstall the above two plugins using Jenkins\u2019 \u201c<strong>Plugin Manager<\/strong>\u201d.<\/li>\n<li><strong>Creating and configuring Jenkins job to build images from Dockerfile:<\/strong><br \/>\nCreate a new Jenkins job (say &#8220;<em>Build Docker Image<\/em>&#8220;) which will use <em>CloudBees Docker Build and Publish plugin<\/em> to build images from Dockerfile and push it on DockerHub.<br \/>\nConfigure this job as follows under the build section:<br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"wp-image-28832 aligncenter\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Jenkins1-1.png\" alt=\"Jenkins1\" width=\"628\" height=\"312\" \/><br \/>\nVarious fields in the above image are explained below:<\/p>\n<ul>\n<li><strong>Repository Name<\/strong>: <strong><span style=\"font-weight: 400;\">As shown we have passed \u201cnavjotsingh\/custom-image\u201d as the repository name.<\/span><\/strong><\/li>\n<li><strong><b>Tag<\/b><span style=\"font-weight: 400;\">: We are passing \u201cv1.0\u201d as tag or version. We can make this build parametrized and pass custom repository name and tag as two parameters to this job.<\/span><\/strong><\/li>\n<li><strong><b>Docker Host URI<\/b><span style=\"font-weight: 400;\">: Our Docker host is on the same machine where Jenkins is installed, so we are using default Docker \u2018s default URI by keeping this field empty.<\/span><\/strong><\/li>\n<li><strong><b>Server credentials<\/b><span style=\"font-weight: 400;\">: Provide user\u2019s credentials who has permission to run Docker commands and have permission to use Docker\u2019s socket \u201c\/var\/run\/docker.sock\u201d. I have provided permission to Jenkins\u2019 user.<\/span><\/strong><\/li>\n<li><strong><b>Docker registry URL<\/b><span style=\"font-weight: 400;\">: We are using public DockerHub registry so we have left \u201cDocker registry URL\u201d field empty.<\/span><\/strong><\/li>\n<li><strong><b>Registry credentials<\/b><span style=\"font-weight: 400;\">: Click \u201cAdd\u201d to add the DockerHub account credentials.<\/span><\/strong><\/li>\n<li><strong><span style=\"font-weight: 400;\">As we can see there are various options provided by this plugin wherein we can choose to <\/span><b>skip push, no cache, force pull and skip build<\/b><span style=\"font-weight: 400;\">.<\/span><\/strong><\/li>\n<li><strong><span style=\"font-weight: 400;\">This plugin creates <\/span><b>fingerprints<\/b><span style=\"font-weight: 400;\"> after building image and are managed by Docker Commons Plugin (installed with this plugin).<\/span><\/strong><\/li>\n<li><strong><span style=\"font-weight: 400;\">Decorating the build name means builds will be decorated with the repository name and tag name. We can skip it by checking \u201c<\/span><b>Skip Decorate<\/b><span style=\"font-weight: 400;\">\u201d check box.<\/span><\/strong><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-28835 aligncenter\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Jenkins6.png\" alt=\"Jenkins6\" width=\"547\" height=\"52\" \/><\/li>\n<li><span style=\"font-weight: 400;\"><strong>Skip tag as latest<\/strong>: If it is unchecked, it will create additional tag \u201clatest\u201d of the currently build image and push it on DockerHub as can be seen in the above image.<\/span><\/li>\n<li><strong><strong><span style=\"font-weight: 400;\"><strong>Docker Directory is in<\/strong>: The directory which contain the Dockerfile can be specified in this field otherwise it will try to fetch the Dockerfile from the Job\u2019s workspace.<\/span><\/strong><\/strong><\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<\/ol>\n<p>&nbsp;<\/p>\n<ul>\n<li><strong>Modifying existing Deployment Job to be triggered immediately after building image:<\/strong><br \/>\nNow we will modify the existing deployment job which we need to be executed whenever that Docker image is updated. We will achieve it by using <strong>CloudBees Docker Hub Notification plugin<\/strong>.<br \/>\nConfigure the deployment job under \u201cBuild Triggers\u201d as follows:<img decoding=\"async\" loading=\"lazy\" class=\"wp-image-28836 aligncenter\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Jenkins7.png\" alt=\"Jenkins7\" width=\"610\" height=\"171\" \/><br \/>\nSelect \u201c<strong>Monitor Docker Hub image changes<\/strong>\u201d, under this select \u201c<strong>Any referenced Docker image can trigger this job<\/strong>\u201d. We can make this job to be triggered on specified repositories by selecting \u201c<strong>Specified repositories will trigger this job<\/strong>\u201d and specifying repository name against \u201c<strong>Repositories<\/strong>&#8221; field. <span style=\"text-decoration: underline;\">Multiple repositories can be specified in the text field, one repository per line.<br \/>\n<\/span>Now, we have configured our deployment job to be triggered if any new image gets available in navjotsingh\/custom-image repository.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ol>\n<li><strong>Configuring webhook in DockerHub:<\/strong><br \/>\nNow, we need to configure webhook for our Jenkins server in the DockerHub as follows:<\/p>\n<ul>\n<li>Login to your DockerHub account.<\/li>\n<li>Select the repository which is \u201cnavjotsingh\/custom-image\u201d in our case.<\/li>\n<li>Click on \u201cWebhooks\u201d and then on &#8220;Add Webhook&#8221;.<img decoding=\"async\" loading=\"lazy\" class=\"wp-image-28838 aligncenter\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Jenkins3.png\" alt=\"Jenkins3\" width=\"568\" height=\"130\" \/><\/li>\n<li>Provide your favourite Webhook name under \u201c Webhook Name\u201d field (say Jenkins Webhook).<\/li>\n<li>Provide below URL under \u201cHook URL 0\u201d.<br \/>\nURL: http:\/\/\/dockerhub-webhook\/notify<\/li>\n<li>Click \u201cAdd URL\u201d as shown below:<br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-28839 aligncenter\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/10\/Jenkins8.png\" alt=\"Jenkins8\" width=\"433\" height=\"293\" \/><\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>That\u2019s all! We have completed the whole configuration to get our scenario working.<\/p>\n<p><strong>Summary<\/strong>: Upon our single click to start \u201cBuild Docker Image\u201d job, as a new image will be created from provided Dockerfile and pushed on to DockerHub. The new image pushed on DockerHub will trigger webhook notification to Jenkins server and this will trigger our \u201cDeployment Job\u201d to perform the deployment based on this new Docker image.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Building a Docker image from a Dockerfile, creating a latest tag and pushing it on DockerHub are equivalent to executing three different commands manually. This could be automated by creating a bash script. Well, that was not a big deal until I had a requirement where I needed to perform above actions and additional task [&hellip;]<\/p>\n","protected":false},"author":154,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":43},"categories":[1174,2348],"tags":[1853,2650,2414,1891,1883,2594,1682,2649],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/28829"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/154"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=28829"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/28829\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=28829"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=28829"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=28829"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}