If you’ve ever wanted to automate building, testing, and deploying your applications, this is your playground.
What is CI/CD?
- CI (Continuous Integration): Automatically integrates code changes into a shared repository and runs builds/tests to catch bugs early.
- CD (Continuous Delivery): Ensures code is always in a release-ready state with automated deployments to staging or production.
Together, CI/CD keeps development fast, reliable, and efficient.
What is a Build Job?
In Jenkins, a build job is a set of instructions to automate tasks — from compiling code, testing, and packaging, to deploying it anywhere.
What is a Freestyle Project?
A Freestyle Project in Jenkins is the most beginner-friendly way to:
- Build & test code
- Run Docker commands
- Deploy applications
- Chain together multiple automation steps
Today’s Challenge Tasks:
** Task 1**
- Create an agent for your Dockerized app.
- Make a new Freestyle Project in Jenkins.
- Add a build step to:
- Run
docker build
to create your image. - Run
docker run
to launch your container.
Task 2
- Create a Jenkins project to run:
-
docker-compose up -d
to start multiple containers (from your Day 19 project).- Add a cleanup step with:
docker-compose down
to stop and remove containers.
This is a hands-on step toward mastering CI/CD automation with Jenkins and Docker.
Prerequisite (do once)
- Confirm Jenkins is up
- Open:
http://<your-host>:8080
- Unlock with the password from:
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
- Create admin user → “Install suggested plugins”
- Give Jenkins access to Docker
# On the machine where Jenkins runs
sudo usermod -aG docker jenkins
sudo systemctl restart jenkins
# Verify the jenkins user can talk to Docker
sudo -u jenkins -H sh -c 'docker version && docker ps'
- Install Git & Compose on the agent/host
sudo apt-get update
sudo apt-get install -y git
docker-compose version || sudo apt-get install -y docker-compose-plugin
Create/prepare an Agent (Node)
You can use the Built-in Node if Jenkins and Docker are on the same machine:
- Jenkins → Manage Jenkins → Nodes → Built-in Node → Configure
- Add a Label (e.g.,
docker
) - Set # of executors (start with 1) → Save
(If you have a separate Docker host, add it as an SSH agent with label docker
and ensure Docker is installed there.)
Task 1: Freestyle job to build and run your container
A. Prepare your repository
Your app repo should have a Dockerfile
at the root. Example:
my-app/
├─ Dockerfile
├─ src/...
└─ ...
B. Create the job
- Jenkins → New Item → Freestyle project → name it
app-build-run
→ OK -
General: Check Restrict where this project can be run → Label:
docker
- Source Code Management → Git → Repo URL (add credentials if private)
-
Build Triggers → Build periodically → Schedule:
H * * * *
(once every hour, nicely scattered) - Build → Add build step → Execute shell Paste:
set -e
APP_NAME="myapp"
IMAGE="${APP_NAME}:${BUILD_NUMBER}"
PORT=8080 # change if your app uses a different port
echo "[INFO] Building image ${IMAGE}"
docker build -t "${IMAGE}" .
echo "[INFO] Stopping previous container (if any)"
docker rm -f "${APP_NAME}" 2>/dev/null || true
echo "[INFO] Running new container"
docker run -d --name "${APP_NAME}" -p ${PORT}:${PORT} "${IMAGE}"
echo "[INFO] Container status:"
docker ps --filter "name=${APP_NAME}"
- Save → Build Now
- Test the app at
http://<host>:8080
(or your mapped port).
Tip: If your app listens on a different internal port, map accordingly (e.g.,
-p 8000:8000
).
Task 2: Freestyle job to run docker compose up -d and clean up
A. Repo structure
Your repo should contain a docker-compose.yml
. Example minimal:
services:
web:
build: .
ports:
- "8080:8080"
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: example
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
B. Create the job
- Jenkins → New Item → Freestyle project → name it
compose-up
→ OK -
Restrict where this project can be run → Label:
docker
- Source Code Management → Git → Your repo URL
-
Build Triggers (optional) → Build periodically (e.g.,
H/30 * * * *
to run every ~30 mins) -
Build → Add build step → Execute shell
If you have
docker compose
:
set -e
FILE="docker-compose.yml"
echo "[INFO] Pull/build & start in detached mode"
docker compose -f "${FILE}" up -d --build
echo "[INFO] Current stack:"
docker compose -f "${FILE}" ps
If your system only has the old binary:
docker-compose -f docker-compose.yml up -d --build
docker-compose -f docker-compose.yml ps
Cleanup: docker compose down
Trap cleanup in the same step (runs even if the build fails)**
set -e
FILE="docker-compose.yml"
cleanup() {
echo "[CLEANUP] Bringing stack down"
docker compose -f "${FILE}" down --volumes --remove-orphans
}
trap cleanup EXIT
docker compose -f "${FILE}" up -d --build
docker compose -f "${FILE}" ps
# Put your tests here if any; cleanup will still run on EXIT
If you want the stack to stay up for manual testing and only clean in dedicated jobs, skip
down
here and add a separate Freestyle job calledcompose-down
with:
docker compose -f docker-compose.yml down --volumes --remove-orphans
If your repo is private
- Jenkins → Manage Jenkins → Credentials → System → Global → Add Credentials
- Choose Username with password or SSH Username with private key
- Reference it in the job’s Git settings.
Add another Execute shell step at the end:
bash
echo "[VERIFY] Hitting health endpoint"
curl -fsS http://localhost:8080/ || (echo "App not responding" && exit 1)
That’s it! Run both jobs, check the Console Output to confirm each stage, and you’re done.
Top comments (0)