{"id":1018,"date":"2019-04-19T18:26:55","date_gmt":"2019-04-19T15:26:55","guid":{"rendered":"https:\/\/artem.services\/?p=1018"},"modified":"2019-04-19T18:49:02","modified_gmt":"2019-04-19T15:49:02","slug":"jenkins-%d0%b4%d0%b5%d0%bf%d0%bb%d0%be%d0%b9-%d0%b2-docker-swarm-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-stack-deploy","status":"publish","type":"post","link":"https:\/\/artem.services\/?p=1018","title":{"rendered":"Jenkins &#8212; \u0414\u0435\u043f\u043b\u043e\u0439 \u0432 Docker Swarm \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f 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>\u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u0435\u043f\u043b\u043e\u044f \u0432 <strong>Docker Swarm<\/strong> \u0441 <strong>Jenkins<\/strong>&#39;\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <strong>stack deploy<\/strong>.<\/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>\u0414\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f <strong>Nginx<\/strong>&#39;\u0430 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 <strong>Load Balancer<\/strong>&#39;\u0430, \u0435\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 <strong>namespace<\/strong> \u0441 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u043c\u0438. \u0414\u043b\u044f \u0441\u0432\u044f\u0437\u043d\u043e\u0441\u0442\u0438 \u0432 \u0444\u0430\u0439\u043b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 <strong>nginx.conf<\/strong> \u0432 \u0431\u043b\u043e\u043a &quot;<strong>http<\/strong>&quot; \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/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>\u0418 \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u0436\u0435 \u043f\u043e \u0438\u043c\u0435\u043d\u0430\u043c \u0430\u043f\u0441\u0442\u0440\u0438\u043c\u043e\u0432.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u0435\u043f\u043b\u043e\u044f \u0432 Docker Swarm \u0441 Jenkins&#39;\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f 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":[37],"tags":[39,4,81,749,125,751],"_links":{"self":[{"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/posts\/1018"}],"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=1018"}],"version-history":[{"count":6,"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/posts\/1018\/revisions"}],"predecessor-version":[{"id":1024,"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/posts\/1018\/revisions\/1024"}],"wp:attachment":[{"href":"https:\/\/artem.services\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1018"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/artem.services\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1018"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/artem.services\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1018"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}