What is a "Container" (vs a package)
  • 06 May 2021
  • 4 Minutes to read
  • Dark
  • PDF

What is a "Container" (vs a package)

  • Dark
  • PDF

Even for experienced developers, containers can be pretty difficult to understand. There's a lot to learn, but this article will help explain how containers work when compared to packages. You may also find the Docker terminology article helpful.

Package Files and Versions

Packages are generally simple: they are just a file that contains other files.

Everything you need to know about a package is contained within the package itself. Because the manifest file included in the package contains the package's name and version number, the filename of the package file doesn't really matter. While it should reflect the name and the version, it doesn't need to.

Package versioning is equally simple: packages are uniquely identified by a name and version, which allows for not only simple identification, but ordering and comparison to determine which is latest, which is newer, etc. Because version numbers are stored in the manifest file (i.e. within the package itself), the package's name and version are an integral part of the package, and are as immutable (unchanging) as its contents.

Container Image Basics

A container image is like a package file, in that it's made up of a other files.

But unlike packages, container images don't have a manifest file that contain a name and version. It's essentially a giant zip file that contains all the files an application needs to run, as well as the underlying operating system.

Unlike ordinary zip files, container images don't even have names. Instead, they are identified by a "cryptographic hash" (or digest) of their contents. This is a 64-character string that, to a human reader, may as well be a bunch of random numbers and letters. This basically means that a container image is essentially 40510175845988f13f6162ed8526f0b09f73384467fa855e1e79b44a56562a58.zip

To make container images useful to humans, those cryptographic hashes can be "tagged" with a name. It's similar how files on disk work, in that a file's name is not a part of the file itself. You can rename it, and the contents are the same. The same is true with container images; you can tag and re-tag them, and the contents will be the same.

Tags are like file names; you can rename files at any time, and the file name has no relation to the contents

Container Image Versioning

Just like a bunch of random files on disk, container images are unversioned. It's up the publisher to determine which container images have which tags, and when those tags change.

For example, some publishers may use [v6] to refer to the last version, whereas another may use [4.2-stable] to indicate a non-beta version of a container image. And then there's tags like [latest-2], [old-1], [new-test11-new-new], etc., which are exactly what one might expect when using the file system for versioning instead of packages.

Many publishers use a form of semantic versioning when tagging images (such as [4.3.0], [2.3.4-latest], etc., but mutable nature of tags means that a publisher can also change [hdards-3.2.4] (which appears to be a specific version) to point to any container image, at any time.

Because publishers can change their tags at any time, this leads to lots of confusion when containers versions change depending on the day you install them. Ultimately this leads to lots of lost productivity and even production failures in organizations when the wrong containers are tested and deployed.

Best Practices with Container Tags

With ProGet's Semantic Versioning for Containers, you don't have to worry about meaningless or changing tags. Once enabled, this feature will
help you manage your container images with the same rigor of your packages: tags may only be used for properly-formatted version numbers, and cannot be overwritten.

Private Registries & Container Naming

One of Docker design quirk is the peculiar relationship between a container's name (technically, the "repository name") and private container registries. Unless you specify the server's network address (IP or DNS name) when building, pulling, or pushing containers, Docker assumes that the image is hosted at hub.docker.org.

For example, proget.kramerica.local\registry-name\kramerica\my-app-name is the only way to reference a container image that's not hosted at hub.docker.org.

This is the only way to use Docker with a private registry. When you build, push, or pull an image, the Docker client will search for a . or a : in the first part of the repository name (i.e. before the first /). If neither of those characters exist, then, Docker will use hub.docker.com; otherwise, Docker pulls or pushes to the server address specified in that first part.

This behavior is important to note, because unlike package managers, there isn't an option when you build, pull, or push container images that instructs Docker to "use this private registry instead of the Docker hub".

Note: when creating your own container images, you must use the server address and registry name each and every time you reference the container image (which is always).

While it's unfortunate that you need to always specify the source, ProGet will help quite a bit by ignoring the first part of the repository name (i.e. the server address) and treating the second part as the registry (feed) name. This way, if you change ProGet's server address or rename your registry, your repositories will work the same.

Registry Mirroring

There is the ability to "mirror" hub.docker.org, but this feature was really only designed to enable Docker, Inc. to host public registries in sensitive regions like China (so you can mirror to registry.docker-cn.com instead).

Unfortunately, the Docker client will only use the configured "mirror" for building and pulling; images are always pushed to hub.docker.org.

Docker, Inc. does not seem to be interested in enabling this, and we aren't particularly keen on forking the Docker client to enable this. Thus, it seems there's no sense in ProGet supporting this anytime soon... but feel free to discuss this on the forums.