Creating A Basic Jenkins Pipeline
This tutorial is tied to this template GitHub repository I created, for projects that require a Jenkins Pipeline.
Required Plugins
- Config File Provider
- Docker Slaves
- Docker
- Docker Pipeline
- Pipeline Utility Steps - for readJSON
- SSH Agent
Steps
Create your repository, or clone the the template on GitHub I created.
Create one of each of the following files (you will see they already exist in the template repository):
- Jenkinsfile
- Dockerfile
Create branches for production
and staging
git branch production && git push -u origin production
git branch staging && git push -u origin staging
Create a project access token and use that in the url for authentication before plugging into jenkins.
Fill the Jenkinsfile with the following content:
pipeline {
agent none
stages {
stage("build") {
agent {
docker { image 'docker:dind' }
}
steps {
echo "building docker image..."
configFileProvider([configFile(fileId: 'fc6ad96f-c364-4b59-b24b-5eddee5b41f6', variable: 'BRANCH_SETTINGS')]) {
echo "Branch ${env.BRANCH_NAME}"
echo "Branch Settings: ${BRANCH_SETTINGS}"
script {
def config = readJSON file:"$BRANCH_SETTINGS"
def branchConfig = config."${env.BRANCH_NAME}"
if (branchConfig) {
echo "using config for branch ${env.BRANCH_NAME}"
def DOCKER_REGISTRY = branchConfig.DOCKER_REGISTRY
def dockerImage = docker.build(branchConfig.IMAGE_NAME)
docker.withRegistry("https://${branchConfig.DOCKER_REGISTRY}", 'docker-registry-credentials') {
dockerImage.push("${env.BUILD_NUMBER}")
dockerImage.push("latest")
}
}
else {
error("Build failed because failed to fetch settings for branch")
}
}
}
}
}
stage("deploy") {
agent {
docker { image 'ubuntu:focal' }
}
steps {
sh "apt-get update && apt-get install ssh -y"
configFileProvider([configFile(fileId: 'fc6ad96f-c364-4b59-b24b-5eddee5b41f6', variable: 'BRANCH_SETTINGS')]) {
echo "Branch ${env.BRANCH_NAME}"
echo "Branch Settings: ${BRANCH_SETTINGS}"
script {
def config = readJSON file:"$BRANCH_SETTINGS"
def branchConfig = config."${env.BRANCH_NAME}"
if (branchConfig) {
echo "using config for branch ${env.BRANCH_NAME}"
def SSH_USER = branchConfig.SSH_USER
def DOCKER_HOST = branchConfig.DOCKER_HOST
def DOCKER_REGISTRY = branchConfig.DOCKER_REGISTRY
def IMAGE_NAME = branchConfig.IMAGE_NAME
sshagent(credentials : ['master.pem']) {
withCredentials([usernamePassword(credentialsId: 'docker-registry-credentials', passwordVariable: 'DOCKER_REGISTRY_PASSWORD', usernameVariable: 'DOCKER_REGISTRY_USER')]) {
sh 'ssh -o StrictHostKeyChecking=no ' + branchConfig.SSH_USER + '@' + branchConfig.DOCKER_HOST + ' "docker login -u ' + DOCKER_REGISTRY_USER + ' -p ' + DOCKER_REGISTRY_PASSWORD + ' ' + branchConfig.DOCKER_REGISTRY + '"'
sh 'ssh -o StrictHostKeyChecking=no ' + branchConfig.SSH_USER + '@' + branchConfig.DOCKER_HOST + ' "docker pull ' + branchConfig.DOCKER_REGISTRY + '/' + IMAGE_NAME + ' && docker kill hello-world || true && docker rm hello-world || true && docker run -d --name hello-world -p80:80 ' + branchConfig.DOCKER_REGISTRY + '/' + branchConfig.IMAGE_NAME + '"'
}
}
}
else {
error("Build failed because failed to fetch settings for branch")
}
}
}
}
}
}
}
In your Jenkins Server, create a new multi-branch project for this codebase.
Branch Settings Config File
Create a config file in that project with the name: my-config-file.json
,
or use an alternative name, and update the Jenkinsfile in this codebase accordingly.
That config file should have the following contents (a block per environment branch).
{
"staging": {
"DOCKER_HOST": "my.staging-server.com",
"IMAGE_NAME": "my-docker-image",
"DOCKER_REGISTRY": "docker-registry.mydomain.com",
"SSH_USER": "programster"
},
"production": {
"DOCKER_HOST": "my.production-server.com",
"IMAGE_NAME": "my-docker-image",
"DOCKER_REGISTRY": "docker-registry.mydomain.com",
"SSH_USER": "programster"
}
}
Create Credentials
Create a credential of type usernamePassword
called "docker-registry-credentials" for which you provide the
username and password to your docker registry.
Create a credential of type file called master.pem
that contains the private SSH key that will allow logging into the
remote server (DOCKER_HOST
).
Configure Triggering From GitHub
Now we have a pipeline that will build and deploy our project, it would be ideal if this would get automatically triggered whenever a change was made. In order to do this, follow this post on how to Integrate Jenkins Multibranch Pipeline With Git / GitHub
First published: 29th June 2021