Multi-container Linux Web App

6 minute read • May 7, 2018

Yi Liao MSFT
The App Service team is happy to announce the public preview of Multi-container support in Web App for Containers.

Multi-container Web App Concept

App Service Linux community has repeatedly asked for the capability to deploy multiple containers for a single App.  Customers want to have additional containers to complement the primary container and have these containers form an “operable” unit. The benefits for Multi-container are: 1. customer can separate capabilities such as proxies, cache and storage into additional containers and manage the source code and container images independently following the “separation of concerns” design pattern in containerization;  2. customer can operate those containers as an atomic unit and leverage App Service’s rich feature set for application life-cycle management, scaling and diagnosis, without the needs to stand up a container Orchestrator and to manage the hosting infrastructure by themselves.  Today we're happy to announce the public preview of Multi-container support in Web App for Containers!

Primary Use Case

In App Service Linux community, the primary multi-container use case is that customer deploy a stateless web app with multiple containers (Web, Proxy, Cache or Git-mirror) to a single App Service plan.  For example: customer can have one container for web frontend and have another container for session cache using Redis, all deployed to the same App Service plan. All containers can communicate to each other through a Docker Bridge network using internal IP addresses.

Supported Configurations 

In Public Preview, we support Docker-Compose and Kubernetes configuration format as they’re the “standard” ways to describe multi-container applications. We don’t want to invent another format.  It’s also convenient for the customers because the formats are well documented and widely used by Docker community. Customer can create or configure a Multi-container app from Azure Portal or through Azure CLI. Customer can describe a multi-container app using Docker Compose and Kubernetes configuration format in a yaml file. Customer can upload the multi-container config file through portal UI or point to the URL if the config file is hosted elsewhere (note: URL link support will come soon after announcement), portal screenshot as below. For example, customer can use Docker-Compose format to describe a multi-container app:
docker-compose.yml version: '3' services: web: image: "appsvcsample/flaskapp" # this image repo's source code come from "Get started with Docker Compose" on docker.com ports: - "80:80" redis: image: "redis:alpine"
CLI command to create a multi-container app:
$ az webapp create --resource-group [resource group] --plan [service plan] --name [app name] --multicontainer-config-type "compose" --multicontainer-config-file [path to "docker-compose.yml"]
CLI command to configure a multi-container app:
$ az webapp config container set --resource-group [resource group] --name [app name] --multicontainer-config-type "compose" --multicontainer-config-file [path to "docker-compose.yml"]
Customer can also use Kubernetes configuration format to describe a multi-container app:
my-kube.yml apiVersion: v1 kind: Pod metadata: name: python spec: containers: - name: web image: appsvcsample/flaskapp # this image repo's source code come from "Get started with Docker Compose" on docker.com ports: - containerPort: 80 - name: redis image: redis:alpine
CLI command to create a multi-container app:
$ az webapp create --resource-group [resource group] --plan [service plan] --name [app name] --multicontainer-config-type "kube" --multicontainer-config-file [path to "my-kube.yml"]
CLI command to configure a multi-container app:
$ az webapp config container set --resource-group [resource group] --name [app name] --multicontainer-config-type "kube" --multicontainer-config-file [path to "my-kube.yml"]

Samples

We're working to add more Multi-container web app samples.  To get you started quickly, please feel free to copy the samples provided in this blog post, or download more from Github.

Scaling Multi-container Web App

Customer can scale up and / or out a stateless multi-container app just as any web apps hosted on App Service, using the same scaling features provided by App Service. If you would like to use a database in container for dev/testing purposes in a single-host app, please make sure to use the persisted shared storage to store your database files, so the database files can be persisted during app restarts. First, you should enable the App Service shared storage following the instructions at here. Then, you should mount the shared storage to a directory within the Docker container where you store the database files, a MySQL example in docker-compose.yml:
services: mysql: image: mysql:5.7 volumes: - ${WEBAPP_STORAGE_HOME}/site:[/path/in/container/where/mysqlfiles/needs/to/be/mounted]
If you would like to scale out a multi-container app to multiple hosts in an App Service plan and use the app for production purpose, we strongly recommend you use Azure Database services instead of putting the database in a container. For example, for a WordPress app you can move the database to an Azure Database for MySQL.  To do that, please follow the following steps:
WORDPRESS_DB_HOST: [mysql server name].mysql.database.azure.com WORDPRESS_DB_USER: [db user name]@[mysql server name] WORDPRESS_DB_PASSWORD: [database password]
  • Test the configuration locally with docker-compose up before you push it to App Service.

Limitations in Public Preview

We wanted to put this feature out as soon as possible so customer can validate and provide more feedbacks during Preview. There are certain limitations in this Public Preview release. We support Docker-Compose and Kubernetes format to describe a multi-container app, but we don’t support all their configuration objects during Public Preview. Our goal is to support any configuration objects that are meaningful to App Service during this release. The supported objects and limitations are as follows:

Docker-Compose

Supported configuration in Public Preview: services A service definition contains configuration that is applied to each container started for that service, much like passing command-line parameters to docker container create. image Specify the image to start the container from. Can either be a repository/tag or a partial image ID. ports Expose ports by mapping ports in the HOST:CONTAINER pattern, recommend explicitly specifying your port mapping as string. App Service specific, we would only expose one service port to external, we would identify a single service port to expose to external based on the HOST port provided for each service, we're looking for port 80 or port 8080. environment Add environment variables. You can use an array as input. The dictionary format is not supported in current release, we will add support for dictionary format in next release.
environment:  #supported RACK_ENV: development SHOW: 'true' SESSION_SECRET: environment:  #not supported - RACK_ENV=development - SHOW=true - SESSION_SECRET
volumes Mount host paths or named volumes, specified as sub-options to a service. We support both persisted volume and non-persisted volume. To use the persisted volume, please enable the shared storage by set WEBSITES_ENABLE_APP_SERVICE_STORAGE=TRUE.  You can reference the shared storage using ${WEBAPP_STORAGE_HOME}. For example, you can mount the shared storage to /tmp in the container:
volumes: - ${WEBAPP_STORAGE_HOME}/site/wwwroot:/tmp
command Override the default command. Currently we support the collection format, for example: command: ["bundle", "exec", "thin", "-p", "3000"]. We will add support for a single string after public preview. entrypoint Override the default entrypoint. restart “no” is the default restart policy, and it does not restart a container under any circumstance. When “always” is specified, the container always restarts. More info at https://docs.docker.com/compose/compose-file/#restart. Configuration not supported in Public Preview: (besides the list below, any other Docker-Compose syntax not explicitly called out in the “Supported Configuration” section will not be supported in Public Preview) build Configuration options that are applied at build time. We don’t support “build” image locally as we need an explicit image to start the container with. depends_on Express dependency between services. we don’t currently support “depends_on” to specify the dependencies among containers, but we plan to support this shortly after Public Preview. networks Networks to join. We don’t support additional “networks” as we run all containers on one Bridge network. secrets Grant access to secrets on a per-service basis using the per-service secrets configuration. We don’t currently support it, but we plan to support this shortly after Public Preview.