<!-- TITLE: Parallel Deploy To Swarm -->
<!-- SUBTITLE: The art of parallel deploy to SWARM -->
# Parallel Deploy to SWARM. Pipeline
The following pipeline example allows to deploy SWARM services in parallel which saves a lot of time comparing to
```groovy
node {
def repo = "$env.backend_repo";
def configs = "$env.deploy_repo";
def creds = "github-ssh";
def branch = (env.gitlabMergeRequestLastCommit) ? env.gitlabMergeRequestLastCommit : "${env.BRANCH}";
def project = "$env.project";
def project_hub = "$env.docker_hub";
def image_tag = (env.environment == 'staging') ? "latest" : "prod";
def envs = [];
stage ("Get app code") {
dir ("build") {
checkout scm: [$class: 'GitSCM',
userRemoteConfigs: [[url: "${repo}", credentialsId: "github-ssh"]],
branches: [[name: "${branch}"]]], changelog: false, poll: false
}
}
stage("Get configs") {
dir("deploy") {
checkout scm: [$class: 'GitSCM',
userRemoteConfigs: [[url: "${configs}", credentialsId: "github-ssh"]],
branches: [[name: "master"]]], changelog: false, poll: false
}
dir('build') {
//Get .env file
configFileProvider(
[configFile(fileId: "${env.environment}-docker-env", variable: 'envs')]) {
sh 'cp ${envs} ./.env';
}
for (String i : readFile('.env').split("\r?\n")) {
if(i != "") {
envs.push(i);
}
}
sh "cp ../deploy/dockerfiles/Backend.Dockerfile ./Backend.Dockerfile";
sh "cp ../deploy/configs/default_nginx.conf ./config/default_nginx.conf";
sh "cp ../deploy/dockerfiles/Proxy.Dockerfile ./Proxy.Dockerfile"
sh "cp ../deploy/dockerfiles/Test.Dockerfile ./Test.Dockerfile";
sh "cp ../deploy/configs/database.yml ./config/database.yml";
sh "cp ../deploy/configs/entrypoint.sh ./entrypoint.sh";
sh "cp ../deploy/docker-compose.docs.yml ./docker-compose.docs.yml";
sh "cp ../deploy/dockerfiles/Static.Dockerfile ./Static.Dockerfile";
}
}
//build container
if(env.BUILD_DOCS == 'yes') {
stage ("Generate Docs"){
dir ("build") {
def customImage = docker.build("backend:docs", "-f Test.Dockerfile .");
def current_dir = pwd();
configFileProvider(
[configFile(fileId: 'test-docker-env', variable: 'envs')]) {
sh 'cp ${envs} ./.env';
sh "docker-compose -f docker-compose.docs.yml up -d";
def test_container = docker.image('backend:docs');
test_container.inside("--env-file=${current_dir}/.env --network=build_docs") {
sh "bundle exec rails db:drop db:create RAILS_ENV=test";
sh "bundle exec rake docs:generate SIMPLECOV=false";
}
sh "docker-compose -f docker-compose.docs.yml stop";
}
}
}
}
stage ("Build App") {
dir ("build") {
withCredentials([file(credentialsId: 'cloudfront-key', variable: 'FILE')]) {
sh "rm -f ./.cfk";
sh 'cp $FILE ./.cfk';
sh "chmod 644 .cfk";
}
configFileProvider(
[configFile(fileId: "${env.environment}-docker-env", variable: 'envs')]) {
sh 'cp ${envs} ./.env';
def customImage = docker.build ("${project_hub}/${project}/backend:${image_tag}", "-f Backend.Dockerfile .");
sh "docker push ${project_hub}/${project}/backend:${image_tag}";
def staticImage = docker.build ("${project_hub}/${project}/backend_static:${image_tag}", "-f Static.Dockerfile .");
sh "docker push ${project_hub}/${project}/backend_static:${image_tag}";
}
}
}
stage("Deploy app") {
shCommand("sudo docker pull ${project_hub}/${project}/backend:${image_tag}");
shCommand("sudo docker pull ${project_hub}/${project}/backend_static:${image_tag}");
def jenvs = envs.join(" --env-add ");
def services = ["backend", "sidekiq", "rpc", "ws"]
parallel rolling_update(services, jenvs, image_tag)
}
dir("build") {
GIT_COMMIT = sh (
script: 'git rev-parse --short HEAD',
returnStdout: true
).trim()
wrap([$class: 'BuildUser']) {
sh """curl https://api.rollbar.com/api/1/deploy/ \
-F access_token=${env.ROLLBAR_KEY} \
-F environment=${env.environment} \
-F revision=${GIT_COMMIT} \
-F local_username=${BUILD_USER}"""
sh 'echo "${BUILD_USER}"'
}
}
}
def rolling_update(services, jenvs, image_tag) {
def buildParallelMap = [:]
for (name in services) {
buildParallelMap.put(name, update(name, jenvs, image_tag))
}
buildParallelMap.put("static", update_static(image_tag))
return buildParallelMap
}
def update(name, jenvs, image_tag) {
return {
shCommand("sudo docker service update --env-add ${jenvs} --force --image ${env.docker_hub}/${env.project}/backend:${image_tag} ${env.project}_${name}");
}
}
def update_static(image_tag) {
return {
shCommand("sudo docker service update --force --image ${env.docker_hub}/${env.project}/backend_static:${image_tag} ${env.project}_static");
}
}
def shCommand(command) {
sshagent (credentials: ['ssh-key']) {
def ip = (env.environment == 'staging') ? env.dev_ip : env.prod_ip
sh "ssh -o StrictHostKeyChecking=no -l $env.user $ip $command"
}
}
```