The way we do it is we have 3 pieces (or artifacts) for every running application.
- The application we are developing. This is the same regardless of environment. To match your example, that will be the Spring application as a jar/war.
- The container that will run the application. This is the same regardless of environment. If using Spring Boot, you don't need Tomcat anymore and just the Java runtime. So use the openjdk Docker container.
- The configuration that the application needs. This is the only thing that is different across environments. In a Spring app, you'll likely be using a properties file.
The configuration file lives in a separate source control. This used to be Git, but we are now using a SaaS we built called Config, at http://www.configapp.com. Config's core feature is the easy handling of environment specific configuration. To run our application on a new server, we pull the Docker container, the application artifact, and the configuration file for that environment. In the container, we mount the directory where the application and the configuration file is stored, as part of the container run. Our application is the same. Our container/image is the same. Only the configuration file is different.
Regarding configuration file vs environment variables. For the longest time we were using configuration files. When we used PaaS/cloud, we used environment variables. It was extra work if you have a lot of configuration so we ended up using environment variables to determine the correct configuration file. We have one application that turned properties to environment variables, but that's atypical. If we have a company sanctioned centralized configuration server, we use that, otherwise we like the simplicity of configuration files.
So to summarize, we pull app.jar, app.properties, openjdk Docker. Then we run openjdk Docker mounting the location of app.jar and app.properties. The only thing environment specific is app.properties. To easily manage app.properties, regardless of how many property keys, environments, cluster/region instances, we use Config.