Deploy a Spring Boot App to Azure – 将Spring Boot应用程序部署到Azure

最后修改: 2018年 5月 30日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.绪论

Microsoft Azure now features quite solid Java support.

微软Azure现在具有相当坚实的Java支持。

In this tutorial, we’ll demonstrate how to make our Spring Boot application work on the Azure platform, step by step.

在本教程中,我们将一步步演示如何使我们的Spring Boot应用在Azure平台上运行。

2. Maven Dependency and Configuration

2.Maven的依赖性和配置

First, we do need an Azure subscription to make use of the cloud services there; currently, we can sign up a free account here.

首先,我们确实需要一个Azure订阅,以利用那里的云服务;目前,我们可以注册一个免费账户这里

Next, login to the platform and create a service principal using the Azure CLI:

接下来,登录平台并使用Azure CLI创建一个服务委托人。

> az login
To sign in, use a web browser to open the page \
https://microsoft.com/devicelogin and enter the code XXXXXXXX to authenticate.
> az ad sp create-for-rbac --name "app-name" --password "password"
{
    "appId": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
    "displayName": "app-name",
    "name": "http://app-name",
    "password": "password",
    "tenant": "tttttttt-tttt-tttt-tttt-tttttttttttt"
}

Now we configure Azure service principal authentication settings in our Maven settings.xml, with the help of the following section, under <servers>:

现在我们在Maven的settings.xml中配置Azure服务本体认证设置,借助以下部分,在<services>下。

<server>
    <id>azure-auth</id>
    <configuration>
        <client>aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa</client>
        <tenant>tttttttt-tttt-tttt-tttt-tttttttttttt</tenant>
        <key>password</key>
        <environment>AZURE</environment>
    </configuration>
</server>

We’ll rely on the authentication configuration above when uploading our Spring Boot application to the Microsoft platform, using azure-webapp-maven-plugin.

当我们使用azure-webapp-maven-plugin将Spring Boot应用程序上传到微软平台时,我们将依靠上述认证配置。

Let’s add the following Maven plugin to the pom.xml:

让我们在pom.xml中添加以下Maven插件。

<plugin>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-webapp-maven-plugin</artifactId>
    <version>1.1.0</version>
    <configuration>
        <!-- ... -->
    </configuration>
</plugin>

We can check the latest release version here.

我们可以查看最新的发布版本这里

There are a number of configurable properties for this plugin that will be covered in the following introduction.

这个插件有许多可配置的属性,将在下面的介绍中介绍。

3. Deploy a Spring Boot App to Azure

3.将Spring Boot应用程序部署到Azure

Now that we’ve set up the environment, let’s try to deploy our Spring Boot application to Azure.

现在我们已经建立了环境,让我们试着把我们的Spring Boot应用部署到Azure。

Our application replies with “hello azure!” when we access “/hello“:

当我们访问”/hello“时,我们的应用程序回复”hello azure!“。

@GetMapping("/hello")
public String hello() {
    return "hello azure!";
}

The platform now allows Java Web App deployment for both Tomcat and Jetty. With azure-webapp-maven-plugin, we can deploy our application directly to supported web containers as the default(ROOT) application, or deploy via FTP.

该平台现在允许为Tomcat和Jetty部署Java Web App。通过azure-webapp-maven-plugin,我们可以将我们的应用作为默认(ROOT)应用直接部署到支持的Web容器上,或者通过FTP部署。

Note that as we’re going to deploy the application to web containers, we should package it as a WAR archive. As a quick reminder, we’ve got an article introducing how to deploy a Spring Boot WAR into Tomcat.

请注意,由于我们要将应用程序部署到Web容器中,我们应该将其打包成WAR归档文件。作为快速提醒,我们已经有一篇文章介绍了如何将Spring Boot WAR部署到Tomcat中

3.1. Web Container Deployment

3.1.网络容器的部署

We’ll use the following configuration for azure-webapp-maven-plugin if we intend to deploy to Tomcat on a Windows instance:

如果我们打算在Windows实例上部署到Tomcat,我们将对azure-webapp-maven-plugin使用以下配置。

<configuration>
    <javaVersion>1.8</javaVersion>
    <javaWebContainer>tomcat 8.5</javaWebContainer>
    <!-- ... -->
</configuration>

For a Linux instance, try the following configuration:

对于一个Linux实例,尝试以下配置。

<configuration>
    <linuxRuntime>tomcat 8.5-jre8</linuxRuntime>
    <!-- ... -->
</configuration>

Let’s not forget the Azure authentication:

让我们不要忘记Azure认证。

<configuration>
    <authentication>
        <serverId>azure-auth</serverId>
    </authentication>
    <appName>spring-azure</appName>
    <resourceGroup>baeldung</resourceGroup>
    <!-- ... -->
</configuration>

When we deploy our application to Azure, we’ll see it appear as an App Service. So here we specified the property <appName> to name the App Service. Also, the App Service, as a resource, needs to be held by a resource group container, so <resourceGroup> is also required.

当我们把我们的应用程序部署到Azure时,我们会看到它以App Service的形式出现。所以在这里我们指定了<appName>这个属性来命名App Service。此外,App服务作为一种资源,需要由资源组容器持有,因此也需要<resourceGroup>

Now we’re ready to pull the trigger using the azure-webapp:deploy Maven target, and we’ll see the output:

现在我们准备使用azure-webapp:deploy Maven目标扣动扳机,我们将看到输出。

> mvn clean package azure-webapp:deploy
...
[INFO] Start deploying to Web App spring-baeldung...
[INFO] Authenticate with ServerId: azure-auth
[INFO] [Correlation ID: cccccccc-cccc-cccc-cccc-cccccccccccc] \
Instance discovery was successful
[INFO] Target Web App doesn't exist. Creating a new one...
[INFO] Creating App Service Plan 'ServicePlanssssssss-bbbb-0000'...
[INFO] Successfully created App Service Plan.
[INFO] Successfully created Web App.
[INFO] Starting to deploy the war file...
[INFO] Successfully deployed Web App at \
https://spring-baeldung.azurewebsites.net
...

Now we can access https://spring-baeldung.azurewebsites.net/hello and see the response: ‘hello azure!’.

现在我们可以访问https://spring-baeldung.azurewebsites.net/hello并看到响应。’hello azure!’。

During the deployment process, Azure automatically created an App Service Plan for us. Check out the official document for details about Azure App Service plans. If we already have an App Service plan, we can set property <appServicePlanName> to avoid creating a new one:

在部署过程中,Azure自动为我们创建了一个应用服务计划。请查看官方文件,了解有关Azure应用服务计划的详细信息。如果我们已经有了一个应用服务计划,我们可以设置属性<appServicePlanName>以避免创建一个新的计划。

<configuration>
    <!-- ... -->
    <appServicePlanName>ServicePlanssssssss-bbbb-0000</appServicePlanName>
</configuration>

3.2. FTP Deployment

3.2.FTP的部署

To deploy via FTP, we can use the configuration:

要通过FTP进行部署,我们可以使用配置。

<configuration>
    <authentication>
        <serverId>azure-auth</serverId>
    </authentication>
    <appName>spring-baeldung</appName>
    <resourceGroup>baeldung</resourceGroup>
    <javaVersion>1.8</javaVersion>

    <deploymentType>ftp</deploymentType>
    <resources>
        <resource>
            <directory>${project.basedir}/target</directory>
            <targetPath>webapps</targetPath>
            <includes>
                <include>*.war</include>
            </includes>
        </resource>
    </resources>
</configuration>

In the configuration above, we make the plugin locate the WAR file in directory ${project.basedir}/target, and deploy it to Tomcat container’s webapps directory.

在上面的配置中,我们让插件在${project.basedir}/target目录下定位WAR文件,并将其部署到Tomcat容器的webapps目录。

Say our final artifact is named azure-0.1.war, we’ll see output like the following once we commence the deployment:

假设我们最终的工件被命名为azure-0.1.war,一旦我们开始部署,我们将看到如下输出。

> mvn clean package azure-webapp:deploy
...
[INFO] Start deploying to Web App spring-baeldung...
[INFO] Authenticate with ServerId: azure-auth
[INFO] [Correlation ID: cccccccc-cccc-cccc-cccc-cccccccccccc] \
Instance discovery was successful
[INFO] Target Web App doesn't exist. Creating a new one...
[INFO] Creating App Service Plan 'ServicePlanxxxxxxxx-xxxx-xxxx'...
[INFO] Successfully created App Service Plan.
[INFO] Successfully created Web App.
...
[INFO] Finished uploading directory: \
/xxx/.../target/azure-webapps/spring-baeldung --> /site/wwwroot
[INFO] Successfully uploaded files to FTP server: \
xxxx-xxxx-xxx-xxx.ftp.azurewebsites.windows.net
[INFO] Successfully deployed Web App at \
https://spring-baeldung.azurewebsites.net

Note that here we didn’t deploy our application as the default Web App for Tomcat, so we can only access it through ‘https://spring-baeldung.azurewebsites.net/azure-0.1/hello’. The server will respond ‘hello azure!’ as expected.

注意,这里我们没有把我们的应用程序部署为Tomcat的默认Web应用程序,所以我们只能通过’https://spring-baeldung.azurewebsites.net/azure-0.1/hello’来访问它。服务器会像预期的那样回应’hello azure!’。

4. Deploy with Custom Application Settings

4.使用自定义应用程序设置进行部署

Most of the time, our Spring Boot application requires data access to provide services. Azure now supports databases such as SQL Server, MySQL, and PostgreSQL.

大多数时候,我们的Spring Boot应用需要数据访问来提供服务。Azure现在支持SQL Server、MySQL和PostgreSQL等数据库。

For the sake of simplicity, we’ll use its In-App MySQL as our data source, as its configuration is quite similar to other Azure database services.

为了简单起见,我们将使用其应用程序内的MySQL作为我们的数据源,因为其配置与其他Azure数据库服务非常相似。

4.1. Enable In-App MySQL on Azure

4.1 在Azure上启用应用内MySQL

Since there isn’t a one-liner to create a web app with In-App MySQL enabled, we have to first create the web app using the CLI:

由于没有一个单行程序来创建一个启用了应用内MySQL的网络应用,我们必须首先使用CLI创建网络应用。

az group create --location japanwest --name bealdung-group
az appservice plan create --name baeldung-plan --resource-group bealdung-group --sku B1
az webapp create --name baeldung-webapp --resource-group baeldung-group \
  --plan baeldung-plan --runtime java|1.8|Tomcat|8.5

Then enable MySQL in App in the portal:

然后门户的应用程序中启用MySQL。

azure1

After the In-App MySQL is enabled, we can find the default database, data source URL, and default account information in a file named MYSQLCONNSTR_xxx.txt under the /home/data/mysql directory of the filesystem.

启用应用内MySQL后,我们可以在文件系统的/home/data/mysql目录下一个名为MYSQLCONNSTR_xxx.txt的文件中找到默认数据库、数据源URL和默认账户信息。

4.2. Spring Boot Application Using Azure In-App MySQL

4.2.使用Azure应用内MySQL的Spring Boot应用

Here, for demonstration needs, we create a User entity and two endpoints used to register and list Users:

在这里,为了演示的需要,我们创建了一个User实体和两个用于注册列表Users的端点:

@PostMapping("/user")
public String register(@RequestParam String name) {
    userRepository.save(userNamed(name));
    return "registered";
}

@GetMapping("/user")
public Iterable<User> userlist() {
    return userRepository.findAll();
}

We’re going to use an H2 database in our local environment, and switch it to MySQL on Azure. Generally, we configure data source properties in the application.properties file:

我们将在本地环境中使用一个H2数据库,并将其切换到Azure上的MySQL。一般来说,我们在application.properties文件中配置数据源属性。

spring.datasource.url=jdbc:h2:file:~/test
spring.datasource.username=sa
spring.datasource.password=

While for Azure deployment, we need to configure azure-webapp-maven-plugin in <appSettings>:

而对于Azure的部署,我们需要在azure-webapp-maven-plugin中配置<appSettings>

<configuration>
    <authentication>
        <serverId>azure-auth</serverId>
    </authentication>
    <javaVersion>1.8</javaVersion>
    <resourceGroup>baeldung-group</resourceGroup>
    <appName>baeldung-webapp</appName>
    <appServicePlanName>bealdung-plan</appServicePlanName>
    <appSettings>
        <property>
            <name>spring.datasource.url</name>
            <value>jdbc:mysql://127.0.0.1:55738/localdb</value>
        </property>
        <property>
            <name>spring.datasource.username</name>
            <value>uuuuuu</value>
        </property>
        <property>
            <name>spring.datasource.password</name>
            <value>pppppp</value>
        </property>
    </appSettings>
</configuration>

Now we can start to deploy:

现在我们可以开始部署了。

> mvn clean package azure-webapp:deploy
...
[INFO] Start deploying to Web App custom-webapp...
[INFO] Authenticate with ServerId: azure-auth
[INFO] [Correlation ID: cccccccc-cccc-cccc-cccc-cccccccccccc] \
Instance discovery was successful
[INFO] Updating target Web App...
[INFO] Successfully updated Web App.
[INFO] Starting to deploy the war file...
[INFO] Successfully deployed Web App at \
https://baeldung-webapp.azurewebsites.net

We can see from the log that the deployment is finished.

我们可以从日志中看到,部署已经完成。

Let’s test our new endpoints:

让我们测试一下我们的新端点。

> curl -d "" -X POST https://baeldung-webapp.azurewebsites.net/user\?name\=baeldung
registered

> curl https://baeldung-webapp.azurewebsites.net/user
[{"id":1,"name":"baeldung"}]

The server’s response says it all. It works!

服务器的反应说明了一切。它成功了!

5. Deploy a Containerized Spring Boot App to Azure

5.将容器化的Spring Boot应用部署到Azure上

In the previous sections, we’ve shown how to deploy applications to servlet containers (Tomcat in this case). How about deploying as a standalone runnable jar?

在前面的章节中,我们已经展示了如何将应用程序部署到servlet容器(本例中为Tomcat)。那么,作为一个独立的可运行的jar进行部署呢?

For now, we may need to containerize our Spring Boot application. Specifically, we can dockerize it and upload the image to Azure.

目前,我们可能需要将我们的Spring Boot应用程序容器化。具体来说,我们可以对其进行dockerize并将镜像上传到Azure。

We already have an article about how to dockerize a Spring Boot App, but here we’re about to make use of another maven plugin: docker-maven-plugin, to automate dockerization for us:

我们已经有一篇关于如何dockerize Spring Boot App的文章,但在这里我们将利用另一个maven插件。docker-maven-plugin,为我们自动实现dockerization:

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>1.1.0</version>
    <configuration>
        <!-- ... -->
    </configuration>
</plugin>

The latest version can be found here.

最新版本可以在这里找到。

5.1. Azure Container Registry

5.1.Azure容器注册处

First, we need a Container Registry on Azure to upload our docker image.

首先,我们需要在Azure上建立一个容器注册处,以上传我们的docker镜像。

So let’s create one:

因此,让我们创建一个。

az acr create --admin-enabled --resource-group baeldung-group \
  --location japanwest --name baeldungadr --sku Basic

We’ll also need the Container Registry’s authentication information, and this can be queried using:

我们还需要容器注册处的认证信息,这可以用以下方式查询。

> az acr credential show --name baeldungadr --query passwords[0]
{
  "additionalProperties": {},
  "name": "password",
  "value": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

Then add the following server authentication configuration in Maven’s settings.xml:

然后在Maven的settings.xml中添加以下服务器认证配置。

<server>
    <id>baeldungadr</id>
    <username>baeldungadr</username>
    <password>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</password>
</server>

5.2. Maven Plugin Configuration

5.2.Maven插件配置

Let’s add the following Maven plugin configuration to the pom.xml:

让我们在pom.xml中添加以下Maven插件配置。

<properties>
    <!-- ... -->
    <azure.containerRegistry>baeldungadr</azure.containerRegistry>
    <docker.image.prefix>${azure.containerRegistry}.azurecr.io</docker.image.prefix>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>docker-maven-plugin</artifactId>
            <version>1.0.0</version>
            <configuration>
                <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
                <registryUrl>https://${docker.image.prefix}</registryUrl>
                <serverId>${azure.containerRegistry}</serverId>
                <dockerDirectory>docker</dockerDirectory>
                <resources>
                    <resource>
                        <targetPath>/</targetPath>
                        <directory>${project.build.directory}</directory>
                        <include>${project.build.finalName}.jar</include>
                    </resource>
                </resources>
            </configuration>
        </plugin>
        <!-- ... -->
    </plugins>
</build>

In the configuration above, we specified the docker image name, registry URL and some properties similar to that of FTP deployment.

在上面的配置中,我们指定了docker镜像名称、注册表的URL和一些类似于FTP部署的属性。

Note that the plugin will use values in <dockerDirectory> to locate the Dockerfile. We put the Dockerfile in the docker directory, and its content is:

注意,该插件将使用<dockerDirectory>中的值来定位Dockerfile。我们把Dockerfile放在docker目录下,其内容为。

FROM frolvlad/alpine-oraclejdk8:slim
VOLUME /tmp
ADD azure-0.1.jar app.jar
RUN sh -c 'touch /app.jar'
EXPOSE 8080
ENTRYPOINT [ "sh", "-c", "java -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]

5.3. Run Spring Boot App in a Docker Instance

5.3.在Docker实例中运行Spring Boot应用

Now we can build a Docker image and push it to the Azure registry:

现在我们可以建立一个Docker镜像,并将其推送到Azure注册中心。

> mvn docker:build -DpushImage
...
[INFO] Building image baeldungadr.azurecr.io/azure-0.1
...
Successfully built aaaaaaaaaaaa
Successfully tagged baeldungadr.azurecr.io/azure-0.1:latest
[INFO] Built baeldungadr.azurecr.io/azure-0.1
[INFO] Pushing baeldungadr.azurecr.io/azure-0.1
The push refers to repository [baeldungadr.azurecr.io/azure-0.1]
...
latest: digest: sha256:0f0f... size: 1375

After the upload is finished, let’s check the baeldungadr registry. We shall see the image in the repository list:

上传完成后,让我们检查一下baeldungadr注册表。我们将在资源库列表中看到图像。

azure2

Now we are ready to run an instance of the image:

现在我们准备运行一个图像的实例。

azure3

Once the instance is booted, we can access services provided by our application via its public IP address:

一旦实例被启动,我们就可以通过其公共IP地址访问我们的应用程序所提供的服务。

> curl http://a.x.y.z:8080/hello
hello azure!

5.4. Docker Container Deployment

5.4.Docker容器的部署

Suppose we have a container registry, no matter it’s from Azure, Docker Hub, or our private registry.

假设我们有一个容器注册表,不管是来自Azure、Docker Hub,还是我们的私人注册表。

With the help of the following configuration of azure-webapp-maven-plugin, we can also deploy our Spring Boot web app to the containers:

在以下azure-webapp-maven-plugin配置的帮助下,我们也可以将Spring Boot Web应用部署到容器中。

<configuration>
    <containerSettings>
        <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
        <registryUrl>https://${docker.image.prefix}</registryUrl>
        <serverId>${azure.containerRegistry}</serverId>
    </containerSettings>
    <!-- ... -->
</configuration>

Once we run mvn azure-webapp:deploy, the plugin will help deploy our web app archive to an instance of the specified image.

一旦我们运行mvn azure-webapp:deploy,该插件将帮助把我们的web应用存档部署到指定镜像的实例中。

Then we can access web services via the instance’s IP address or Azure App Service’s URL.

然后我们可以通过实例的IP地址或Azure应用服务的URL来访问网络服务。

6. Conclusion

6.结语

In this article, we introduced how to deploy a Spring Boot application to Azure, as a deployable WAR or a runnable JAR in a container. Though we’ve covered most of the features of azure-webapp-maven-plugin, there are some rich features yet to be explored. Please check out here for more details.

在本文中,我们介绍了如何将Spring Boot应用部署到Azure,作为可部署的WAR或容器中可运行的JAR。虽然我们已经介绍了azure-webapp-maven-plugin的大部分功能,但还有一些丰富的功能有待探索。请查看这里了解更多细节。

As always, the full implementation of the code samples can be found over on Github.

一如既往,可以在Github上找到代码样本的完整实现。