Debian Docker – apt Update Different Behavior in Dockerfile and Prompt

aptdebiandocker

I'm trying to install an apt source on the Microsoft azure function docker, here is my Dockerfile

FROM mcr.microsoft.com/azure-functions/python:3.0-python3.9

RUN echo 'deb [trusted=yes] http://deb.debian.org/debian testing main' > /etc/apt/sources.list.d/testing.list
RUN apt update -y

This fails in the apt update -y step with the following error

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Get:1 http://deb.debian.org/debian buster InRelease [122 kB]
Get:2 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB]
Hit:3 http://security.debian.org/debian-security jessie/updates InRelease
Get:4 http://deb.debian.org/debian buster-updates InRelease [51.9 kB]
Get:5 https://packages.microsoft.com/debian/9/prod stretch InRelease [4009 B]
Get:6 http://deb.debian.org/debian testing InRelease [112 kB]
Get:7 https://packages.microsoft.com/debian/9/prod stretch/main amd64 Packages [161 kB]
Get:8 http://deb.debian.org/debian testing/main amd64 Packages [8248 kB]
Reading package lists...
E: Repository 'http://security.debian.org/debian-security buster/updates InRelease' changed its 'Suite' value from 'stable' to 'oldstable'
E: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Suite' value from 'stable' to 'oldstable'
E: Repository 'http://deb.debian.org/debian buster-updates InRelease' changed its 'Suite' value from 'stable-updates' to 'oldstable-updates'
The command '/bin/sh -c apt update -y' returned a non-zero code: 100

But:

  • if I run the exact same two commands after launching docker run --rm -it --entrypoint bash mcr.microsoft.com/azure-functions/python:3.0-python3.9, apt update -y works fine,
  • if I change the base image to debian:buster-slim on which the image is based, the docker build works fine,
  • even if the command fails, I can install package from testing, e.g., apt update -y || apt install g++ will install g++-10 instead of the default g++-8 on Buster.

Any idea why the command fails? And how I can fix it?


Edit: Adding --allow-releaseinfo-change to apt update -y in the dockerfile fixed the issue, but I'd still like to know why it failed without?


Note: Question moved from SO since it's apparently off-topic there… Let me know if it's also off-topic here.

Best Answer

TL;DR

The root issue is a bug in the base image you're using. The permanent fix is to clear out /var/lib/apt/lists in the base image Dockerfile, but it can be temporarily worked around by rebuilding the base image or using the --allow-releaseinfo-change option.

The reason why this behavior differs between docker build and docker run -it is the use of the -t flag to allocate a tty. This changes the behavior of apt -y (APT::Get::Assume-Yes).

Full explanation

Repository ... changed its 'Suite' value

This error occurs when:

  1. APT has a cached version of the Release file -- This is the bug. Docker base images should generally clean this cache.
  2. The remote repo has a newer version
  3. Certain fields don't match between the two versions

In a non-docker environment, this check is intended to protect the user from suddenly and unexpectedly installing packages from a different Debian release.

In this case, the base image mcr.microsoft.com/azure-functions/python:3.0-python3.9 contains contained cached versions of the Debian buster Release files (condition #1) with Suite: stable, because that was current at the time it was built.

However, the master copy in the Debian archive is newer (condition #2), and now has Suite: oldstable (condition #3), because Debian 10 buster has been superseded by Debian 11 bullseye.

So when you try to run apt update on this base image, it fails because of the mismatch between the old cached version and the current version.

I tried your Dockerfile just now (2021-09-03), and it worked OK for me. This is probably because it's been rebuilt since you posted this question. This would have caused it to cache the new Release files from the Debian archive, correcting the mismatch (#2/#3 above are no longer true).

However, you can verify that the bug is still there:

$ docker run --rm -it --entrypoint bash mcr.microsoft.com/azure-functions/python:3.0-python3.9               
root@722ec78233b4:/# grep Suite /var/lib/apt/lists/*Release
/var/lib/apt/lists/deb.debian.org_debian_dists_buster-updates_InRelease:Suite: oldstable-updates
/var/lib/apt/lists/deb.debian.org_debian_dists_buster_InRelease:Suite: oldstable
/var/lib/apt/lists/packages.microsoft.com_debian_9_prod_dists_stretch_InRelease:Suite: stretch
/var/lib/apt/lists/security.debian.org_debian-security_dists_buster_updates_InRelease:Suite: oldstable
/var/lib/apt/lists/security.debian.org_debian-security_dists_jessie_updates_InRelease:Suite: oldoldstable

And the same error will recur after the next Debian release, when buster becomes oldoldstable and bullseye becomes oldstable.

I saw a similar issue with an unrelated docker base image recently, and I think this bug is fairly widespread.

Behavior of -y option

When you run apt with a tty as stdin, -y will override this check and allow the update command to succeed. However, if there is no tty (non-interactive session), the -y option will not override this check. I confirmed this using an older version of the buggy image:

# aborts    
docker run --rm mcr.microsoft.com/azure-functions/python:3.0.15066-python3.9-slim apt update -y

# succeeds
docker run -t --rm mcr.microsoft.com/azure-functions/python:3.0.15066-python3.9-slim apt update -y

# prompts for y/N to continue
docker run -it --rm mcr.microsoft.com/azure-functions/python:3.0.15066-python3.9-slim apt update

# aborts
docker run --rm mcr.microsoft.com/azure-functions/python:3.0.15066-python3.9-slim apt update