Outside GitHub Actions 29 , the GitHub Container Registry 29 accepts only a personal access token (classic) with write:packages. In Jenkins 8,793 it would be a Username with password credential, and the login would read (not run here: this book's account uses fine-grained tokens only):
echo "$CR_PAT" | docker login ghcr.io -u binarybehemoth --password-stdinBookNest's pipeline pushes instead to a self-hosted registry:3 container, l2-registry, published on localhost:32550 with htpasswd authentication (Securing a Registry). Its user and password are the Jenkins credential l2-registry, which the Docker 514 Pipeline plugin's withRegistry turns into a temporary login:
stage('Push') {
when { branch 'main' }
steps {
script {
docker.withRegistry("http://${env.REGISTRY}", 'l2-registry') {
def image = docker.image("${env.IMAGE}:${env.TAG}")
image.push()
image.push('main')
}
}$ docker login -u booknest -p ******** http://localhost:32550 WARNING! Using --password via the CLI is insecure. Use --password-stdin. ... Login Succeeded
The password is masked in the log and the login's config.json sits in the build's @tmp directory until the block ends, but -p puts it briefly on the agent's process list. Where that matters, use withCredentials([usernamePassword(...)]) and --password-stdin, as above. Plain http:// works only because Docker treats localhost as an insecure registry; other hosts need TLS.