The promise of Docker is that it simplifies application deployment, allows greater application density on hosts, and features a portable format that offers unparalleled flexibility over standard packaging. But one thing Docker doesn’t get you is the simplicity of `yum install foo` to install an application. Nor can Docker define or process a directed graph of container orchestration dependencies. We aim to change that.
The Air Gap between Docker and Delivery
Many enterprise developers and ISVs have begun exploring containers as an application delivery system. This is pretty good if you can put one application on a single container, but very few have gone beyond the simple one container per app model.
Google released Kubernetes as a way to add orchestration to those applications that stretch across multiple containers. This at least gives developers a way forward to defining multi-container applications. However, the effort required to piece together orchestration via Kubernetes for an application is still mostly piecemeal with no standardized methodology for delivering an application.
In fact, going beyond the typical basic use case of deploying applications on containers requires much DIY and highly customized processes that are difficult to repeat for different types of applications. There remains a gap in the application delivery via containers model in the form of standardized packaging and deployment tools that are portable, container format agnostic, host platform agnostic, and orchestration engine agnostic. Putting together all three would make the devops model attainable for the rest of us and greatly improve the lives of enterprise IT and developers.
First, let’s look at packaging. How can we package an application for deployment in a container or pods of containers? How do you distribute this package? And how do you run it? In much the same way as yum and RPM combine to form the application management tooling for Red Hat Enterprise Linux, Nulecule is the basis for container-based application packaging. After thinking about this problem, the container tools team at Red Hat decided that we needed a packaging format that met these criteria:
- Support any Linux container format and runtime
- We don’t want to lock in users to a particular format.
- Support any host platform (as long as it can run Linux containers)
- We don’t want to lock in users to a particular Linux platform.
- Support any orchestration provider
- See above (except for orchestration).
- Build on existing, available container images
- It’s important that developers be able to construct composite applications using off-the-shelf “parts” - in this case, other containers. Think of it as application development via Lego construction.
To do this, we needed an easy way to define the parameters of an application. After looking at the OASIS Topology and Orchestration Specification for Cloud Applications (TOSCA) and some other application definition efforts, we decided to create a specification tailored specifically for containers. Thus, Nulecule (...it’s a Simpsons reference: “It all starts when a nulecule leaves the nest…”). The idea is that you should be able to define an application in terms of container images published to a registry, configuration parameters, and orchestration providers.
In the Nulecule file, you define which container layers are needed, the orchestration targets, and the dependencies of each. For example, to use an existing wordpress image, you’ll need another container that supplies a database, such as MariaDB. Or to use OpenShift as an orchestration provider, you may need to inherit some parameters from Kubernetes. The end result is an application definition that, when combined with a root container and a runtime, should be self-contained.
Now that we have a specification, what then? The next step was to create the tools one could use for deployment. It’s important to note that Nulecule is a specification that can be used by myriad tools. We are creating a reference implementation in the form of Atomic App, but the idea is for Nulecule to be used by anyone looking to solve the problem of packaging container-based applications.
Having said that, we’ve put together our implementation, called Atomic App, that utilizes Docker, Kubernetes, and sometimes OpenShift. Even then, when desired, various pieces can be switched out. Using Atomic App with Rkt, for example, should be feasible. Or, if you don’t want Kubernetes or OpenShift, you can use Just Plain Docker (JPD) as the deployment target - assuming, of course, that you don’t need multiple hosts for your container pods.
The Nulecule getting started guide walks you through creating an Atomic App. Using the Atomic App container as your starting point, you define your application graph in Nulecule and then launch the application from inside Atomic App. Note: to use Kubernetes, OpenShift, or any other deployment provider, including Docker, you will minimally need their respective client tools installed on your root container.
After creating your Nulecule file, you simply build a container image from the Atomic App base image:
docker build -t IMAGE [TAG]
This packages the application metadata with the Atomic App deployment tool.
We’ve built up quite a number of example applications that you can find on the Nulecule specification repository. All of the Atomic App containers you see in that repo have been added to DockerHub for ease of use. You can find most of them under the Project Atomic image repository on DockerHub, including the Atomic App base image.
So pull one down, tailor it for your use, and then happy hacking! You’ll find that by using Atomic App, you’ll significantly reduce the time to delivery for an enterprise application in production. Instead of the 5-page readme generally required for these types of applications, you can significantly reduce the learning curve to run, not to mention the virtual trees you’ll save with your simpler deployment instructions.
In addition to trying out Atomic App, we’d like to implement more deployment targets, including Ansible, Puppet, Chef, et al. There is currently a plugin in development to support Nulecule applications from the Cockpit dashboard, and we would love to see support for Atomic App in ManageIQ and other management frameworks. If you’re interested in working on client development tools, management integration, or deployment targets, we’d love to talk to you.