Practical Guide: Installing Jenkins with Docker and Building Cross-Platform Images Using Buildx
Recently, I attempted to upgrade Jenkins, but it failed to start after the update. After troubleshooting, I discovered the cause was an outdated JDK version: the old version used JDK 8, while the new version requires JDK 17. To avoid the hassle of upgrading JDK, I decided to migrate it to a containerized version, which permanently solved the environment dependency issues.

Preparation
Directory Permissions
- The Jenkins container version runs as the
jenkinsuser with a User ID (UID) of1000, so the Jenkins data directory must also be set to UID1000. - You can use the command
id 1000to check the specific username. In my case, the username for UID 1000 isdebian. - You also need to add the
debianuser to thedockergroup to ensure execution permissions for the Docker client.
The complete commands are:
# Check the user corresponding to id 1000
id 1000
# Add the debian user to the docker group
usermod -aG docker debian
# Immediately refresh user group permissions
newgrp docker
# Set permissions for the jenkins_home directory
chown -R debian:docker ./jenkins_home
Installing Jenkins with Docker
For easier maintenance, I chose to install Jenkins using Docker Compose. The content of docker-compose.yaml is as follows:
version: '3.8'
services:
jenkins:
container_name: jenkins
image: jenkins/jenkins:lts-jdk17
ports:
- "8080:8080"
- "50000:50000"
volumes:
- ./jenkins_home:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock # Mount Docker Socket
- /usr/bin/docker:/usr/bin/docker
- /usr/libexec/docker/cli-plugins:/usr/libexec/docker/cli-plugins
restart: unless-stopped
user: "1000:994"
Parameter meanings:
./jenkins_home:/var/jenkins_home: Mounts the host's./jenkins_homedirectory inside the container for persistent data storage. Modify this path according to your actual situation./var/run/docker.sock:/var/run/docker.sock: Mounts the Docker daemon socket into the Jenkins container, enabling automation tools within Jenkins to use Docker./usr/bin/docker:/usr/bin/docker: Mounts the Docker client binary into the Jenkins container (since the Jenkins container does not have the Docker client installed by default)./usr/libexec/docker/cli-plugins:/usr/libexec/docker/cli-plugins: Maps Docker plugins into the container; otherwise, Buildx cannot be used later.user: "1000:994": Corresponds to the User ID and Group ID. The first User ID must be1000, otherwise permission issues will occur.994is the Group ID corresponding to the Docker group.
Then, run the command docker-compose up -d to start the container. If everything goes smoothly, you can access Jenkins at http://IP:8080.
Using Buildx
Docker Buildx is an extended tool that enhances Docker's build capabilities, supporting multi-platform builds (such as ARM, x86, etc.), parallel builds, and advanced cache management, helping users create and manage container images more efficiently. If you do not need to build cross-platform images, you can skip using Buildx for now!
First, execute the following commands on the host:
# Check buildx version
docker buildx version
# Create a new Buildx builder instance
docker buildx create --name multiarch --driver docker-container --bootstrap
# Switch to the specified Buildx builder instance
docker buildx use multiarch
# Display detailed information about the Buildx builder
docker buildx inspect --bootstrap
After execution, run the same commands inside the container:
docker exec -it jenkins /bin/bash
# Check buildx version
docker buildx version
# Create a new Buildx builder instance
docker buildx create --name multiarch --driver docker-container --bootstrap
# Switch to the specified Buildx builder instance
docker buildx use multiarch
# Display detailed information about the Buildx builder
docker buildx inspect --bootstrap
Now you can use Buildx to build cross-platform images, for example:
docker buildx build --platform linux/amd64,linux/arm64 -t ${IMAGE_NAME}:${VERSION} . --push
Pushing Docker Images
The Docker configuration file locations differ between the host and the Jenkins container. Even if you have logged in to Docker on the host, you must log in again inside the Jenkins container.
Execute the following inside the Jenkins container:
# Login to Docker
docker login
After logging in, the data is persisted to jenkins_home, so this operation only needs to be performed once; subsequent times are not required.
Conclusion
Containerized installation of Jenkins faces more challenges compared to direct installation on the host, especially when using Docker Buildx to build cross-platform images. Although the Jenkins official recommendation is to use the DIND (Docker-in-Docker) mode to connect to Docker, in practice, I found that Buildx has many issues in DIND mode. To simplify the process, I ultimately chose to run via the sock mode. While this may reduce security slightly, the specific solution should be evaluated based on business requirements.