An application I’m working on uses Spring Boot 2 and produces a fat executable JAR that run with an embedded Tomcat server. I needed to deploy it to an AWS beanstalk environment using Corretto running on Amazon Linux 2. I also needed to customize the config for Nginx, the reverse proxy used by beanstalk.
It turns out this process wasn’t that simple. To hopefully spare some people struggling with this more pain, let’s go through the steps you need to take.
Deployment structure
To make things clearer, let’s first take a look at the end result we want to achieve. To make things work you want to upload a ZIP file that has the following contents:
coderdreams-app.zip
|-- coderdreams-1.0.jar
|-- Procfile
`-- .platform/
`-- nginx/
|-- nginx.conf
`-- conf.d/
`-- nginx_custom.conf
- coderdreams-1.0.jar is the fat JAR produced by running Maven package.
- Procfile can be a simple command that tells beanstalk which JAR file to execute.
- nginx_custom.conf – custom config for NGINX. Must follow this exact folder structure.
Prepare our Spring Boot app
In the root of your Spring Boot project create a folder called aws which will contain the following:
~/aws/
|-- Procfile
`-- .platform/
`-- nginx/
|-- nginx.conf
`-- conf.d/
`-- nginx_custom.conf
Procfile: (@jarname@ is a placeholder which will be replace with the actual jar file
web: java -jar @jarname@
nginx_custom.conf: (as a simple example)
client_max_body_size 20M;
Maven ant task to the rescue
Now to spare us any manual work each time we build our project, we need to create some Ant tasks to compose the final ZIP file. We will do this in the pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>prepare</id>
<phase>package</phase>
<configuration>
<tasks>
<property name="buildName" value="${project.build.finalName}.jar"/>
<copy todir="${project.build.directory}/aws-build/" overwrite="false">
<fileset file="${project.build.directory}/${project.build.finalName}.jar"/>
<fileset dir="./aws" />
</copy>
<replace file="${project.build.directory}/aws-build/Procfile" token="@jarname@" value="${buildName}"/>
<zip compress="false" destfile="${project.build.directory}/aws-build/app-to-deploy.jar" basedir="${project.build.directory}/aws-build"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
It seems like a lot but is simple if we break it down into steps:
- We store the name of the build JAR file into a variable (Line 11)
- We create a new directory called aws-build in our build folder and copy the final JAR file and the /aws folder into it (Lines 13-16)
- We replace the token in the Procfile with the value from step 1.
- We create the final ZIP file, called app-to-deploy.jar, from the contents of the aws-build folder. (Line 20)
All Done!
Of course the last and final step is to upload app-to-deploy.jar to beanstalk. Enjoy!