A Jenkins pipeline is a set of automated steps defined in a Jenkinsfile
(usually as part of the code repository, a.k.a. as Code) that tells Jenkins what to do in each step of your CI/CD pipeline.
The Jenkinsfile
, written in Groovy, has a specific syntax and structure, and it is executed within the Jenkins server.
The pipeline typically consists of multiple stages, each of which performs a specific steps, such as building the code as a Docker image, running tests, or deploying the software to Kubernetes cluster.
- In your repository, in branch
main
, create abuild.Jenkinsfile
in the root directory as the following template:
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'echo building...'
}
}
}
}
- Commit and push your changes.
- From the main Jenkins dashboard page, choose New Item.
- Enter
Yolo5Build
as the project name, and choose Pipeline. - Check GitHub project and enter the URL of your GitHub repo.
- Under Build Triggers check GitHub hook trigger for GITScm polling.
- Under Pipeline choose Pipeline script from SCM.
- Choose Git as your SCM, and enter the repo URL.
- If you don't have yet credentials to GitHub, choose Add and create Jenkins credentials.
- Kind must be Username and password
- Choose informative Username (as github or something similar)
- The Password should be a GitHub Personal Access Token with the following scope:
Click here to create a token with this scope.
repo,read:user,user:email,write:repo_hook
- Enter
github
as the credentials ID. - Click Add.
- Under Branches to build enter
main
as we want this pipeline to be triggered upon changes in branch main. - Under Script Path write the path to your
build.Jenkinsfile
defining this pipeline. - Save the pipeline.
- Test the integration by add a
sh
step to thebuild.Jenkinsfile
, commit & push and see the triggered job.
The Build stage specifies how should the code be built before it's ready to be deployed. In our case, we want to build a Docker image.
Let's implement the Build stage in your Jenkinsfile, will build the "Yolo5" app.
- The complete source code can be found under
projects/app_development_I/yolo5
. If you haven't done it before your docker project, copy the app files into your project Git repo. - If you don't have yet, create a private registry in ECR for the app.
- In the registry page, use the View push commands to implement a build step in your
build.Jenkinsfile
. The step may be seen like:
stage('Build Yolo5 app') {
steps {
sh '''
aws ecr get-login-pass..... | docker login --username AWS ....
docker build ...
docker tag ...
docker push ...
'''
}
}
You can use the timestamp, or the BUILD_NUMBER
or BUILD_TAG
environment variables to tag your Docker images, but don't tag the images as latest
.
- Give your EC2 instance an appropriate role to push an image to ECR.
- Use the
environment
directive to store global variable (as AWS region and ECR registry URL) and make your pipeline a bit more elegant.
We would like to trigger a Deployment pipeline after every successful running of the Build pipeline (Yolo5Build
).
- In the app repo, create another
Jenkinsfile
calleddeploy.Jenkinsfile
. In this pipeline we will define the deployment steps for the Yolo5 app:
pipeline {
agent any
stages {
stage('Deploy') {
steps {
sh '# kubectl apply -f ....'
}
}
}
}
- Create another Jenkins Pipeline named
Yolo5Deploy
, fill it similarly to the Build pipeline, but don't trigger this pipeline as a result of a GitHub hook event (why?).
We now want that every successful Build pipeline running will automatically trigger the Deploy pipeline. We can achieve this using the following two steps:
- Use the Pipeline: Build step that triggers the Deploy pipeline:
stage('Trigger Deploy') {
steps {
build job: '<deploy-job-name>', wait: false, parameters: [
string(name: 'YOLO5_IMAGE_URL', value: "<full-url-to-docker-image>")
]
}
}
Where:
<deploy-job-name>
is the name of your Deploy pipeline (should beYolo5Deploy
).<full-url-to-docker-image>
is a full URL to your built Docker image. You can use env vars like:value: "${IMAGE_NAME}:${IMAGE_TAG}"
or something similar.
- In the
deploy.Jenkinsfile
define a string parameter that will be passed to this pipeline from the Build pipeline:
pipeline {
agent ..
# add the below line in the same level an `agent` and `stages`:
parameters { string(name: 'YOLO5_IMAGE_URL', defaultValue: '', description: '') }
stages ...
}
As for now, we build the Docker images in the system of the Jenkins server itself, which is a very bad idea (why?).
Use the post
directive and the docker image prune
command to cleanup the built Docker images from the disk.
The Snyk Container command line interface helps you to find and fix Docker image vulnerabilities.
You must first to Sign up for Snyk account. Make sure you've installed Snyk on your Jenkins server.
- Get you API token from your Account Settings page.
- Once you've set a
SNYK_TOKEN
environment variable with the API token as a value, you can easily scan docker images for vulnerabilities:
export SNYK_TOKEN=mytoken
# will scan ubuntu docker image from DockerHub
snyk container test ubuntu
# will alarm for `high` issue and above
snyk container test ubuntu --severity-threshold=high
# will scan a local image my-image:latest. The --file=Dockerfile can add more context to the security scanning.
snyk container test my-image:latest --file=Dockerfile
- Create a Secret text Jenkins credentials containing the API token.
- Implement Docker image scanning in your pipelines (where?). Use the
withCredentials
step, read your Snyk API secret asSNYK_TOKEN
env var, and perform the security testing using simplesh
step andsynk
cli.
Sometimes, Snyk alerts you to a vulnerability that has no update or Snyk patch available, or that you do not believe to be currently exploitable in your application.
You can ignore a specific vulnerability in a project using the snyk ignore
command:
snyk ignore --id=<ISSUE_ID>
Bonus: use Snyk Jenkins plugin or use the Jenkins HTML publisher plugin together with snyk-to-html project to generate a UI friendly Snyk reports in your pipeline page.
Review some additional pipeline features, as part of the options
directive. Add the options{}
clause with the relevant features for the Build and Deploy pipelines.