Fixed Container Build Release file for http://deb.debian.org/debian-security/dists/bullseye-security/InRelease is expired

วันนี้มาจด Error ในการ Build Container Image สักหน่อย เพราะวันนี้อยู่ๆ ตัว Jenkins แล้ว Build Fail ขึ้นมาครับ โดยมี Key Error Message ตามนี้เลย

Release file for http://deb.debian.org/debian-security/dists/bullseye-security/InRelease is expired (invalid since 3d 11h 49min 21s). Updates for this repository will not be applied.

เจ้าที่มาเนี่ยมาจากที่ว่าตัว bullseye (End Of Life 20260931) นี่เองครับ เลยทำให้พวก Repo หลักต่างๆ ถูก Deprecate ไปแล้วพวก Security update ต่างๆ จะไม่ได้ด้วย ซึ่งทางแก้มี 2 ทาง

🔦 ทางแรก ยอมขยับไปให้ base image ที่สูงกว่า อาทิ เช่น bookworm (Debian 12 LTS) หรือ Trixie (Debian 13 Testing)
🔦 อีกทางถ้าลูกค้าไม่ยอม Update ต้องแก้ Repo List ใน Container ใช้ชี้ไปที่ Mirror อื่นๆ อย่างของตัว https://snapshot.debian.org/archive/debian หรือ https://mirror.kku.ac.th/debian/ เป็นต้น

สำหรับของผมต้องแก้ Repo List ใน Container

เคสของผมมีประเด็นลูกค้าไม่ยอมขยับ RedHat 8.2 ทำให้ Kernel มันเก่า และไม่สามารถไปใช้ Base Image ใหม่ได้ครับ ถ้าฝืนใช้จริงๆจะเจอ Error [DOTNET] Container cannot start on Podman 2.0.X, Failed to create CoreCLR, HRESULT: 0x80070008 (Blog Public MAR-23 ปกติผมเขียนดองไว้ น่าจะปี 2022 เลย)

ทางแก้เอา mcr.microsoft.com/dotnet/aspnet:6.0 มาทำเป็น base image ขึ้นใช้ใน nexus ใช้ไป อย่างน้อยมั่นใจว่ามี image พร้อมใช้งานหาก snapshot หรือ kku mirror ใช้ไม่ได้ครับ โดย Dockerfile ที่ปรับประมาณนี้ครับ

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS dotnet6-base

RUN set -eu; \
    . /etc/os-release; \
    set --; \
    if [ "${ID:-}" = "debian" ] && [ "${VERSION_CODENAME:-}" = "bullseye" ]; then \
        printf '%s\n' \
          'deb [check-valid-until=no] https://snapshot.debian.org/archive/debian/20260901T000000Z/ bullseye main' \
          'deb [check-valid-until=no] https://snapshot.debian.org/archive/debian/20260901T000000Z/ bullseye-updates main' \
          'deb [check-valid-until=no] https://snapshot.debian.org/archive/debian-security/20260901T000000Z/ bullseye-security main' \
          > /etc/apt/sources.list.d/bullseye-snapshot.list; \
        set -- \
          -o Dir::Etc::sourcelist=/etc/apt/sources.list.d/bullseye-snapshot.list \
          -o Dir::Etc::sourceparts=-; \
    fi; \
    if ! apt-get "$@" -o Acquire::Check-Valid-Until=false -o Acquire::Retries=3 -o Acquire::http::Timeout=15 -o Acquire::https::Timeout=15 update; then \
        echo "==> snapshot.debian.org update failed, falling back to mirror.kku.ac.th"; \
        printf '%s\n' \
          'deb [check-valid-until=no] http://mirror.kku.ac.th/debian bullseye main' \
          'deb [check-valid-until=no] http://mirror.kku.ac.th/debian bullseye-updates main' \
          'deb [check-valid-until=no] http://mirror.kku.ac.th/debian-security bullseye-security main' \
          'deb [check-valid-until=no] https://snapshot.debian.org/archive/debian-security/20260901T000000Z/ bullseye-security main' \
          > /etc/apt/sources.list.d/bullseye-snapshot.list; \
        apt-get "$@" -o Acquire::Check-Valid-Until=false -o Acquire::Retries=5 update; \
    fi; \
    apt-get "$@" -y install fontconfig curl wget libxml2-dev && \
    apt-get "$@" install -y libc6 -f -o APT::Immediate-Configure=0 && \
    apt-get "$@" install -y netcat-traditional && \
    apt-get "$@" install -y \
        libgdiplus \
        libicu-dev \
        libharfbuzz0b \
        libfontconfig1 \
        libfreetype6 \
        libpango-1.0-0 \
        libpangocairo-1.0 && \
    rm -rf /var/lib/apt/lists/*

📌 ส่วนแรก การจัดการ Repo List - ตรวจสอบก่อน ถ้าเป็น Debian(Bullseye) ลอง Override sources.list ไปที่ snapshot.debian.org อันนี้ดึงวันล่าสุดมา 20260901T000000Z นอกจากนี้มี Fallback ให้ไปดึงจาก mirror.kku.ac.th

📌ส่วนถัดมา อันนี้เป็นการลง Package ที่จำเป็นสำหรับ Image นั้นๆแล้ว

  • Base Tools / Network - พวก fontconfig, curl, wget, libxml2-dev และ netcat-traditional
  • .NET - libgdiplus (.NET System.Drawing บน Linux), ibicu-dev (จัดการข้อความและภาษาต่าง ๆ) และจัดการข้อความ Font เช่น libharfbuzz0b, libfontconfig1, libfreetype6, libpango-1.0-0 และ libpangocairo-1.0

สุดท้ายเป็นการ ใช้คำสั่ง rm -rf /var/lib/apt/lists/* ในตอนท้ายเพื่อลบ Cache ของ apt ให้ Container Image เล็กที่สุด ที่เหลือ Jenkinfile แล้ว เอาเป็นตัวอย่่างไปใช้ได้ตามนี้

pipeline {
    agent{
		label 'jenkins-worker'
	}
    parameters {
        string(name: 'IMAGEVERSION', defaultValue: '0.0.0', description: 'Image Version')
        gitParameter branchFilter: 'origin/(.*)', defaultValue: 'origin/main', name: 'BRANCH_ON_GIT', type: 'PT_BRANCH', description: 'Branch', quickFilterEnabled: true
        booleanParam(name: 'CLEAN_UP', defaultValue: true, description: 'Execute CLEAN_UP')     
    }
    environment {
        NEXUS_HOSTNAME = 'nexus.dsdev.local:5000'
        NEXUS_URL = 'https://nexus.dsdev.local:5000/'
        IMAGE_NAME = "bullseye_net6:$IMAGEVERSION"
    }
    stages {
         stage ('Lock Resource') {
            options{
                lock('jenkins-worker')
            }
            stages {
                stage('Build & Push'){
                    steps {
                        dir("net6_tsy") {
                            sh 'echo "PATH --------> " && pwd'
                            sh 'ls -al'
                            script {
                                withDockerRegistry(credentialsId: 'nexus3-jenkins', toolName: 'DOCKER', url: "${NEXUS_URL}") {
                                    sh "docker build -t ${NEXUS_HOSTNAME}/${IMAGE_NAME} -f Dockerfile.bullseye_net6 ."
                                }
                            }

                            script {
                                withDockerRegistry(credentialsId: 'nexus3-jenkins', toolName: 'DOCKER', url: "${NEXUS_URL}") {
                                    sh "docker push ${NEXUS_HOSTNAME}/${IMAGE_NAME}"
                                }
                            }
                        }
                    }
                }

            }
        }
    }
    post {
        always {
            script {
                if (params.CLEAN_UP) {
                    echo 'CLEAN_UP ...'
                    cleanWs();
                    sh "docker system prune -a -f"
                }
            }
        }
        failure {
            emailext body: "Build Fail, please help me ${env.BUILD_URL}", subject: "${env.JOB_NAME} - Build # ${env.BUILD_NUMBER} - ${env.BUILD_URL} - Fail", mimeType: 'text/html', to: "[email protected]"
        }
    }
}

Reference