When initially installing a package, phased update percentage is not considered at all. It's only used when considering package upgrades.
As a result, opting out of phased updates can create a situation where a package from the updates repository is installed during the container build in an earlier phase, but a later installation may try to install dependencies in sibling packages which are not available at the required version due to being behind the phased update percentage wall.
This is intended to be an alternative to #708
As of the time these tests were performed, the following was the entry for dovecot-core in the contents of the jammy-updates repository for amd64. I picked dovecot-core because it was the first result for a phased update and doesn't have too many dependencies.
FROM ubuntu:jammy as always
RUN echo 'apt::get::always-include-phased-updates "true";' > /etc/apt/apt.conf.d/90-phased-updates
RUN apt update
RUN apt install -y dovecot-core
CMD apt list --installed | grep dovecot-core
FROM ubuntu:jammy as never
RUN echo 'apt::get::never-include-phased-updates "true";' > /etc/apt/apt.conf.d/90-phased-updates
RUN apt update
RUN apt install -y dovecot-core
CMD apt list --installed | grep dovecot-core
In both cases, the output from docker run ... is the same
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
dovecot-core/jammy-updates,now 1:2.3.16+dfsg1-3ubuntu2.2 amd64 [installed]
So empirically, the phased update configuration has no bearing on what is considered an installation candidate for an initial install. This seems overall problematic but maybe we're doing something very unusual here.
If we simulate our scenario by forcing the install of the base version of the package, we get the following pair of image builds:
FROM ubuntu:jammy as always
RUN echo 'apt::get::always-include-phased-updates "true";' > /etc/apt/apt.conf.d/90-phased-updates
RUN apt update
RUN apt install -y dovecot-core=1:2.3.16+dfsg1-3ubuntu2.1
CMD apt list --installed | grep dovecot-core
FROM ubuntu:jammy as never
RUN echo 'apt::get::never-include-phased-updates "true";' > /etc/apt/apt.conf.d/90-phased-updates
RUN apt update
RUN apt install -y dovecot-core=1:2.3.16+dfsg1-3ubuntu2.1
CMD apt list --installed | grep dovecot-core
Again in both cases, the output is, perhaps surprisingly, the same:
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
dovecot-core/jammy-security,now 1:2.3.16+dfsg1-3ubuntu2.1 amd64 [installed,upgradable to: 1:2.3.16+dfsg1-3ubuntu2.2]
Even where phased updates are opted-out, the package is listed as upgradeable.
When running apt upgrade we see an actual difference.
Always:
# apt upgrade
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Calculating upgrade... Done
The following packages will be upgraded:
dovecot-core libncurses6 libncursesw6 libssl3 libtinfo6 ncurses-base ncurses-bin
7 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 5788 kB of archives.
After this operation, 4096 B disk space will be freed.
Do you want to continue? [Y/n]
Never:
# apt upgrade
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Calculating upgrade... Done
The following packages have been kept back:
dovecot-core
The following packages will be upgraded:
libncurses6 libncursesw6 libssl3 libtinfo6 ncurses-base ncurses-bin
6 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
Need to get 2469 kB of archives.
After this operation, 4096 B disk space will be freed.
Do you want to continue? [Y/n]
One odd thing, I couldn't reproduce the behavior where an installation of a new package would fail when a set of dependencies conflicted.
I tried installing dovecot-imapd, which had a dependency on dovecot-core (= 1:2.3.16+dfsg1-3ubuntu2.2) and in both scenarios this resulted in the version of dovecot-core getting installed.
So I'm starting to suspect that this is an issue with recovering from a phased update being completely removed (as it seems the mesa update has been, as of now) and that nothing we do in this configuration will actually make one jot of difference in that scenario since it does not seem that anything would allow us to recover short of completely busting the docker image cache.
So this PR does not seem likely to resolve this class of error in the future.
I debated just closing it, but on balance I think that switching to opt-in for phased updates will make the image more consistent with what will actually get put on it during the build phase, and if in the future apt changes to respecting this value during initial package installation it will make it will ensure continuity of behavior.
Other controls, such as forcing a full --no-cache build once in a while or catching apt issues in a post-build heuristic and retriggering after a cache purge would be potential ways to address this core problem.
When initially installing a package, phased update percentage is not considered at all. It's only used when considering package upgrades.
As a result, opting out of phased updates can create a situation where a package from the updates repository is installed during the container build in an earlier phase, but a later installation may try to install dependencies in sibling packages which are not available at the required version due to being behind the phased update percentage wall.
This is intended to be an alternative to #708
As of the time these tests were performed, the following was the entry for
dovecot-core
in the contents of the jammy-updates repository for amd64. I picked dovecot-core because it was the first result for a phased update and doesn't have too many dependencies.Two initial base images always, and never.
In both cases, the output from
docker run ...
is the sameSo empirically, the phased update configuration has no bearing on what is considered an installation candidate for an initial install. This seems overall problematic but maybe we're doing something very unusual here.
If we simulate our scenario by forcing the install of the base version of the package, we get the following pair of image builds:
Again in both cases, the output is, perhaps surprisingly, the same:
Even where phased updates are opted-out, the package is listed as upgradeable. When running
apt upgrade
we see an actual difference.Always:
Never:
One odd thing, I couldn't reproduce the behavior where an installation of a new package would fail when a set of dependencies conflicted.
I tried installing
dovecot-imapd
, which had a dependency ondovecot-core (= 1:2.3.16+dfsg1-3ubuntu2.2)
and in both scenarios this resulted in the version of dovecot-core getting installed.So I'm starting to suspect that this is an issue with recovering from a phased update being completely removed (as it seems the
mesa
update has been, as of now) and that nothing we do in this configuration will actually make one jot of difference in that scenario since it does not seem that anything would allow us to recover short of completely busting the docker image cache.So this PR does not seem likely to resolve this class of error in the future. I debated just closing it, but on balance I think that switching to opt-in for phased updates will make the image more consistent with what will actually get put on it during the build phase, and if in the future apt changes to respecting this value during initial package installation it will make it will ensure continuity of behavior.
Other controls, such as forcing a full
--no-cache
build once in a while or catching apt issues in a post-build heuristic and retriggering after a cache purge would be potential ways to address this core problem.