As a step of a Dockerfile I need to install the build-essential package (if not available) and run make. To keep the footprint of the container nice and small; I would also like to remove build-essential and all resulting dependencies when done.
Simply removing it with apt-get remove followed by autoremove does not work; most packages installed (100mb or so) are left behind, probably as they are listed as recommended or suggested packages by others. Also; this approach may risk removing build-essential from a base image that did already contain it (and still should), unless checking for that case explicitly.
Another approach is to check the list of install packages and revert to that state after the make. My almost working solution is a script containing:
dpkg --get-selections > /before
apt-get -y install build-essential
make -C <path to Makefile>
dpkg --clear-selections
dpkg --set-selections < /before
apt-get -y dselect-upgrade
This successfully restores package state and removes whatever packages were installed, while keeping any existing stuff in place. Great. However; existing packages on the system with pending updates are also updated -- which I would very much like to avoid at this stage as this adds unnecessary weight to this specific docker layer.
The following packages will be upgraded:
apt apt-utils base-files coreutils cpio dpkg gcc-4.9-base ifupdown
initscripts isc-dhcp-client isc-dhcp-common libapt-inst1.5 libapt-pkg4.12
libc-bin libdrm2 libffi6 libgcc1 libgcrypt11 libgnutls-openssl27 libgnutls26
libpng12-0 libssl1.0.0 libudev1 login multiarch-support ntpdate passwd
sysv-rc sysvinit-utils udev
30 upgraded, 0 newly installed, 38 to remove and 0 not upgraded.
Need to get 11.3 MB of archives.
...
The question is; how can I restore the package state (read: remove all new packages installed by build-essential) without causing any packages to be updated?
Managed to solve it myself:
dpkg --get-selections > /before
apt-get -y install build-essential
make -C <path to Makefile>
dpkg --clear-selections
cat /before | sed 's/install/hold/' | dpkg --set-selections
apt-get -y dselect-upgrade
dpkg --set-selections < /before
The key difference is to set all packages not to be removed to to 'hold' (and then restore it to be polite to future upgrades).