avatarStefan Schindler

Summary

The author discusses the challenge of package version pinning in Docker images using Alpine Linux due to the distribution's policy of not retaining old package versions, which can lead to inconsistencies in image builds.

Abstract

The author, a proponent of Alpine Linux for its minimal and small Docker images, encounters an issue with package version pinning when attempting to build images for an older project. Alpine's package manager, apk, fails because the specific version of a package required by the project is no longer available in the repository, as Alpine Linux does not keep old packages. This problem undermines the principle of reproducibility in Docker builds, which is crucial both at runtime and during image construction. While Alpine supports repository and package pinning, the lack of old package versions forces users to rely on repository pinning, which may lead to unexpected package versions when rebuilding images. The author contrasts this with package managers like PyPI and npm, which maintain all package versions, allowing for reliable version pinning. Despite the inconvenience, the author remains committed to using Alpine Linux in Docker but advises caution with package versions and suggests implementing unit tests for better coverage.

Opinions

  • The author is a strong advocate for Alpine Linux due to its suitability for minimal Docker images.
  • Reproducibility is highlighted as a key benefit and expectation of Docker, which is compromised by Alpine's handling of package versions.
  • The author is critical of Alpine Linux's decision not to retain old package versions, as it leads to potential build inconsistencies.
  • There is a preference expressed for the approach taken by PyPI and npm, which maintain all package versions, thus supporting reliable version pinning.
  • The author recommends that users pay close attention to package versions and implement unit tests when using Alpine Linux in Docker to mitigate potential issues.

The problem with Docker and Alpine’s package pinning

Being a huge fan of Alpine Linux, I’m using it in a lot of my built Docker images. The resulting images are very small and minimal, so ideal for containerized environments.

Recently I wanted to build Docker images for a dated project. But Alpine’s package manager apk failed, and the reason surprised me.

What’s one of the biggest benefits of Docker? Clearly reproducibility: It doesn’t matter where you run your images, or when you run them: The result will always be the same.

Reproducibility isn’t only important at runtime, though. It’s also very important when building the images: Again, no matter where or when you build them: Same result!

Version pinning

For achieving consistent builds, the dependencies you rely on must be pinned down to a specific version. You can’t just go install nodejs, you have to be very specific, like install [email protected].

Why is that? If you don’t pin down version numbers, your images are dependent on the point of time when they are built. When package maintainers decide to release a new version, it will be automatically installed as soon as you rebuild your image the next time.

Alpine Linux and version pinning

Alpine Linux does support two ways of pinning down packages: Repository and package pinning.

Alpine Linux itself carries a version number (current version as of writing is 3.7). Every Alpine Linux version has its own package repository (the thing where the package archives are stored).

With repository pinning, you can actually pin down the packages to the latest available package version of the selected Alpine Linux version. For example, in Alpine 3.5, the package Node.js might be 2.0, and in Alpine 3.4 it’s 1.9. By pinning down the repository to Alpine 3.4, you will alwaysget Node.js 1.9, because Alpine 3.4 is an old version and not updated anymore.

With package pinning, you can pin down the packages to their respective versions. It lets you specify what version of a package you want, like Node.js in version 1.2.3. This sounds perfect!

Alpine doesn’t keep old packages

Unfortunately Alpine Linux does not keep old packages. When I tried building the dated project, I got this response from apk:

ERROR: unsatisfiable constraints:
  postgresql-dev-10.3-r0:
    breaks: world[postgresql-dev=10.2-r0]

The postgresql-dev version I used to use (10.2-r0) isn’t available anymore. Instead 10.3-r0 has been released, and the old package has been dropped from the repository.

This is a huge problem, as it forces you to avoid pinning down package versions and resort to repository pinning.

However, when rebuilding your images, the packages might be installed in versions you didn’t expect. And that can be a real problem, depending on what changed in the respective packages when they were updated.

PyPI, npm, …?

I’d like to have it similar to PyPI and npm: No version is dropped, so version pinning works perfectly fine, no matter when you build or use your stuff.

Alpine is a great distribution, especially for Docker. Of course I will continue using it, but you better pay a good amount of attention to package versions in the future and install unit tests to get you covered!

Liked this article? Feel free to clap your hands! ;-) Also check out my other stories and my website as well. Have a nice day!

Docker
Alpine
Linux
DevOps
Recommended from ReadMedium