DevOps

6 Docker .NET App Templates To Get You Started On Containers

This is the first blog of a three part blog series that discusses the automated deployment of .NET applications on both Linux and Windows containers.

In this blog, we will cover the deployment of very basic ASP.NET and ASP.NET MVC applications on Linux containers using HyperForm, a deployment automation platform that simplifies the application journey to containers. The blog covers 6 application templates that include Nginx and Apache HTTP for reverse proxy.

To run & manage the simple Docker ASP.NET “Hello MVC” and “Hello Web” applications on 18 different clouds and virtualization platforms (including HyperGrid, vSphere, OpenStack, AWS, Rackspace, Microsoft Azure, Google Compute Engine, DigitalOcean, IBM SoftLayer, etc.), make sure that you either:

0-aspnet-app-screenshot

Background

Containerizing enterprise applications is still a challenge mostly because existing application composition frameworks do not address complex dependencies, external integrations or application life-cycle management tasks post-provision.

HyperForm, available in hosted and on-premise versions, addresses all of these challenges and simplifies the containerization of enterprise applications through an advanced application composition framework that extends Docker Compose supporting

  • advanced plug-ins that can be invoked at more than 20 different lifecycle stages to enable service discovery, on-the-fly containerization and application storage automation, and
  • data injection to support complex application dependencies.

The Plug-ins framework, which relies on custom scripts that can be written in BASH, PowerShell, Perl, Ruby or Python, enables advanced application deployment and facilitates quick integration with any external service – including storage, networking or monitoring solutions.

Once an application is deployed, a user can access monitoring, alerts and notifications, continuous delivery using Jenkins, application backups, scale in/out, in-browser terminal to access the containers, log viewing, and container updates using custom plug-ins.

Why Even Bother with Containers?

Containers have been the driving force behind efforts to accelerate software development, cloud migration, and the modernization of legacy applications. The main advantages of containers are:

  • Application Portability – Docker containers run exactly the same on any Linux host. This eliminates the challenge of deploying applications across different compute infrastructure (e.g. local developer machine, vSphere VM or in the cloud).
  • Higher Server Density – The light-weight nature of containers allow developers to optimize server utilization for their application workloads by running more containers on the same host while achieving the same isolation and resource allocation benefits of virtual machines.

For developers who are still wondering what the exact differences are between virtual machines and containers, here’s a list of the key differences.

Application Storage Overhead

  • Virtual Machines: Each application workload runs on a separate virtual machine – which typically needs Gigabytes of OS overhead
  • Containers: Containers can run in isolation on the same physical or virtual machine – in which one common OS is used for all containers. The Docker Engine overhead is pretty small – i.e. megabytes.

Instantiation

  • Virtual Machines: Boot up time of both the OS and the application
  • ContainersApplication instantiation time only – i.e. time to spin up Linux processes

Resource Allocation

  • Virtual Machines: Generally rigid. Virtual CPU and Memory are typically pre-allocated to a VM and are hard to change post-provision – depending on the virtualization platform or cloud provider used.
  • Containers: Generally flexible. CPU and Memory maximum limits can be defined for containers if desired (using the cpu_shares and mem_limit parameters). By default, containers can continue to consume the resources available on the underlying machine. With HyperForm, the minimum limits for CPU and Memory can also be defined – allowing users to place application workloads on machines that have enough CPU and Memory resources. You can read more about this here: http://dchq.co/docker-compose.html#docker-nodejs.

Building The Docker Images Using microsoft/aspnet:1.0.0-rc1-final

If you have a Dockerfile in your code repository for building your latest images, then you can use HyperForm to automate the building of the Docker image as well as pushing the new images to one of the registered Docker registries.

Of course, if you’re using Docker Hub, then you have the option to use the Automated Builds feature. However, if you’re using a private registry, then HyperForm can provide the needed image build automation.

The ASP.NET examples used in this blog were cloned from the official Microsoft projects on GitHub:

Once logged in to HyperForm (either the hosted DCHQ.io or on-premise version), a user can navigate to Automate > Image Build and then click on the + button to create a new Dockerfile (Git/GitHub/BitBucket) image build.
Provide the required values as follows:

  • Git URL – (e.g. https://github.com/dchqinc/docker-aspnet-hellomvc.git or https://github.com/dchqinc/docker-aspnet-helloweb)
  • Git Branch – this field is optional — but a user can specify a branch from a GitHub project. The default branch is master.
  • Git Credentials – a user can store the credentials to a private GitHub repository securely in HyperForm. This can be done by navigating to Cloud Providers and clicking on the + to select Credentials
  • Cluster – the building of Docker images is orchestrated through the HyperForm agent. As a result, a user needs to select a cluster on which an agent will be used to execute the building of Docker images. If a cluster has not been created yet, please refer to this section to either register already running hosts or automate the provisioning of new virtual infrastructure.
  • Push to Registry – a user can push the newly created image on either a public or private repository on Docker Hub, Nexus, Artifactory or Quay. To register a Docker registry account, a user should navigate to Cloud Providers and clicking on the + to select Docker Registries
  • Repository – this is the name of the repository on which the image will be pushed. For example, our image was pushed todchq/php-example:latest
  • Tag – this is the tag name that you would like to give for the new image. The supported tag names in HyperForm include:
    • {{date}} — formatted date
    • {{timestamp}} — the full time-stamp
  • Cron Expression – a user can schedule the building of Docker images using out-of-box cron expressions. This facilitates daily and nightly builds for users.
  • Pre Build Plugins and Post Build Plugins – a user can execute plug-ins on the machines used to run the image builds – e.g. installing Linux libraries or running post image build cleanup scripts.
  • Who can Manage – a user can mark this build as private or share it with other users or groups.

Once the required fields are completed, a user can click Save.

0-aspnet-automated-image-builds_orig

A user can then click on the Play Button to build the Docker image on-demand.0-aspnet-running-automated-image-builds_origHere’s the actual Dockerfile used to build the Docker image for the ASP.NET Hello Web application.

https://github.com/dchqinc/docker-aspnet-helloweb/blob/master/Dockerfile

Building The YAML-Based Application Templates That Can Re-Used On Any Linux Host Running Anywhere

HyperForm is fully compatible with Docker Compose (https://docs.docker.com/compose/compose-file/).

The platform however provides core (optional) enhancements to Docker Compose supporting advanced plug-ins that can be invoked at more than 20 different lifecycle stages to enable service discovery, on-the-fly containerization and application storage automation.

It also supports cross-image environment variable bindings, automatic container IP retrieval and injection, and additional parameters like mem_min, publish_all, cluster_size, and registry_id. The service discovery framework takes care of re-configuring the load balancers and other application components when a cluster is scaled in/out or when the containers are stopped/started.

To create an application template, a user can log into HyperForm (either the hosted DCHQ.io or on-premise version), navigate to Blueprints > App/Machine and then click on the + button to create a new Docker Compose template.

We have created 6 application templates for the basic ASP.NET “Hello MVC” and “Hello Web” applications but with different web servers for reverse proxy and load balancing.

Docker ASP.NET Hello MVC
0-aspnet-customize-and-run_orig

aspnet-mvc:
  image: dchq/aspnet-hellomvc:latest
  mem_min: 50m
  host: host1
  publish_all: true
  cluster_size: 1

Docker ASP.NET Hello MVC with Nginx
0-aspnet-customize-and-run_orig

nginx:
  image: nginx:latest
  publish_all: true
  host: host1
  mem_min: 50m
  plugins:
    - !plugin
      id: 0H1Nk
      restart: true
      lifecycle: on_create, post_scale_out:aspnet-mvc, post_scale_in:aspnet-mvc
      arguments:
        # Use container_private_ip if you're using Docker networking
        - servers=server {{aspnet-mvc | container_private_ip}}:5004;
        # Use container_hostname if you're using Weave networking
        #- servers=server {{aspnet-mvc | container_hostname}}:5004;
aspnet-mvc:
  image: dchq/aspnet-hellomvc:latest
  mem_min: 100m
  host: host1
  publish_all: false
  cluster_size: 1

 Docker ASP.NET Hello MVC with Apache HTTP
0-aspnet-customize-and-run_orig

http-lb:
  image: httpd:latest
  publish_all: true
  mem_min: 50m
  host: host1
  plugins:
    - !plugin
      id: uazUi
      restart: true
      lifecycle: on_create, post_scale_out:aspnet-mvc, post_scale_in:aspnet-mvc
      arguments:
        # Use container_private_ip if you're using Docker networking
        - BalancerMembers=BalancerMember http://{{aspnet-mvc | container_private_ip}}:5004
        # Use container_hostname if you're using Weave networking
        #- BalancerMembers=BalancerMember http://{{aspnet-mvc | container_hostname}}:5004
aspnet-mvc:
  image: dchq/aspnet-hellomvc:latest
  mem_min: 100m
  host: host1
  publish_all: false
  cluster_size: 1

Docker ASP.NET Hello Web
0-aspnet-customize-and-run_orig

aspnet:
  image: dchq/aspnet-helloweb:latest
  mem_min: 50m
  host: host1
  publish_all: true
  cluster_size: 1

Docker ASP.NET Hello Web with Nginx
0-aspnet-customize-and-run_orig

nginx:
  image: nginx:latest
  publish_all: true
  host: host1
  mem_min: 50m
  plugins:
    - !plugin
      id: 0H1Nk
      restart: true
      lifecycle: on_create, post_scale_out:aspnet, post_scale_in:aspnet
      arguments:
        # Use container_private_ip if you're using Docker networking
        - servers=server {{aspnet | container_private_ip}}:5004;
        # Use container_hostname if you're using Weave networking
        #- servers=server {{aspnet | container_hostname}}:5004;
aspnet:
  image: dchq/aspnet-helloweb:latest
  mem_min: 100m
  host: host1
  publish_all: false
  cluster_size: 1

Docker ASP.NET Hello Web with Apache HTTP
0-aspnet-customize-and-run_orig

http-lb:
  image: httpd:latest
  publish_all: true
  mem_min: 50m
  host: host1
  plugins:
    - !plugin
      id: uazUi
      restart: true
      lifecycle: on_create, post_scale_out:aspnet, post_scale_in:aspnet
      arguments:
        # Use container_private_ip if you're using Docker networking
        - BalancerMembers=BalancerMember http://{{aspnet | container_private_ip}}:5004
        # Use container_hostname if you're using Weave networking
        #- BalancerMembers=BalancerMember http://{{aspnet | container_hostname}}:5004
aspnet:
  image: dchq/aspnet-helloweb:latest
  mem_min: 100m
  host: host1
  publish_all: false
  cluster_size: 1

Environment Variable Bindings Across Images

A user can create cross-image environment variable bindings by making a reference to another image’s environment variable or container values. For example, the plug-used in the Apache HTTP container is referencing the container private IP of the ASP.NET container BalancerMembers=BalancerMember http://{{aspnet-mvc | container_private_ip}}:5004 – in which the container IP of the ASP.NET Hello MVC container is automatically retrieved and injected in the Apache HTTP configuration file.

Here is a list of supported environment variable values:

  • {{alphanumeric | 8}} – creates a random 8-character alphanumeric string. This is most useful for creating random passwords.
  • {{Image Name | ip}} – allows you to enter the host IP address of a container as a value for an environment variable. This is most useful for allowing the middleware tier to establish a connection with the database.
  • {{Image Name | container_hostname}} or {{Image Name | container_ip}} – allows you to enter the name of a container as a value for an environment variable. This is most useful for allowing the middleware tier to establish a secure connection with the database (without exposing the database port).
  • {{Image Name | container_private_ip}} – allows you to enter the internal IP of a container as a value for an environment variable. This is most useful for allowing the middleware tier to establish a secure connection with the database (without exposing the database port).
  • {{Image Name | port_Port Number}} – allows you to enter the Port number of a container as a value for an environment variable. This is most useful for allowing the middleware tier to establish a connection with the database. In this case, the port number specified needs to be the internal port number – i.e. not the external port that is allocated to the container. For example, {{PostgreSQL | port_5432}} will be translated to the actual external port that will allow the middleware tier to establish a connection with the database.
  • {{Image Name | Environment Variable Name}} – allows you to enter the value an image’s environment variable into another image’s environment variable. The use cases here are endless – as most multi-tier applications will have cross-image dependencies.

Using plug-ins and the host parameter to deploy a highly-available Docker Java application

When creating application templates in HyperForm, the host parameter allows you to specify the host you would like to use for container deployments. This is possible if you have selected Weave as the networking layer when creating your clusters. That way you can ensure high-availability for your application server clusters across different hosts (or regions) and you can comply with affinity rules to ensure that the database runs on a separate host for example. Here are the values supported for the host parameter:

  • host1, host2, host3, etc. – selects a host randomly within a data-center (or cluster) for container deployments
  • IP Address 1, IP Address 2, etc. — allows a user to specify the actual IP addresses to use for container deployments
  • Hostname 1, Hostname 2, etc. — allows a user to specify the actual hostnames to use for container deployments
  • Wildcards (e.g. “db-”, or “app-srv-”) – to specify the wildcards to use within a hostname

Using plug-in lifecycle stages for Docker service discovery

The service discovery framework in HyperForm provides event-driven life-cycle stages that executes custom scripts to re-configure application components. This is critical when scaling out clusters for which a load balancer may need to be re-configured or a replica set may need to be re-balanced.

You will notice that the Nginx and Apache HTTP plug-in are getting executed during these different stages or events:

  • When the Nginx or the Apache HTTP container is created — in this case, the container IP’s of the application servers are injected into the default configuration file to facilitate the load balancing to the right services
  • When the ASP.NET application server cluster is scaled in or scale out — in this case, the updated container IP’s of the application servers are injected into the default configuration file to facilitate the load balancing to the right services
  • When the ASP.NET application servers are stopped or started — in this case, the updated container IP’s of the application servers are injected into the default configuration file to facilitate the load balancing to the right services

So the service discovery framework here is doing both service registration (by keeping track of the container IP’s and environment variable values) and service discovery (by executing the right scripts during certain events or stages).

The lifecycle parameter in plug-ins allows you to specify the exact stage or event to execute the plug-in. If no lifecycle is specified, then by default, the plug-in will be execute on_create. Here are the supported lifecycle stages:

  • on_create — executes the plug-in when creating the container
  • on_start — executes the plug-in after a container starts
  • on_stop — executes the plug-in before a container stops
  • on_destroy — executes the plug-in before destroying a container
  • pre_create – executes the plug-in before creating the container
  • post_create — executes the plug-in after the container is created and running
  • post_start[:Node] — executes the plug-in after another container starts
  • post_stop[:Node] — executes the plug-in after another container stops
  • post_destroy[:Node] — executes the plug-in after another container is destroyed
  • post_scale_out[:Node] — executes the plug-in after another cluster of containers is scaled out
  • post_scale_in[:Node] — executes the plug-in after another cluster of containers is scaled in
  • cron(0 1 1 * * ?) – schedules the plug-in based on a specified cron expression. Here are some examples for cron expressions.
  • exec_on_machine – executes the plug-in on the underlying machine. This lifecycle can be used with other container life cycles. For example, exec_on_machine pre_create will execute the plug-in on the machine before creating the container.

Provisioning The Underlying Infrastructure On Any Cloud

Once an application is saved, a user can deploy the application to a cluster (or pool of servers) that is already available or provision infrastructure on 18 different cloud end-points including HyperGrid, VMware vSphere, OpenStack, CloudStack, Amazon Web Services, Rackspace, Microsoft Azure, DigitalOcean, IBM SoftLayer, and many others.

For detailed instructions on automating infrastructure provisioning, please refer to the detailed documentation here:
http://dchq.co/docker-infrastructure-as-a-service.html

The recorded demo in this blog uses a cluster of provisioned VM’s on Microsoft Azure Resource Manager. For instructions on automating the provisioning of VM’s on ARM using reusable YAML templates, please refer to the detailed documentation here.

http://dchq.co/docker-azure-resource-manager.html

Deploying the ASP.NET Application on the HyperGrid Cluster

A user can deploy the ASP.NET applications on any of the available clusters.  On the HyperForm SaaS Platform (http://dchq.io) – a public cluster set up on HyperGrid infrastructure is available for free application deployment (up to 2GB of Memory). This cluster is meant for DEV/TEST deployments only and is refreshed every 2 to 3 months.

To deploy the application on the HyperGrid cluster, a user can navigate to the Library page, click on Customize and then select the available HyperGrid cluster.0-aspnet-deploy-app-on-hypergrid-cluster_orig

Accessing The In-Browser Terminal For The Running Containers

A command prompt icon should be available next to the containers’ names on the Apps page. This allows users to enter the container using a secure communication protocol through the agent message queue. A white list of commands can be defined by the Tenant Admin to ensure that users do not make any harmful changes on the running containers.

For the ASP.NET deployment for example, we used the command prompt to make sure that the application code is indeed under the /app directory.0-aspnet-in-browser-terminal_orig

Monitoring The CPU, Memory & I/O Utilization Of The Running Containers

Once the application is up and running, users can monitor the CPU, Memory, & I/O of the running containers to get alerts when these metrics exceed a pre-defined threshold. This is especially when performing functional & load testing.

A user can perform historical monitoring analysis and correlate issues to container updates or build deployments. This can be done by clicking on the Stats link. A custom date range can be selected to view CPU, Memory and I/O historically.0-aspnet-container-monitoring_orig

Replacing (Redeploying) Containers When New Images Are Pushed Into A Registry

For developers wishing to follow the “immutable” containers model by rebuilding Docker images containing the application code and spinning up new containers with every application update, HyperForm provides an automated container replacement workflow that pulls that latest image in a registry and replaces the running container with the latest image.

To set up a container redeployment (or replacement) profile, a user can select Container Redeploy Profile from the Action menu.0-aspnet-container-redeploy-selection_orig

A user can then select one of the stored Docker registries and enter the name of the image that should be used when replacing the running container. To register a Docker Hub, Nexus, Artifactory or Quay account, a user should navigate to Cloud Providers and clicking on the + to select Docker Registries.0-aspnet-container-redeploy-profile-form_orig

Scaling Out The ASP.NET Application

If the running application becomes resource constrained, a user can scale out the application to meet the increasing load. Moreover, a user can schedule the scale out during business hours and the scale in during weekends for example.

To scale out the cluster of the ASP.NET containers from 1 to 2, a user can click on the Actions menu of the running application and then select Scale Out. A user can then specify the new size for the cluster and then click on Run Now.

The service discovery plug-in configured for the load balancer (i.e. Nginx or Apache HTTP) will be automatically triggered to inject the container IP’s of the new application servers into the default configuration file to facilitate the load balancing to the right services.0-aspnet-scale-out_orig

An application time-line is available to track every change made to the application for auditing and diagnostics. This can be accessed from the expandable menu at the bottom of the page of a running application.
0-aspnet-application-timeline_orig

Alerts and notifications are available for when containers or hosts are down or when the CPU & Memory Utilization of either hosts or containers exceed a defined threshold.

Executing Plug-ins Post-Provision to Update an Application

If a user would like to make simple changes to the ASP.NET application by leveraging ASP.NET Dynamic Compilation (https://msdn.microsoft.com/en-us/library/ms366723.aspx), then a custom script plug-in can be invoked to make such updates.

The Plug-ins framework, which relies on custom scripts that can be written in BASH, PowerShell, Perl, Ruby or Python, enables advanced application deployment and facilitates quick integration with any external service – including storage, networking or monitoring solutions.

To do this, a user must first create a plug-in by navigating to Blueprints > Plug-ins.

Then from the application’s page, a user can select Plug-ins Run from the Actions menu.0-aspnet-plugins-run-selection_orig

As user can then search for the plug-in and override the available arguments if needed (e.g. URL to fetch the latest ASP.NET files). Since ASP.NET Dynamic Compilation is used in this example, then a container restart is not needed. However for other updates that require a quick restart of the container, then the Restart toggle can be selected.0-aspnet-plugins-run_orig

Conclusion

Containerizing enterprise applications is still a challenge mostly because existing application composition frameworks do not address complex dependencies, external integrations or application life-cycle management tasks post-provision.

HyperForm, available in hosted and on-premise versions, addresses all of these challenges and simplifies the containerization of enterprise applications through an advanced application composition framework that extends Docker Compose supporting

  • advanced plug-ins that can be invoked at more than 20 different lifecycle stages to enable service discovery, on-the-fly containerization and application storage automation, and
  • data injection to support complex application dependencies.

To run & manage the simple Docker ASP.NET “Hello MVC” and “Hello Web” applications on 18 different clouds and virtualization platforms (including HyperGrid, vSphere, OpenStack, AWS, Rackspace, Microsoft Azure, Google Compute Engine, DigitalOcean, IBM SoftLayer, etc.), make sure that you either:

Amjad Afanah

Amjad Afanah is the founder of DCHQ. He has extensive experience in application deployment automation and systems management. DCHQ was part of 500 Startups.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button