Customizing Appsody stacks: An introduction

Appsody is an open source project that simplifies your cloud-native application development. Appsody’s primary component is a stack which builds a pre-configured Docker image that is ready for you to deploy in a cloud environment. These Docker images can include any amount of customized content and allow stack builders to decide which parts are fixed (stack image) and which parts stack users can modify or extend (templates).

This article gives you a quick introduction to Appsody repositories, stacks, and templates and helps you determine when to create a new stack, when to modify a stack, and when to use or modify a template.

Repositories, stacks, and templates

The hierarchy of objects in Appsody is made up of repositories at the top level, followed by stacks, which include a curated image full of technologies, and templates at the lowest level. Appsody repositories offer a central hub for you to use the Appsody stacks.

flowchart

You can use the appsody CLI to add or remove repositories and initialize new projects based on stacks. For example, appsody repo add kabanero https://github.com/kabanero-io/collections/releases/download/v0.1.2/kabanero-index.yaml makes your local installation aware of a new remote stack repository, with its stacks and templates now available for local development.

As an example, here is the output of appsody list when multiple repositories are registered in your local Appsody configuration (stored under ~/.appsody):

$  appsody list

REPO            ID                              VERSION         TEMPLATES               DESCRIPTION
appsodyhub      java-microprofile               0.2.13          *default                Eclipse MicroProfile on Open Liberty & OpenJ9 using Maven
appsodyhub      java-spring-boot2               0.3.11          *default, kotlin        Spring Boot using OpenJ9 and Maven
appsodyhub      nodejs                          0.2.5           *simple                 Runtime for Node.js applications
appsodyhub      nodejs-express                  0.2.5           *simple, skaffold       Express web framework for Node.js
appsodyhub      nodejs-loopback                 0.1.4           *scaffold               LoopBack 4 API Framework for Node.js
appsodyhub      python-flask                    0.1.3           *simple                 Flask web Framework for Python
appsodyhub      swift                           0.1.4           *simple                 Runtime for Swift applications
custom_stack    my-stack-name                   1.0.0           *default                My custom stack
experimental    java-spring-boot2-liberty       0.1.8           *default                Spring Boot on Open Liberty & OpenJ9 using Maven
experimental    nodejs-functions                0.1.3           *simple                 Serverless runtime for Node.js functions
experimental    quarkus                         0.1.5           *default                Quarkus runtime for running Java applications
experimental    vertx                           0.1.1           *default                Eclipse Vert.x runtime for running Java applications
local_stack     java-microprofile               0.2.6           *default                Eclipse MicroProfile using OpenJ9 and Maven
local_stack     java-spring-boot2               0.3.2           *default                Spring Boot using OpenJ9 and Maven
local_stack     nodejs                          0.2.3           *simple                 Runtime for Node.js applications
local_stack     nodejs-express                  0.2.3           *simple                 Express web framework for Node.js
local_stack     nodejs-loopback                 0.1.0           *                       LoopBack API framework for Node.js
local_stack     swift                           0.1.2           *simple                 Runtime for Swift applications
my_local        java-microprofile               0.2.6           *default, gdpr, restapi Eclipse MicroProfile on Open Liberty & OpenJ9 using Maven
my_stacks       java-microprofile               0.2.6           *default                Eclipse MicroProfile using OpenJ9 and Maven
my_stacks       java-spring-boot2               0.3.2           *default                Spring Boot using OpenJ9 and Maven
my_stacks       nodejs                          0.2.3           *simple                 Runtime for Node.js applications
my_stacks       nodejs-express                  0.2.3           *simple                 Express web framework for Node.js
my_stacks       nodejs-loopback                 0.1.0           *                       LoopBack API framework for Node.js
my_stacks       swift                           0.1.2           *simple                 Runtime for Swift applications

The first column is the repository, the second is the stack name, followed by the version of the stack, and a list of available templates. The Appsody CLI initializes an app through a combination of thes parts. For example, in this instance:

$ appsody init  my_local/java-microprofile default

the CLI initializes an application based on the default Java MicroProfile template.

Decision tree for whether to use, modify, or create a stack

An Appsody application contains a Docker image created from a stack and injects the template and user files into it. Because Dockerfiles are part of the stack, they can’t be modified by a user accessing a stack. However, templates are copied into your working directory during the appsody init process. Appsody users are free to make changes to anything that’s part of the template, which is combined with the stack image during the appsody build phase.

Depending on your needs, you will either:

  • Select an existing stack and base your application on one of its templates
  • Modify or extend a stack
  • Create an entirely new stack

The question is: how do you decide which option is best for your particular use case? We’ve created a decision tree to help you make that decision.

flowchart

Creating or modifying stacks

Stacks may contain code that is always part of the application and cannot be modified, while templates contain code that users can modify. So, for example, suppose you decide that everyone in an organization that uses a private repository must have a set of dependencies and libraries in their microservice. In this scenario, you would want to build a set of customized stacks in a private repository.

Other examples of when you would want to create or modify a stack (or multiple stacks) include:

  • Your organization needs to create a library of base images that come pre-built with certain common features (health checks, telemetry, security, logging, etc) that should be part of every microservice. These features are controlled by the Dockerfile that is stored in the Appsody repository. You can update the Dockerfile at any time, and the Appsody CLI will pull the latest available version during build time.
  • When a user initializes an instance of an Appsody template, the Dockerfile is not downloaded to the user’s sandbox as part of the initialization. The appsody build step downloads it from the repository each time, compiling the user’s code and adding it to the appropriate path in the base image.

    As an example, in this excerpt from the Java MicroProfile stack Dockerfile, note that the stack Dockerfile copies the Java source code into the image and compiles it. This Dockerfile is only available as part of the stack and can’t be changed by developers who don’t have write access to the repository.

      COPY . /project
    
      WORKDIR /project/user-app
    
      RUN mvn install -DskipTests
    
      RUN cd target && \
          unzip *.zip && \
          mkdir /config && \
          mv wlp/usr/servers/*/* /config/
    

You can add dependencies into the container via language-dependent mechanisms without changing the stack. For example, you can modify pom.xml and have Maven add dependencies to Java stacks or make changes to the Pipfile to add dependencies in a Python stack.

Using templates

If your stack doesn’t require a new function, you can work from one of our existing templates or create a new one to meet your needs. Templates can provide scaffolding code that’s suitable for starting a microservice for a specific task, for example, creating a REST API backend for a web or mobile application.

Templates:

  • are easy to create. You simply copy an existing stack and tweak it.
  • allow you to build many variants of an existing stack for different use cases.
  • give users a starting point from which to build their service, but won’t lock them into any particular requirement.

Conclusion

Appsody can speed the development of cloud-native applications by allowing you to building on existing stacks and templates optimized for specific use cases, instead of starting from scratch. Hopefully this article helped you understand about how the different parts of Appsody fit together and when you should create a new stack, modify an existing one, or just use or modify a template.

Next steps

Yan Koyfman