Why shared libraries?
When many Jenkinsfiles copy the same “npm ci → test → docker build” block, extract it into a shared library.
Typical Git repo layout:
vars/
buildNodeApp.groovy # becomes step buildNodeApp()
src/
org/mycompany/... # Groovy classes
resources/
... # templates / non-Groovy files
vars/buildNodeApp.groovy
def call(Map config = [:]) {
sh 'npm ci'
sh 'npm test'
sh 'npm run build'
}Jenkinsfile
@Library('my-shared-library@main') _
pipeline {
agent { docker { image 'node:20-alpine' } }
stages {
stage('Build') {
steps {
buildNodeApp()
}
}
}
}Configure the library under Manage Jenkins → System → Global Pipeline Libraries.
Production best practices
| Practice | Why |
|---|---|
| Jenkinsfile in Git | Reviewable, reproducible |
| Credentials store | No secrets in SCM |
| Agents for heavy work | Protect the controller |
Timeouts on input | Free executors |
| Notifications on failure | Fast feedback |
| Pin image tags | Reproducible agents |
Backup JENKINS_HOME | Disaster recovery |
What you built across 4 days
Day 1 CI/CD + install + first job
Day 2 Freestyle + Git + triggers
Day 3 Declarative Jenkinsfile
Day 4 Docker agents + deploy + libraries
Next steps: Multibranch Pipelines, RBAC folders, and DevSecOps scans (SonarQube, Trivy) on the image you already push.