Step 2 - Deploy Environments
Now that our image is in Artifactory, we need to deploy it. In this step, we add deployment stages for Dev, QA, and Prod environments.
Jenkinsfile¶
Here is the Jenkinsfile for this step. Source code: 30-02-Jenkinsfile-docker-deploy-jfrog.
pipeline {
agent any
options {
disableConcurrentBuilds()
disableResume()
buildDiscarder(logRotator(numToKeepStr: '10'))
timeout(time: 1, unit: 'HOURS')
}
parameters {
choice(name: 'ENVIRONMENT', choices: ['dev', 'qa', 'prod'], description: 'Choose Environment')
string(name: 'IMAGE_TAG', defaultValue: '1.0', description: 'Docker image tag')
}
environment {
DOCKER_CREDENTIAL_ID = "jfrog-credential"
SSH_CREDENTIAL_ID = "ssh-pass-credential"
DOCKER_REGISTRY = "vigneshsweekaran.jfrog.io"
DOCKER_REPOSITORY = "docker-helloworld-local"
IMAGE_NAME = "hello-world-java"
IMAGE_TAG = "${params.IMAGE_TAG}"
CONTAINER_NAME = "hello-world-java"
HOST_PORT = "8080"
CONTAINER_PORT = "8080"
}
stages {
stage ('Deploy to Dev') {
when {
environment name: "ENVIRONMENT", value: "dev"
}
steps {
script {
withCredentials([usernamePassword(credentialsId: "${SSH_CREDENTIAL_ID}", passwordVariable: 'SSH_PASSWORD', usernameVariable: 'SSH_USERNAME')]) {
def remote = [:]
remote.name = 'test'
remote.host = '20.193.155.41'
remote.user = "${SSH_USERNAME}"
remote.password = "${SSH_PASSWORD}"
remote.allowAnyHosts = true
withCredentials([usernamePassword(credentialsId: "${DOCKER_CREDENTIAL_ID}", passwordVariable: 'DOCKER_PASSWORD', usernameVariable: 'DOCKER_USERNAME')]) {
sshCommand remote: remote, command: "docker rm -f ${CONTAINER_NAME} || true && echo ${DOCKER_PASSWORD} | docker login ${DOCKER_REGISTRY} -u ${DOCKER_USERNAME} --password-stdin && docker run -d --name ${CONTAINER_NAME} -p ${HOST_PORT}:${CONTAINER_PORT} ${DOCKER_REGISTRY}/${DOCKER_REPOSITORY}/${IMAGE_NAME}:${IMAGE_TAG} && docker logout ${DOCKER_REGISTRY}"
}
}
}
}
}
stage ('Deploy to Qa') {
when {
environment name: "ENVIRONMENT", value: "qa"
}
steps {
script {
withCredentials([usernamePassword(credentialsId: "${SSH_CREDENTIAL_ID}", passwordVariable: 'SSH_PASSWORD', usernameVariable: 'SSH_USERNAME')]) {
def remote = [:]
remote.name = 'test'
remote.host = '20.197.20.30'
remote.user = "${SSH_USERNAME}"
remote.password = "${SSH_PASSWORD}"
remote.allowAnyHosts = true
withCredentials([usernamePassword(credentialsId: "${DOCKER_CREDENTIAL_ID}", passwordVariable: 'DOCKER_PASSWORD', usernameVariable: 'DOCKER_USERNAME')]) {
sshCommand remote: remote, command: "docker rm -f ${CONTAINER_NAME} || true && echo ${DOCKER_PASSWORD} | docker login ${DOCKER_REGISTRY} -u ${DOCKER_USERNAME} --password-stdin && docker run -d --name ${CONTAINER_NAME} -p ${HOST_PORT}:${CONTAINER_PORT} ${DOCKER_REGISTRY}/${DOCKER_REPOSITORY}/${IMAGE_NAME}:${IMAGE_TAG} && docker logout ${DOCKER_REGISTRY}"
}
}
}
}
}
stage ('Deploy to Prod') {
when {
environment name: "ENVIRONMENT", value: "prod"
}
steps {
script {
withCredentials([usernamePassword(credentialsId: "${SSH_CREDENTIAL_ID}", passwordVariable: 'SSH_PASSWORD', usernameVariable: 'SSH_USERNAME')]) {
def remote = [:]
remote.name = 'test'
remote.host = '20.197.20.178'
remote.user = "${SSH_USERNAME}"
remote.password = "${SSH_PASSWORD}"
remote.allowAnyHosts = true
withCredentials([usernamePassword(credentialsId: "${DOCKER_CREDENTIAL_ID}", passwordVariable: 'DOCKER_PASSWORD', usernameVariable: 'DOCKER_USERNAME')]) {
sshCommand remote: remote, command: "docker rm -f ${CONTAINER_NAME} || true && echo ${DOCKER_PASSWORD} | docker login ${DOCKER_REGISTRY} -u ${DOCKER_USERNAME} --password-stdin && docker run -d --name ${CONTAINER_NAME} -p ${HOST_PORT}:${CONTAINER_PORT} ${DOCKER_REGISTRY}/${DOCKER_REPOSITORY}/${IMAGE_NAME}:${IMAGE_TAG} && docker logout ${DOCKER_REGISTRY}"
}
}
}
}
}
}
post {
always {
deleteDir()
}
}
}
Detailed Explanation¶
Environment Block¶
IMAGE_TAG: Taken from theparams.IMAGE_TAGparameter, allowing you to deploy any specific version, not just the latest.CONTAINER_NAME: Defined as a variable to ensure consistent naming across all environments.
Deployment Stages¶
Each stage (Dev, QA, Prod) works identically but targets a different server IP:
1. when Condition: Checks the ENVIRONMENT parameter to decide if this stage should run.
2. sshCommand:
- Connects to the remote server using SSH credentials.
- Removes any existing container with the same name.
- Logs into the JFrog registry.
- Runs the new container image.
- Logs out for security.
Important Tips¶
Tip
Notice how we use || true after docker rm. This prevents the pipeline from failing if the container doesn't exist (e.g., on the very first deployment).
Next Step: Trigger Downstream Jobs
Quick Quiz¶
Quick Quiz¶
Which Jenkins pipeline directive allows you to prompt the user for input before the build?
Which step is used to execute commands on a remote server via SSH?
What does the when directive do in a stage?
📬 DevopsPilot Weekly — Learn DevOps, Cloud & Gen AI the simple way.
👉 Subscribe here