Deploy an application with a custom container image

Caution

This article references CentOS, a Linux distribution that is End Of Life (EOL) status. Please consider your use and plan accordingly. For more information, see the CentOS End Of Life guidance.

Note

The Basic, Standard, and Enterprise plans will be deprecated starting from mid-March, 2025, with a 3 year retirement period. We recommend transitioning to Azure Container Apps. For more information, see the Azure Spring Apps retirement announcement.

The Standard consumption and dedicated plan will be deprecated starting September 30, 2024, with a complete shutdown after six months. We recommend transitioning to Azure Container Apps. For more information, see Migrate Azure Spring Apps Standard consumption and dedicated plan to Azure Container Apps.

This article applies to: ✔️ Standard ✔️ Enterprise

This article explains how to deploy Spring Boot applications in Azure Spring Apps using a custom container image. Deploying an application with a custom container supports most features as when deploying a JAR application. Other Java and non-Java applications can also be deployed with the container image.

Prerequisites

  • A container image containing the application.
  • The image is pushed to an image registry. For more information, see Azure Container Registry.

Note

The web application must listen on port 1025 for the Standard plan and on port 8080 for the Enterprise plan. The way to change the port depends on the framework of the application. For example, specify SERVER_PORT=1025 for Spring Boot applications or ASPNETCORE_URLS=http://+:1025/ for ASP.NET Core applications. You can disable the probe for applications that don't listen on any port. For more information, see How to configure health probes and graceful termination periods for apps hosted in Azure Spring Apps.

Deploy your application

To deploy an application to a custom container image, use the following steps:

To deploy a container image, use one of the following commands:

  • To deploy a container image to the public Docker Hub to an app, use the following command:

    az spring app deploy \
       --resource-group <your-resource-group> \
       --name <your-app-name> \
       --container-image <your-container-image> \
       --service <your-service-name>
    
  • To deploy a container image from ACR to an app, or from another private registry to an app, use the following command:

    az spring app deploy \
       --resource-group <your-resource-group> \
       --name <your-app-name> \
       --container-image <your-container-image> \
       --service <your-service-name>
       --container-registry <your-container-registry> \
       --registry-password <your-password> |
       --registry-username <your-username>
    

To overwrite the entry point of the image, add the following two arguments to any of the above commands:

    --container-command "java" \
    --container-args "-jar /app.jar -Dkey=value"

To disable listening on a port for images that aren't web applications, add the following argument to the above commands:

    --disable-probe true

Feature Support matrix

The following matrix shows what features are supported in each application type.

Feature Spring Boot Apps - container deployment Polyglot Apps - container deployment Notes
App lifecycle management ✔️ ✔️
Support for container registries ✔️ ✔️
Assign endpoint ✔️ ✔️
Azure Monitor ✔️ ✔️
APM integration ✔️ ✔️ Supported by manual installation.
Blue/green deployment ✔️ ✔️
Custom domain ✔️ ✔️
Scaling - auto scaling ✔️ ✔️
Scaling - manual scaling (in/out, up/down) ✔️ ✔️
Managed identity ✔️ ✔️
Spring Cloud Eureka & Config Server ✔️
API portal for VMware Tanzu ✔️ ✔️ Enterprise plan only.
Spring Cloud Gateway for VMware Tanzu ✔️ ✔️ Enterprise plan only.
Application Configuration Service for VMware Tanzu ✔️ Enterprise plan only.
Application Live View for VMware Tanzu ✔️ Enterprise plan only.
VMware Tanzu Service Registry ✔️ Enterprise plan only.
VNET ✔️ ✔️ Add registry to allowlist in NSG or Azure Firewall.
Outgoing IP Address ✔️ ✔️
E2E TLS ✔️ ✔️ Trust a self-signed CA.
Liveness and readiness settings ✔️ ✔️
Advanced troubleshooting - thread/heap/JFR dump ✔️ The image must include Bash and the JDK with PATH specified.
Bring your own storage ✔️ ✔️
Integrate service binding with Resource Connector ✔️
Availability Zone ✔️ ✔️
App Lifecycle events ✔️ ✔️
Reduced app size - 0.5 vCPU and 512 MB ✔️ ✔️
Automate app deployments with Terraform ✔️ ✔️
Soft Deletion ✔️ ✔️
Interactive diagnostic experience (AppLens-based) ✔️ ✔️
SLA ✔️ ✔️

Note

Polyglot apps include non-Spring Boot Java, NodeJS, AngularJS, Python, and .NET apps.

Common points to be aware of when deploying with a custom container

The following points will help you address common situations when deploying with a custom image.

Trust a Certificate Authority

There are two options to trust a Certificate Authority:

Option 1: Upload via Azure Spring Apps

To load the CA certs into your apps, see Use TLS/SSL certificates in your application in Azure Spring Apps. Then the certs will be mounted into the location /etc/azure-spring-cloud/certs/public/.

Option 2: Manual installation in the image

To trust a CA in the image, set the following variables depending on your environment:

  • You must import Java applications into the trust store by adding the following lines into your Dockerfile:

    ADD EnterpriseRootCA.crt /opt/
    RUN keytool -keystore /etc/ssl/certs/java/cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias EnterpriseRootCA -file /opt/EnterpriseRootCA.crt
    
  • For Node.js applications, set the NODE_EXTRA_CA_CERTS environment variable:

    ADD EnterpriseRootCA.crt /opt/
    ENV NODE_EXTRA_CA_CERTS="/opt/EnterpriseRootCA.crt"
    
  • For Python, or other languages relying on the system CA store, on Debian or Ubuntu images, add the following environment variables:

    ADD EnterpriseRootCA.crt /usr/local/share/ca-certificates/
    RUN /usr/sbin/update-ca-certificates
    
  • For Python, or other languages relying on the system CA store, on CentOS or Fedora based images, add the following environment variables:

    ADD EnterpriseRootCA.crt /etc/pki/ca-trust/source/anchors/
    RUN /usr/bin/update-ca-trust
    

Avoid unexpected behavior when images change

When your application is restarted or scaled out, the latest image will always be pulled. If the image has been changed, the newly started application instances will use the new image while the old instances will continue to use the old image.

Note

Avoid using the latest tag or overwrite the image without a tag change to avoid unexpected application behavior.

Avoid not being able to connect to the container registry in a VNet

If you deployed the instance to a VNet, make sure you allow the network traffic to your container registry in the NSG or Azure Firewall (if used). For more information, see Customer responsibilities for running in VNet to add the needed security rules.

Install an APM into the image manually

The installation steps vary on different application performance monitors (APMs) and languages. The following steps are for New Relic with Java applications. You must modify the Dockerfile using the following steps:

  1. Download and install the agent file into the image by adding the following to the Dockerfile:

    ADD newrelic-agent.jar /opt/agents/newrelic/java/newrelic-agent.jar
    
  2. Add the environment variables required by the APM:

    ENV NEW_RELIC_APP_NAME=appName
    ENV NEW_RELIC_LICENSE_KEY=newRelicLicenseKey
    
  3. Modify the image entry point by adding: java -javaagent:/opt/agents/newrelic/java/newrelic-agent.jar

To install the agents for other languages, refer to the official documentation for the other agents:

New Relic:

Dynatrace:

AppDynamics:

View the container logs

To view the console logs of your container application, the following CLI command can be used:

az spring app logs \
    --resource-group <your-resource-group> \
    --name <your-app-name> \
    --service <your-service-name> \
    --instance <your-instance-name>

To view the container events logs from the Azure Monitor, enter the query:

AppPlatformContainerEventLogs
| where App == "hw-20220317-1b"

Screenshot of the Azure Monitor that shows the container events log.

Scan your image for vulnerabilities

We recommend that you use Microsoft Defender for Cloud with ACR to prevent your images from being vulnerable. For more information, see Microsoft Defender for Cloud

Switch between JAR deployment and container deployment

You can switch the deployment type from JAR deployment to container deployment directly by redeploying using the following command:

az spring app deploy \
    --resource-group <your-resource-group> \
    --name <your-app-name> \
    --container-image <your-container-image> \
    --service <your-service-name>

Or reversely:

az spring app deploy \
    --resource-group <your-resource-group> \
    --name <your-app-name> \
    --artifact-path <your-jar-file> \
    --service <your-service-name>

Create another deployment with an existing JAR deployment

You can create another deployment using an existing JAR deployment using the following command:

az spring app deployment create \
    --resource-group <your-resource-group> \
    --name <your-deployment-name> \
    --app <your-app-name> \
    --container-image <your-container-image> \
    --service <your-service-name>

CI/CD

Automating deployments using Azure Pipelines Tasks or GitHub Actions are supported now. For more information, see Automate application deployments to Azure Spring Apps and Use Azure Spring Apps CI/CD with GitHub Actions

Next steps