Yesterday, my Jenkins pipeline could install dependencies and build the frontend.
But there was a missing piece: Docker. Without it, I couldn't package my applications into containers — the whole point of this challenge!
Today, I fixed that. I configured Jenkins to build Docker images for both my backend and frontend, turning my CI pipeline into a complete build system.
First: Why Docker in CI?
Before Docker in CI
The pipeline could:
- Pull code from GitHub
- Install dependencies
- Build the frontend
- Could NOT create Docker images
After Docker in CI
The pipeline can:
- Pull code from GitHub
- Install dependencies
- Build the frontend
- Create Docker images for backend AND frontend
Why this matters: Docker images are what actually get deployed to production. Without them, you can't run your app anywhere else.
Step 1: Giving Jenkins Docker Access
The Problem
Jenkins runs in a container. By default, containers can't access the host's Docker daemon.
+------------------+ +------------------+
| Jenkins | | Docker Daemon |
| Container | X | (on host) |
| "I need Docker" |---->| "Cannot reach" |
+------------------+ +------------------+
The Solution: Docker Socket Mounting
Mount the host's Docker socket into the Jenkins container:
# jenkins/docker-compose.yml
services:
jenkins:
user: root # Run as root for permissions
volumes:
- /var/run/docker.sock:/var/run/docker.sock # Mount Docker socket
environment:
- DOCKER_HOST=unix:///var/run/docker.sock # Tell Jenkins where Docker is
After Mounting
+------------------+ +------------------+
| Jenkins | | Docker Daemon |
| Container | ✓ | (on host) |
| "I need Docker" |---->| "Here you go!" |
+------------------+ +------------------+
Step 2: Installing Docker in Jenkins Container
Even with the socket mounted, Jenkins needs the Docker CLI tool.
# Enter Jenkins container
sudo docker exec -it jenkins bash
# Install Docker CLI
apt-get update
apt-get install -y docker.io
# Verify it works
docker --version
Expected output:
Docker version 26.1.5, build a72d7cd
Step 3: Adding Docker Build to Pipeline
The Docker Build Stage
stage('Docker Build') {
steps {
echo 'Building Docker images...'
sh 'docker build -t myapp-backend:latest ./backend'
sh 'docker build -t myapp-frontend:latest ./frontend'
}
}
What Each Command Does
| Command | What it does |
|---|---|
docker build |
Creates a Docker image from a Dockerfile |
-t myapp-backend:latest |
Tags the image with a name and version |
./backend |
Tells Docker where to find the Dockerfile |
The Complete Jenkinsfile (Docker Stage Added)
pipeline {
agent any
stages {
stage('Checkout') {
steps {
echo 'Cloning repository...'
checkout scm
}
}
stage('Backend Dependencies') {
steps {
dir('backend') {
sh 'npm install'
}
}
}
stage('Frontend Build') {
steps {
dir('frontend') {
sh 'npm install'
sh 'npm run build'
}
}
}
stage('Docker Build') {
steps {
echo 'Building Docker images...'
sh 'docker build -t myapp-backend:latest ./backend'
sh 'docker build -t myapp-frontend:latest ./frontend'
}
}
stage('Success') {
steps {
echo 'Pipeline completed successfully!'
}
}
}
}
Step 4: Understanding Docker Build in CI
What Happens During Docker Build
Stage: Docker Build
│
├── Backend Image
│ ├── FROM node:18-alpine
│ ├── WORKDIR /app
│ ├── COPY package*.json ./
│ ├── RUN npm install
│ ├── COPY . .
│ └── CMD ["npm", "start"]
│
└── Frontend Image
├── FROM nginx:alpine
├── COPY build /usr/share/nginx/html
└── EXPOSE 80
Image Sizes
| Image | Size | Why |
|---|---|---|
| myapp-backend:latest | ~135MB | Node.js + dependencies |
| myapp-frontend:latest | ~23MB | Just nginx + static files |
Step 5: Testing Docker Build Locally
Before trusting Jenkins, test manually:
# Build backend image
cd backend
docker build -t test-backend .
docker run -p 3001:5000 test-backend
curl http://localhost:3001/health
# Build frontend image
cd ../frontend
npm run build
docker build -t test-frontend .
docker run -p 8080:80 test-frontend
# Open browser to http://localhost:8080
Step 6: Running the Pipeline
Trigger the Build
- Go to Jenkins -> microservices-ci
- Click "Build Now"
- Watch the console output
Console Output
[Pipeline] stage
[Pipeline] { (Docker Build)
[Pipeline] echo
Building Docker images...
[Pipeline] sh
+ docker build -t myapp-backend:latest ./backend
#1 [internal] load build definition from dockerfile
#1 transferring dockerfile: 149B done
#1 DONE 0.2s
#2 [internal] load metadata for docker.io/library/node:18-alpine
#2 DONE 35.8s
#3 [1/5] FROM docker.io/library/node:18-alpine
#3 DONE 0.0s
...
Successfully built dd22467f3082
Successfully tagged myapp-backend:latest
[Pipeline] sh
+ docker build -t myapp-frontend:latest ./frontend
#1 [internal] load build definition from dockerfile
...
Successfully built 54515d7d59a9
Successfully tagged myapp-frontend:latest
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Success)
[Pipeline] echo
Pipeline completed successfully!
Finished: SUCCESS
Docker in CI: Before vs After
| Aspect | Before (Day 9) | After (Day 10) |
|---|---|---|
| Docker access | No | Yes |
| Backend image | Not built | Built automatically |
| Frontend image | Not built | Built automatically |
| Ready for deployment | No | Yes |
Troubleshooting
Issue 1: "docker: command not found"
Error:
+ docker build
docker: command not found
Fix: Install Docker CLI in Jenkins container:
sudo docker exec jenkins bash -c "apt-get update && apt-get install -y docker.io"
Issue 2: "Permission denied"
Error:
Got permission denied while trying to connect to the Docker daemon
Fix: Run Jenkins as root user in docker-compose.yml:
services:
jenkins:
user: root
Issue 3: Build context issues
Error:
COPY failed: file not found in build context
Fix: Check your Dockerfile paths. The build context is the directory you specify in docker build -t name ./path.
Key Takeaways
- Docker in CI = Deployable artifacts — Without Docker, you can't deploy
- Mount the Docker socket — Jenkins container needs access to host's Docker
-
Install Docker CLI — The container needs the
dockercommand -
Tag images meaningfully —
latestis fine, but version tags are better - Build once, deploy anywhere — CI builds images, they can run anywhere
Resources
Let's Connect!
Have you integrated Docker with Jenkins before? What challenges did you face with Docker in CI?
Drop a comment or connect on LinkedIn. Let's learn together!
Top comments (0)