💾Thananjhayan
← Back to notes

Jenkins in Docker — Setup & Troubleshooting

December 14, 2025

Running Jenkins in a Docker container and building/pushing Docker images from a pipeline. These are the errors I hit, in order, and the fix for each — for both macOS (Docker Desktop) and Windows (Docker Desktop).

The core idea

The official jenkins/jenkins:lts image has no Docker CLI inside it. Mounting /var/run/docker.sock only gives access to the host's Docker daemon — you still need a docker binary inside the container to talk to it. So you must build your own Jenkins image with the Docker CLI baked in.

Step 1 — Build a Jenkins image with the Docker CLI

Dockerfile (same for Mac and Windows):

FROM jenkins/jenkins:lts

USER root

RUN apt-get update && apt-get install -y \
      ca-certificates curl gnupg lsb-release && \
    install -m 0755 -d /etc/apt/keyrings && \
    curl -fsSL https://download.docker.com/linux/debian/gpg \
      | gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
      https://download.docker.com/linux/debian $(lsb_release -cs) stable" \
      > /etc/apt/sources.list.d/docker.list && \
    apt-get update && apt-get install -y docker-ce-cli && \
    rm -rf /var/lib/apt/lists/*

USER jenkins

Build it:

docker build -t jenkins:1.0 .

Verify the CLI is actually in the image before running:

docker run --rm jenkins:1.0 which docker
# -> /usr/bin/docker

Step 2 — Run the Jenkins container

Run as root so the container can access the Docker socket. On Docker Desktop (both OSes) the socket is owned by root inside the VM, so -u root is the reliable fix — the Linux --group-add docker trick does not work here.

macOS (zsh / Terminal):

docker rm -f jenkins   # remove any old container with this name first

docker run -d --name jenkins -p 8080:8080 \
  -u root \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v jenkins_home:/var/jenkins_home \
  jenkins:1.0

Windows (PowerShell) — line continuation is a backtick ` (not \):

docker rm -f jenkins

docker run -d --name jenkins -p 8080:8080 `
  -u root `
  -v /var/run/docker.sock:/var/run/docker.sock `
  -v jenkins_home:/var/jenkins_home `
  jenkins:1.0

Windows (CMD) — line continuation is ^:

docker rm -f jenkins

docker run -d --name jenkins -p 8080:8080 ^
  -u root ^
  -v /var/run/docker.sock:/var/run/docker.sock ^
  -v jenkins_home:/var/jenkins_home ^
  jenkins:1.0

getent does not exist on Mac or Windows — that's a Linux-only command. Don't use --group-add $(getent group docker ...) on Desktop; use -u root.

Error map — symptom → cause → fix

1. docker: not found (exit 127)

  • Cause: Docker CLI not installed in the running container (or you're still running the old jenkins/jenkins:lts container, not your new jenkins:1.0).
  • Fix: Rebuild the image (Step 1), docker rm -f jenkins, re-run (Step 2). Confirm which image is live and that the CLI exists:
docker ps --filter name=jenkins --format '{{.Names}}  {{.Image}}'
docker exec jenkins which docker

2. permission denied ... unix:///var/run/docker.sock

  • Cause: The jenkins user can't read the Docker socket.
  • Fix: Recreate the container with -u root (Step 2).

3. localhost:8080 still shows Jenkins after stopping the container

  • Cause: Something else is holding port 8080 — another container, or a native Jenkins installed on the host.
  • Fix (find what owns the port):
    • Mac: lsof -i :8080 → if java, it's a Homebrew Jenkins → brew services stop jenkins-lts
    • Windows (PowerShell): netstat -ano | findstr :8080 → note the PID → tasklist /FI "PID eq <pid>" to identify it → stop the service/process
    • Also check Docker: docker ps --filter publish=8080
    • If nothing obvious, it's browser cache → hard refresh (Cmd/Ctrl+Shift+R) or open a private window.

4. fatal: not in a git directory when reading the Jenkinsfile

  • Cause: Jenkins "Lightweight checkout" failing.
  • Fix: Job → Configure → Pipeline → Definition: Pipeline script from SCMuncheck "Lightweight checkout" → Save → build.

5. fatal: not in a git directory on the pipeline's Checkout SCM stage

  • Cause: Stale/corrupt workspace left in the reused jenkins_home volume (ownership changed when switching to -u root).
  • Fix: Wipe the workspace so Jenkins re-clones fresh:
docker exec jenkins rm -rf /var/jenkins_home/workspace/nccV1

or in the UI: Job → Workspace → Wipe Out Current Workspace. If git 2.47 still complains about "dubious ownership" while running as root:

docker exec jenkins git config --global --add safe.directory '*'

6. invalid reference format on the image tag

  • Cause: Docker image names must be lowercase, no @, in the format namespace/repository:tag where namespace = your Docker Hub username. The tag was using an email + stray digits.
  • Fix: Build the tag from the Docker Hub username. If withCredentials binds DOCKERHUB_CREDS, then DOCKERHUB_CREDS_USR is the username:
sh "docker build -f backend2/Dockerfile -t ${DOCKERHUB_CREDS_USR}/backend:latest ./backend2"

Result: yourusername/backend:latest.

Quick reference

TaskmacOS / LinuxWindows PowerShell
Remove old containerdocker rm -f jenkinsdocker rm -f jenkins
Build imagedocker build -t jenkins:1.0 .docker build -t jenkins:1.0 .
Check CLI in containerdocker exec jenkins which dockerdocker exec jenkins which docker
See what's on port 8080lsof -i :8080netstat -ano | findstr :8080
Wipe workspacedocker exec jenkins rm -rf /var/jenkins_home/workspace/nccV1same
Get a shell in containerdocker exec -it jenkins bashdocker exec -it jenkins bash

Sane order to bring it up from scratch

  1. Write the Dockerfile (Step 1).
  2. docker build -t jenkins:1.0 .
  3. docker run --rm jenkins:1.0 which docker — confirm the CLI is present.
  4. docker rm -f jenkins (clear old container/name).
  5. Run with -u root + socket mount (Step 2).
  6. Make sure nothing else holds 8080 (error #3 checks).
  7. In the job: uncheck "Lightweight checkout".
  8. Fix the image tag in the Jenkinsfile to username/repo:latest.
  9. Build. Check the docker logout/login and push stage credentials.

Next: [[jenkins-docker-hub-credentials]], [[jenkins-pipeline-job]], and [[jenkins-jenkinsfile-explained]].

💬 Comments