BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage Articles Using Docker Application Packages to Deliver Apps across Teams

Using Docker Application Packages to Deliver Apps across Teams

Bookmarks

Key Takeaways

  • Currently there is no single solution for defining and packaging multi-service, multi-format distributed applications that run on any host.
  • Cloud-Native Application Bundle (CNAB) is an open source, cloud-agnostic specification for packaging and running distributed applications. 
  • The CNAB package format is made up of a bundle definition file (bundle.json) to define the app, and an invocation image to install the app. 
  • The latest release of Docker App implements the current CNAB spec. By implementing the CNAB spec, Docker App can be used to both build CNAB bundles for Compose and also install, upgrade and uninstall any other CNAB bundle.

Cloud native applications typically use different technologies, each with their own packaging formats. For example, If you’re working on Microsoft Azure then it would be ARM templates, or if its Kubernetes, then its Helm charts, or if it’s on AWS then it would be CloudFormation and so on.

Distributed applications usually comprise executable units and supporting API-based services. Executable units could span across environments like IaaS (like OpenStack or Azure), container orchestrators (like Kubernetes or Nomad), container runtimes (like local Docker or ACI), cloud platform services (like object storage or Database as a Service) and Functions-as-a-Service (FaaS), as well as higher-level PaaS services. Along with these components, many managed cloud services (e.g. load balancers, routers to databases) are provisioned and interconnected via REST APIs.

In the industry, currently there is no single solution for defining and packaging multi-service, multi-format distributed applications.

In this article, we will look at how the CNAB packaging format provides application providers and developers with a way of installing a multi-component application into a distributed computing environment, supporting all of the above types and makes it easy to deliver apps across teams, organizations and marketplaces.

Introducing Cloud Native Application Bundle (CNAB)

CNAB is an open source, cloud-agnostic specification for packaging and running distributed applications. Created by Microsoft, Docker, HashiCorp, Bitnami, Pivotal, and many others. It unifies the management of multi-service, distributed applications across different toolchains into a single all-in-one packaging format.

Simplifies complex deployments. With CNAB, you can package multi-service, multi-format distributed applications. So deployments can be done with ease & simplified.
Open Source, Cloud Agnostic CNAB bundles can have varied infrastructure components or services that you need. CNABs is the right choice for your multi-cloud strategy.
Shareable Apps  Enables Developers/Application Providers to share/deliver apps across teams, organizations and marketplaces.

Key benefits of CNAB

According to the CNAB Spec, CNAB packaging format brings in:

  1. Support for packages targeted to different runtimes and architectures.
  2. Internally uses containers for encapsulating installation logic so its independent of underlying cloud environment it runs in.
  3. Comprises of a bundle definition file (bundle.json) to define the app, and an invocation image to install the app. The invocation image's job is to install required components into the host environment.
  4. CNAB bundle definition is a single file that contains the following information:
    • Information about the bundle, like name, bundle version, description, and keywords
    • Information about the invocation image (the installer program)
    • List of executable images that this bundle will install
    • List of credential paths or environment variables that this bundle requires to execute
  5. CNAB invocation image contains a standardized file system layout where metadata and installation data is stored.
    • File system hierarchy as specified in the spec
    • Main entry point (run tool) - Executable responsible for translating action requests (ex. Install / update etc.,) to a sequence of tasks
    • Runtime metadata (For example - Helm charts, Terraform templates, etc)
    • Files for constructing the images (For Example - Dockerfile)

Container applications built on Docker compose are not easy to share and to manage across different teams and between different environments.

To overcome this, the latest release of Docker App implements the current CNAB spec. By implementing the CNAB spec, Docker App can be used to both build CNAB bundles for Compose and also install, upgrade and uninstall any other CNAB bundle. The same CNAB bundle can then be used with any other CNAB compatible client too.

In the next section, let’s look at steps on how to convert existing Docker compose application to new Docker Application Package.

Install Docker App

There are two ways in which you can install Docker App, either as standalone or as CLI plugin. Pre-built static binaries are available on GitHub releases for Windows, Linux and macOS. Here I’m going to use the Linux version and install Docker app as standalone utility.


Image – Docker App Installation

Image – Docker App Installation Success

In the below example, we are going to check how to convert an existing Compose app into a Docker App project.

Create New Helloworld Docker App

Once we have got the Docker App set up, use an existing Docker compose file (below) which launches an HTTP echo server that prints the specified text when hit on the configured port.

version: '3.2'
services:
  hello:
    image: hashicorp/http-echo
    command: ["-text", "hello world"]
    ports:
      - 5678:5678


Image – Hello World Docker compose File

Run the docker-app init command from the folder where compose file is located to create a new Application Package:

docker app init --single-file hello

 
Image – Hello World Docker App Created

If you check the Docker Application Package hello.dockerapp, it will contain three YAML documents:

  • First section contains metadata such as name, version, description and maintainers.
  • Second section describes the application; this is essentially your Compose file.
  • Third section would have parameters for your application

If you prefer having the three core documents in separate YAML files, omit the --single-file option to the docker app init command. This will create a new directory instead of a single file.

 
Image – Docker Application Package File

Edit Metadata

Let’s modify the Compose file section in helloworld.dockerapp, by introducing variables $text and $port.

version: '3.2'
services:
  hello:
    image: hashicorp/http-echo
    command: ["-text", "${text}"]
    ports:
      - ${port}:5678


Image – Modified Docker Application Package File

Inspect Docker App

Before launching the modified Docker Application Package, let’s do inspect and check if everything looks good.


Image – Inspect Docker App

Docker App also provides a validate command to check syntax and other aspects of the configuration. We are going to skip and render the app.

Render Docker App

The render command will display the compose file with the default values.

 
Image – Render Docker App

The next step is to deploy the Docker App project. Here we have 2 options, either we can launch it as Native Docker app application or as Compose app application.

We are going to use Compose app option and then push the application to the DockerHub registry.

Launch Docker App

Image – Launch Docker App

Image – Output of Docker App

Launch Docker App with different configuration

Although Docker Compose configuration has default ports and text values, we can set the values at runtime and deploy them.

Lets try different configuration with different values for port and text.

Image – Launch Docker App with different configuration

 
Image – Output of Docker App

You can also check the status of the app with the docker app status <app-name> command.

Share Docker App on DockerHub

With new Docker application packaged, the compose configuration with default values can be pushed to DockerHub and be shared across developers/teams.

Image – Share Docker App on DockerHub

Install as Docker Native App

Applications can also be installed by running docker app deploy or can use the rendered version and run docker stack deploy render/docker-compose.yml or docker-compose –f up.

Image – Install Docker App

Upgrade Docker App

Once your Application Packages are in DockerHub or any registry, you can use commands like install, upgrade, uninstall, etc.,

Image – Upgrade Docker App

Uninstall Docker App

Image – Uninstall Docker App

In the next section, we will take another example that has a Angular, SpringBoot and PostgreSQL stack and create Docker Application Package out of it.

Create Docker App for Angular, SpringBoot and PostgreSQL application

Below is the compose file for the Angular, SpringBoot and PostgreSQL application that we are going to use.

version: '3'
services:
   ui:
    build:
      context: .
      dockerfile: UIDockerfile
    ports:
      - '4200:4200'
    networks:
      - samplenet
    links:
      - 'api:api'
  api:
   build:
     context: .
     dockerfile: AppDockerfile
   ports:
     - '8080:8080'
   depends_on:
    - db
   networks:
    - samplenet
   links:
    - 'db:db'
  db:
   build:
    context: .
    dockerfile: DBDockerfile
  volumes:
   - 'postgresdb:/var/lib/postgresql/data'
  environment:
   POSTGRES_USER: postgres
   POSTGRES_PASSWORD: postgres
   POSTGRES_DB: testdb
  ports:
   - '5432:5432'
  healthcheck:
   test:
     - CMD-SHELL
     - 'pg_isready -U postgres'
   interval: 10s
   timeout: 5s
   retries: 5
  networks:
   - samplenet
networks:
samplenet: null
volumes:
postgresdb: {}

The above compose file defines four services:

  • ui : Is for Angular application runs on port 4200.
  • api : Is for Spring boot application runs on port 8080.
  • db : Is for postgresdb application runs on port 5432.
  • All the above services uses samplenet network and
  • Persistent volume postgresdb definition is for db service
  • Added healthcheck section for db service to keep tab on the health of the database
  • depends_on denotes the service dependencies. When you start the services, compose would start the dependent services as well.

Run docker-app init command from the folder where the compose file is located to create a new Application Package:


Image – Create new Application Package

Image - Generated Application Package

Let’s do inspect and check if everything is proper

Image – Inspect Application Package

Use the render option to start the application using Docker Compose up command

Image – Render Application Package

Once you push it to DockerHub, you can share it with team and they would be able do all tasks like install, upgrade and uninstall tasks etc.,

Image – Push Application Package to DockerHub

Applications can then be installed by running docker app deploy or can use the rendered version and run docker stack deploy render/docker-compose.yml or docker-compose –f up.

Image – Install Application Package

Conclusion

Compose files are not easy to share between environments or across teams, so Docker Application Packages solves these problems and make Compose Application reusable across multiple environments (Development/QA/Staging/Production). Docker App is currently in experimental mode and it must not be used in production environments.

References

  1. Cloud Native Application Bundle (CNAB) specification
  2. CNAB Example bundles
  3. Docker App Github

About the Author

Karthikeyan Shanmugam (Karthik) is an experienced Solutions Architect professional with about 18+ years of experience in design & development of enterprise applications across Banking, Financial Services, Healthcare and Aviation domains. Currently engaged in Technical consulting & providing solutions in the Application Transformation space.
 

Rate this Article

Adoption
Style

BT