Practical Guide: Installing Jenkins with Docker and Building Cross-Platform Images Using Buildx

jenkins docker installationdocker buildx cross-platformjenkins container setupdocker socket mountingmulti-arch image build
Published·Modified·

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.

77e8f49aac2f6bfd.png

Preparation

Directory Permissions

  1. The Jenkins container version runs as the jenkins user with a User ID (UID) of 1000, so the Jenkins data directory must also be set to UID 1000.
  2. You can use the command id 1000 to check the specific username. In my case, the username for UID 1000 is debian.
  3. You also need to add the debian user to the docker group 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_home directory 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 be 1000, otherwise permission issues will occur. 994 is 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.