{"id":1032,"date":"2019-04-19T18:26:55","date_gmt":"2019-04-19T15:26:55","guid":{"rendered":"https:\/\/artem.services\/?p=1018"},"modified":"2019-04-23T17:03:09","modified_gmt":"2019-04-23T14:03:09","slug":"jenkins-d0-b4-d0-b5-d0-bf-d0-bb-d0-d0-b9-d0-d1-81-docker-swarm-d0-be-b8-bb-d1-d0-bf-d0-d1-83-d1-d0-8c-d0","status":"publish","type":"post","link":"https:\/\/artem.services\/?p=1032&lang=en","title":{"rendered":"Jenkins &#8212; Deploy in Docker Swarm using Stack Deploy"},"content":{"rendered":"<p><img loading=\"lazy\" class=\"size-full wp-image-819 aligncenter\" src=\"https:\/\/artem.services\/wp-content\/uploads\/2019\/02\/Jenkins-Logo.png\" alt=\"\" width=\"1280\" height=\"412\" srcset=\"https:\/\/artem.services\/wp-content\/uploads\/2019\/02\/Jenkins-Logo.png 1280w, https:\/\/artem.services\/wp-content\/uploads\/2019\/02\/Jenkins-Logo-300x97.png 300w, https:\/\/artem.services\/wp-content\/uploads\/2019\/02\/Jenkins-Logo-768x247.png 768w, https:\/\/artem.services\/wp-content\/uploads\/2019\/02\/Jenkins-Logo-1024x330.png 1024w, https:\/\/artem.services\/wp-content\/uploads\/2019\/02\/Jenkins-Logo-954x307.png 954w\" sizes=\"(max-width: 1280px) 100vw, 1280px\" \/><\/p>\n<p><span class=\"tlid-translation translation\" lang=\"en\"><span class=\"\" title=\"\">An example deployment in <strong>Docker Swarm<\/strong> from <strong>Jenkins<\/strong> using <strong>stack deploy<\/strong>.<\/span><\/span><\/p>\n<h3>Jenkinsfile:<\/h3>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\npipeline {\r\n    agent any\r\n    environment {\r\n        PROJECT_NAME = 'artem-api'\r\n        SLACK_CHANNEL = 'maintenance-artem-api'\r\n        SWARM_MANAGER_IP = '8.8.8.8'\r\n        SWARM_WORKER_1_IP = '1.1.1.1'\r\n        SWARM_WORKER_2_IP = '2.2.2.2'\r\n        TLS_CA = '\/var\/lib\/jenkins\/TLS\/swarm\/ca.pem'\r\n        TLS_CERT = '\/var\/lib\/jenkins\/TLS\/swarm\/cert.pem'\r\n        TLS_KEY = '\/var\/lib\/jenkins\/TLS\/swarm\/key.pem'\r\n        ECR = '111111111111.dkr.ecr.us-west-1.amazonaws.com\/artem'\r\n        PROFILE = 'artem'\r\n    }\r\n    stages {\r\n        stage ('Auth to AWS ECR.') {\r\n            steps {\r\n                sh &quot;echo 'Auth to image repo'&quot;\r\n                sh &quot;eval \\$(aws ecr get-login --profile ${PROFILE} --no-include-email) &amp;&gt;\/dev\/null&quot;\r\n            }\r\n        }\r\n        stage ('Build image'){\r\n            steps{\r\n                script{\r\n                    withDockerServer([uri:'tcp:\/\/127.0.0.1:4243']) {\r\n                        sh &quot;cp .\/.jenkins\/Dockerfile .\/Dockerfile&quot;\r\n                        echo &quot;Debug: Building  with ${ECR}:${PROJECT_NAME}-${JOB_BASE_NAME}-${BUILD_NUMBER}&quot;\r\n                        def image = docker.build (&quot;${ECR}:${PROJECT_NAME}-${JOB_BASE_NAME}-${BUILD_NUMBER}&quot;)\r\n                        image.push ()\r\n                        echo &quot;Debug: After push to registry&quot;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        stage ('Update API on Staging') {\r\n            when { branch 'staging' }\r\n            steps {\r\n                sh 'envsubst &lt; &quot;.jenkins\/Staging.yml&quot; &gt; &quot;Staging.yml&quot;'\r\n                sh &quot;ssh ubuntu@${SWARM_WORKER_1_IP} 'sudo docker pull ${ECR}:${PROJECT_NAME}-${JOB_BASE_NAME}-${BUILD_NUMBER}'&quot;\r\n                sh &quot;ssh ubuntu@${SWARM_WORKER_2_IP} 'sudo docker pull ${ECR}:${PROJECT_NAME}-${JOB_BASE_NAME}-${BUILD_NUMBER}'&quot;\r\n                sh &quot;docker -H tcp:\/\/${SWARM_MANAGER_IP}:2376 --tlsverify --tlscacert=${TLS_CA} --tlscert=${TLS_CERT} --tlskey=${TLS_KEY} stack deploy --compose-file Staging.yml artem-api&quot;\r\n            }\r\n        }\r\n        stage ('Update API on Production') {\r\n            when { branch 'production' }\r\n            steps {\r\n                sh 'envsubst &lt; &quot;.jenkins\/Production.yml&quot; &gt; &quot;Production.yml&quot;'\r\n                sh &quot;ssh ubuntu@${SWARM_WORKER_1_IP} 'sudo docker pull ${ECR}:${PROJECT_NAME}-${JOB_BASE_NAME}-${BUILD_NUMBER}'&quot;\r\n                sh &quot;ssh ubuntu@${SWARM_WORKER_2_IP} 'sudo docker pull ${ECR}:${PROJECT_NAME}-${JOB_BASE_NAME}-${BUILD_NUMBER}'&quot;\r\n                sh &quot;docker -H tcp:\/\/${SWARM_MANAGER_IP}:2376 --tlsverify --tlscacert=${TLS_CA} --tlscert=${TLS_CERT} --tlskey=${TLS_KEY} stack deploy --compose-file Production.yml artem-api&quot;\r\n            }\r\n        }\r\n    }\r\n    post {\r\n        success {\r\n            slackSend channel: &quot;${SLACK_CHANNEL}&quot;, color: 'good', message: &quot;Job: ${JOB_NAME}${BUILD_NUMBER} build was successful.&quot;\r\n        }\r\n        failure {\r\n            slackSend channel: &quot;${SLACK_CHANNEL}&quot;, color: 'danger', message: &quot;Job: ${JOB_NAME}${BUILD_NUMBER} was finished with some error. It may occurs because of the build was rollbacked by docker swarm, or because of other error (watch the Jenkins Console Output): ${JOB_URL}${BUILD_ID}\/consoleFull&quot;\r\n        }\r\n        unstable {\r\n            slackSend channel: &quot;${SLACK_CHANNEL}&quot;, color: 'warning', message: &quot;Job: ${JOB_NAME}${BUILD_NUMBER} was finished with some error. Please watch the Jenkins Console Output: ${JOB_URL}${BUILD_ID}\/console.&quot;\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p><!--more--><\/p>\n<h3>Production.yml<\/h3>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nversion: '3.7'\r\n\r\nservices:\r\n  production:\r\n    image: ${ECR}:${PROJECT_NAME}-${JOB_BASE_NAME}-${BUILD_NUMBER}\r\n    deploy:\r\n      replicas: 2\r\n        update_config:\r\n          parallelism: 1\r\n          delay: 30s\r\n      placement:\r\n        constraints:\r\n          - node.labels.env == production\r\n    volumes:\r\n      - &quot;\/var\/docker\/api\/production:\/usr\/src\/app\/storage&quot;\r\n    environment:\r\n      SERVER_URL: &quot;api.artem.service&quot;\r\n    ports:\r\n      - 8080:80\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h3>Staging.yml<\/h3>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nversion: '3.7'\r\n\r\nservices:\r\n  staging:\r\n    image: ${ECR}:${PROJECT_NAME}-${JOB_BASE_NAME}-${BUILD_NUMBER}\r\n    deploy:\r\n      replicas: 2\r\n        update_config:\r\n          parallelism: 1\r\n          delay: 30s\r\n      placement:\r\n        constraints:\r\n          - node.labels.env == staging\r\n    volumes:\r\n      - &quot;\/var\/docker\/api\/staging:\/usr\/src\/app\/storage&quot;\r\n    environment:\r\n      SERVER_URL: &quot;stg.api.artem.service&quot;\r\n    ports:\r\n      - 8081:80\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><span class=\"tlid-translation translation\" lang=\"en\"><span class=\"\" title=\"\">To use <strong>Nginx<\/strong> as a <strong>Load Balancer<\/strong>, you need to add it to the <strong>namespace<\/strong> with the other containers.<\/span> <span class=\"\" title=\"\">For connectivity, add the following to the &quot;<strong>http<\/strong>&quot; block in the <strong>nginx.conf<\/strong> configuration file:<\/span><\/span><\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\n    upstream production {\r\n        server artem-api_production;\r\n    }\r\n\r\n    upstream staging {\r\n    \tserver artem-api_staging;\r\n    }\r\n<\/pre>\n<p><span class=\"tlid-translation translation\" lang=\"en\"><span class=\"\" title=\"\">And proxy already by the names of upstream.<\/span><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>An example deployment in Docker Swarm from Jenkins using stack deploy. Jenkinsfile:<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[613],"tags":[615,771,773,775,617,777],"_links":{"self":[{"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/posts\/1032"}],"collection":[{"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/artem.services\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1032"}],"version-history":[{"count":2,"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/posts\/1032\/revisions"}],"predecessor-version":[{"id":1037,"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/posts\/1032\/revisions\/1037"}],"wp:attachment":[{"href":"https:\/\/artem.services\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1032"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/artem.services\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1032"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/artem.services\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1032"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}