Migrating Jenkins DinD to Podman: Setting Up a Custom Podman Builder
Introduction
If you're running Jenkins agents as Kubernetes pods with JNLP and Docker-in-Docker (DinD) as containers, you may be considering a migration to Podman as your container engine. This transition helps improve security, eliminates the need for privileged containers, and ensures better compliance with modern containerization best practices.
In this guide, we'll walk through how to set up a custom Podman builder and connect it with a JNLP agent in a Jenkins pod environment using the Podman Builder project.Steps to Set Up a Custom Podman Builder in Jenkins
Build a Custom Podman Image
you can create a custom image using the Podman Builder project and push to any registries
This entrypoint.sh configures Podman to listen on a TCP socket , sets up storage options
#!/bin/sh
set -eu
# Set container runtime to use Podman
export CONTAINER_RUNTIME=podman
# Create or update registries.conf file with the mirror URLs
cat <<EOF > /etc/containers/registries.conf
[registries.search]
registries = ['docker.io', 'quay.io']
[registries.insecure]
registries = []
[registries.block]
registries = []
[registries.forward]
registries = []
EOF
cat <<EOF > /etc/containers/containers.conf
[socket]
listen = "tcp://0.0.0.0:2375"
[containers]
netns="host"
EOF
cat <<EOF > /etc/containers/storage.conf
[storage]
# Default Storage Driver, Must be set for proper operation.
driver = "overlay"
# Runtime directory for temporary container storage.
runroot = "/run/containers/storage"
# Root directory where all container storage data resides.
graphroot = "/build/containers/storage"
[storage.options]
# List of additional image stores.
additionalimagestores = []
# Pull options for images (must be on a single line).
pull_options = { enable_partial_images = "false", use_hard_links = "false", ostree_repos = "" }
[storage.options.overlay]
# Mount options for overlay storage.
mountopt = "nodev"
[storage.options.thinpool]
# Storage options for thinpool.
# 'basesize' defines the default size for new container storage.
basesize = "50G"
EOF
# Start Podman service in the background
podman system service --time=0 tcp://localhost:2375 &
# Keep the container running
tail -f /dev/null
Replace DinD with a Podman Container
Once the podman image is ready, We need to replace the dind
container with a podman
container inside the Jenkins agent pod.
Modify your Jenkins agent pod YAML definition:
apiVersion: v1
kind: Pod
spec:
containers:
image: podman:latest
imagePullPolicy: Always
name: dind
resources: {}
securityContext:
privileged: true
procMount: Default
tty: true
workingDir: /home/build
- env:
- name: DOCKER_HOST
value: tcp://localhost:2375
- name: HOME
value: /home/build
image: jenkins-jnlp-worker
imagePullPolicy: Always
name: jnlp
resources:
limits:
cpu: "25"
memory: 64G
requests:
cpu: "17500m"
memory: 45G
securityContext:
privileged: false
procMount: Default
tty: true
workingDir: /home/build
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: <add_your_secret>
nodeSelector:
beta.kubernetes.io/arch: amd64
buildtype: default
priority: 0
restartPolicy: Never
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
Conclusion
Migrating from DinD to Podman enhances security, simplifies container management, and aligns with modern container best practices. By following this approach and leveraging the Podman Builder project, you can seamlessly integrate Podman into your Jenkins agent pod setup while maintaining a robust CI/CD pipeline.
Happy containerizing with Podman! ๐