
Cloud-native application bundles for easy container deployment
Packages in the Cloud
In 2018, Docker and Microsoft noticed the lack of a generic package standard for containers and set out to address the problem. The result was cloud-native application bundles (CNABs), which "… facilitate the bundling, installing, and managing of container-native apps and their coupled services" [1] (Figure 1). The "approved deliverable" version 1.0 was made publicly available under the terms of the Open Web Foundation 1.0 license in September 2019. I take a close look at the CNAB standard to see what it does and does not define and how administrators and developers can benefit.

A New Ecosystem
In the typical manner for new technology, a standard toolset can take a while to crystallize. Even containers are not immune to this effect. In the initial phase, Docker was the undisputed king of the hill, single-handedly guiding containers out of the shadows and making them presentable. (See the "Container Advantages" box.)
However, it soon became clear that anyone that uses Docker as a foundation for applications needs logic to manage the various containers of an application centrally. In the age of the cloud, a suitable framework must also let admins operate Docker containers as entire fleets of physical or virtual systems because it is the only way to ensure scalability.
Solutions such as Kubernetes quickly appeared on the scene, while the actual container formats tended to take a back seat. Kubernetes, for example, can now be operated just as well with CRI-O as with the Docker format for container images. From the outside, you hardly notice any difference (e.g., as with OpenShift, shown in Figure 2).

The question then is how a format can be defined that is as generic as possible, yet sufficiently effective for distributing containers. Anyone familiar with the Linux world knows that RPM and DEB have been closely defined standards for decades. If you build a DEB package for a program and stick to the rules, you can rely on having a good package. Containers have been different thus far, until Docker and Microsoft teamed up to create CNABs.
What Is Needed
To understand the idea behind CNABs, it helps to visualize the container developer's working day. In an application that comprises many small components, the developer also has to deal with many small containers. A CNAB does not give any instructions on how to develop these containers, which is very much in the tradition of the classic package manager.
For DEB, it doesn't matter how the package is created. What is important is its compatibility with the version of the DEB standard that the package developer specifies in the metadata. Just as certain toolchains have emerged in RPM and DEB that are mainly used today for building packages, containers have followed the same course.
Comprehensive integration with a continuous integration and continuous deployment (CI/CD) tool is an essential part of a valid container success story. If the developer takes the trouble to set it up at the very beginning of this work, it pays dividends time and time again. The commands required to build an image can reside in a Docker file in a Git directory, for example. If a detail changes in this Docker file or anywhere else in the repository, the Git environment itself triggers the image rebuild with a hook application. As an example, GitLab comes with its own Docker registry, to which it uploads new images on demand.
However, one swallow does not a summer make, and an image doesn't make an application rolled out in a microservices architecture – for many reasons. For one, admins do not just need to deal with one container, but with several, and they typically have to be rolled out in a certain way.
As for normal packages, containers often have dependencies. Sometimes the complexity of containers is even far greater than that of package systems, because certain containers not only have to run in parallel, their configuration also has to be coordinated. If you roll out containers in the context of a fleet orchestrator such as Kubernetes, you also have to be familiar with the various parameters that need to be taken into account during the rollout.
CNABs Supply the Metadata
Metadata, and a tool that interprets and implements it, acts as the glue that holds together various active Docker images and their configurations and is where a CNAB comes into play: The term is (and is certainly confusing for many users) both the name of the defined standard and the umbrella term for the tools associated with it. Nevertheless, it does make sense to consider the standard format and tools separately.
The two initiators of CNAB, Microsoft and Docker, see it primarily as a package standard that defines the formats and metadata for distributing applications in containers. A CNAB is aimed at all administrators who have worried about getting lost in the tangle of different services and APIs in their container environments in recent years.
As an admin, you have to deal with a number of APIs and tools: Docker at the command line and Kubernetes with what feels like hundreds of tools and utilities (partly upstream, partly not). Various additional services like Terraform and CloudFormation enjoy the users' favor, as well, and they all come with their own metadata formats that you have to learn if you want to use them to roll out applications. In the simplest form, an application is rolled out by packing it into a large Docker container and distributing it over Docker Hub, although this is not a very flexible solution.
The CNAB standard sets out to bring order to the combination of available tools and standards by wrapping itself around them like a vise. A CNAB describes a metadata format that abstracts the minutiae of many different run-time environments (including Terraform, CloudFormation, Kubernetes, and Docker Compose) and makes them usable under a common domain-specific language (DSL). Although Kubernetes is undoubtedly the container tool of the hour, a CNAB is not aimed only at Kubernetes fans (probably because of the involvement of Docker, who offers a Kubernetes competitor in the form of Docker Swarm).
Environments and Structure
With CNABs, abstraction goes so far as to make it possible to roll out different services of an application on different platforms. Although some components then run in Kubernetes, others opt for a BOSH (bidirectional streams over synchronous HTTP) or Rancher deployment. In practice, you might not encounter such deployment scenarios very often, but the fact that they are possible shows how flexibly the CNAB standard is designed.
The basic structure of the CNAB format will not surprise most admins. Basically, you are dealing with two files: A YAML file, which contains the bundle definition with all the relevant metadata, and an invocation image, which is used to install the containers. The invocation image is therefore a kind of meta service, whose only task is to roll out the containers according to the information in the bundle definition.
Microsoft, Docker, and companies like HashiCorp have also added a built-in quality check to the new format. It distinguishes between "well formed" and "complete." A CNAB application is considered well formed if both the bundle definition and the required images follow the CNAB standard. It can call itself complete if it either integrates all required components into the package (thick bundle) or if the bundle definition lists all external dependencies correctly and they can be resolved (thin bundle). The thin bundle approach obviously saves disk space and makes rolling out CNABs dependent on external factors (e.g., a working Internet connection).
If you have ever built packages in RPM or DEB format, you know an armada of tools exist that, among other things, take care of writing the metadata file for the respective package. Most Debian packages, for example, rely on the debhelper suite to perform tasks automatically, such as creating the metadata description. Not surprisingly, Microsoft, Docker, and others have released several tools along with the CNAB standard to make it easier to use.
Three of these tools play an important role: Duffle is a reference implementation of a tool that can build packages in line with the CNAB definition. It is joined by Porter, which wraps itself around Duffle and creates installer packages on demand that then use the CNAB format in the background. Finally, Docker App builds reusable images on the basis of Docker Compose and the CNAB standard that can even be distributed from Docker Hub.
Duffle
Duffle (Figure 3) unabashedly refers to itself as the reference implementation of the CNAB format and provides a variety of functions for building CNAB packages. Duffle is easy to learn; you can create an initial usable app in package form without problems. After installing Duffle, duffle init
drags the local development environment for Duffle into the light of day.

As the next step, you create a folder for your application that contains two files and one folder. In bundle.json
, enter the metadata that a CNAB cannot automatically guess, such as the name of the CNAB's maintainers. You need to add similar information to the duffle.json
file, which is only used for Duffle and will not be included in the CNAB later on. The cnab/
folder contains all the files necessary for creating the image. In the case of the trivial Hello World Duffle example [2], this folder contains the Docker file that turns a generic container into a Hello World container. The app/
folder also contains files that need to be copied to the container in the Dockerfile – Duffle only searches for them there.
Once you have created the configuration files for the container, the following steps are trivial:
-
duffle build
creates the CNAB for the Hello World package, which is then found in the host's Docker registry. -
duffle install
then rolls out the application as a CNAB.
In the end, you have a ready-to-run container based on Docker. You guessed it: Duffle currently only works with Docker and requires Docker as its command-line interface.
Porter
The second reference implementation for CNABs, Porter [3], does not come from Docker but from Microsoft, who has invested resources in the past years to get Docker running on Windows – with some success. However, for understandable reasons, Microsoft primarily wants to attract customers to its own cloud. What could be more obvious than building a tool that offers developers and administrators the possibility of building CNABs directly for Azure? Porter precisely hits this target (Figure 4).

For Porter, you again write a file containing the metadata for the CNAB, but this file is not the bundle.json
file used by Duffle. Porter uses the metadata file to generate a future bundle.json
. By the way, if you don't like JSON, Porter will be happy to provide YAML, to avoid all those parentheses.
Developers store all the required details in the YAML file. For example, you would specify not only the name and version of the CNAB, but also which invocation image is to be used. Mixins are a kind of module that can be used to integrate support for container environments. They exist for (surprise!) Azure, as well as AWS or completely different environments like Terraform.
Unlike Duffle, Porter knows how to handle the various as-a-services of the clouds it supports. For example, if you need MySQL in a CNAB, you can integrate the MySQL resources from Azure or AWS with the database-as-a-service (DBaaS) functionality there. If you later install the CNAB in an environment with Porter, it automatically starts the necessary database.
Moreover, Porter works with Kubernetes, because one of the supported mixins is the Kubernetes package manager Helm. If you want to roll out WordPress to a Kubernetes cluster in Azure that also talks directly to a MySQL database in Azure, you can enter all these details directly in a Porter metadata file.
Creating Bundles with Porter
Once you have built the porter.yaml
for your project, the rest of the work is very simple. Use porter build
to create the bundle, which can then be loaded into an open containers initiative (OCI)-compatible container registry such as Docker Hub or a local instance of Quay. From there, you can easily roll out the bundle again locally with porter install
.
Working with the porter
command is quite similar to using the docker
command, but unlike Docker, Porter gives you the complete bundle, which can roll out resources in many different cloud environments at the same time. This clearly shows how practical CNAB is as a format.
Docker App
The third reference for CNABs, which once again comes from Docker, is also worth a mention. In contrast to Duffle, which looks to build local bundles, Docker App [4] is intended to be the Docker counterpart to Porter, but with a far smaller feature set (Figure 5).

The basic principle of Docker App is similar to that of Porter: You use a metadata file to describe the CNAB, which can comprise various Docker images and their respective configurations. Running docker app
then creates a bundle for this app that meets the CNAB specification.
Practically speaking, docker app
actively ensures that the resulting bundle complies with the CNAB standard; the container registries that comply with the OCI standard (e.g., Docker Hub) can already handle CNABs. From an admin point of view, this setup is very practical because the CNABs created in this way can be distributed without problem.
Unlike Porter, Docker App is oriented exclusively toward Docker Swarm or, locally, to Docker itself. A Kubernetes connection also exists with the Helm package manager, which allows applications built in Docker App to be deployed directly in Swarm or in a Kubernetes environment. What is missing, however, is the versatility of integration with various Kubernetes variants or the services offered by public cloud providers.
If you want to use Kubernetes for a WordPress installation, for example, you need the MySQL database. Although this can also be operated in Kubernetes as part of an application with its own container, you can weigh yourself down with an additional full application in this way. The advantage of the cloud providers' as-a-service offers is that you have no need to worry about certain basics of these applications – such as replication, backups, data integrity, or maintenance of the underlying operating system. However, Docker App does not support the integration of such services and therefore falls a little short of the mark.
Also unclear at the time of this writing was whether Docker App would have a real future. After all of Docker's commercial business was transferred to Mirantis, the new owner immediately set about cleaning up. Only a few hours after the announcement of the takeover, several news items popped up on Twitter announcing that former Docker developers were now looking for new employment opportunities.
Meanwhile, prophets of doom hint that what is now left of Docker could make a great match for Microsoft, which, however, would probably not be a good thing for the future of Docker App, because Microsoft already has the far more extensive Porter. If you're currently getting started with CNABs, you are well advised to take a closer look at Porter and wait and see how Docker App develops.
CNABs and Kubernetes?
It makes sense to take another look at the relationship between CNABs and Kubernetes. As mentioned at the beginning, Kubernetes is currently without doubt the only real shooting star in the container universe. Docker felt this painfully in November: Rumors that the company was on the verge of bankruptcy persisted for weeks. The speculation only came to an end when Mirantis took over the business from Docker Enterprises. However, Mirantis is taking a rigorous pro-Kubernetes course, which raises the question of whether Docker is planning to quit using CNABs and to what extent the use of CNAB packages in the CNAB context makes sense at all. After all, Kubernetes also has its own package manager, Helm, which is similar to a CNAB in many ways.
Whether and to what extent CNABs and Kubernetes can complement each other meaningfully all depends on the question of how homogeneously admins and developers design their container experience. Those who run Kubernetes on bare metal or in a cloud do not have a central problem that CNABs address. Normally, they will not need to deal constantly with different toolchains and different targets for the deployment of their containers. Instead, in such a use case, Kubernetes APIs are available to handle all the tasks at hand, including installing packages with Helm.
CNABs, on the other hand, have a reason to exist if you do not want to deploy exclusively to a local Kubernetes instance via the native Kubernetes APIs. Anyone using Terraform or wanting to use the Kubernetes services of AWS, Azure, or Google in their respective clouds is already confronted with several tools. In this scenario, CNABs help, because they abstract and resolve this complexity. The admin uses the same bundles for all target platforms and enjoys a uniform interface.
Conclusions
In and of itself, the CNAB standard is a good idea. Although a package manager in the form of Helm already exists for containers, it is Kubernetes-specific and cannot be used outside the container orchestrator. If CNABs were designed to work better with Kubernetes and Helm out of the box, so that Helm could build and use CNAB-compatible bundles, it would be a really practical toolchain. Instead, the two standards tend to exist in parallel.
Porter offers a good example of DIY Kubernetes integration with CNABs, but that's not the ultimate solution. Moreover, the future of CNABs is at stake, as one of the two main protagonists – Docker – ran out of commercial steam. Microsoft and Docker are no longer the only companies driving the standard, but it remains to be seen whether the loss of Docker can be compensated for that easily.