Back to Articles
Spring Boot Application to Docker Container: Containerizing and Deploying a Java Application on AWS
Spring BootAwsDatabaseJavaDockerDocker-ComposeEc2

Spring Boot Application to Docker Container: Containerizing and Deploying a Java Application on AWS

Containerizing a Spring Boot application makes it easier to package, run, test, and deploy the same application consistently across development, staging, and production environments.

This guide walks through the complete journey:

Published at Medium.saiifbaba.co.

Spring Boot Application
        |
        v
Build JAR
        |
        v
Create Docker Image
        |
        v
Run Docker Container
        |
        v
Push Image to Registry
        |
        v
Deploy on AWS
        |
        v
Production Application

The examples use Java, Spring Boot, Docker, and AWS. The same concepts can be applied to Spring Boot microservices and larger distributed systems.


1. Why Containerize a Spring Boot Application?

A traditional deployment might look like:

Developer Machine
    |
    +--> Install Java
    +--> Install Maven
    +--> Configure Environment
    +--> Copy JAR
    +--> Configure Server
    +--> Start Application

This can create environment-specific problems.

With Docker:

Docker Image
    |
    +--> Application
    +--> Java Runtime
    +--> Required Files
    +--> Runtime Configuration

The application runs inside an isolated container with a predictable runtime environment.

Benefits include:

  • Consistent environments
  • Easier deployments
  • Portable application packaging
  • Faster environment setup
  • Simplified CI/CD
  • Better isolation
  • Easier horizontal scaling
  • Reproducible builds
  • Straightforward rollback to a previous image version

2. What Is a Docker Image?

A Docker image is an immutable package containing everything required to create a container.

For a Spring Boot application:

Spring Boot Docker Image
├── Java Runtime
├── Application JAR
├── Application configuration
└── Runtime metadata

A container is a running instance of that image.

Docker Image
      |
      +---- Container 1
      |
      +---- Container 2
      |
      +---- Container 3

The image is the artifact. The container is the running process created from that artifact.


3. Dockerfile

A Dockerfile describes how the application image should be built.

A simple production-oriented Dockerfile is:

FROM eclipse-temurin:21-jre

WORKDIR /app

COPY target/application.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "app.jar"]

The instructions mean:

FROM
  -> Select a base image

WORKDIR
  -> Set the working directory

COPY
  -> Copy the application JAR

EXPOSE
  -> Document the application's listening port

ENTRYPOINT
  -> Define the container startup command

4. Build the Spring Boot Application

For Maven:

./mvnw clean package

On Windows:

mvnw.cmd clean package

This typically creates:

target/
└── application.jar

The JAR is the deployable Spring Boot artifact.

You can test it without Docker:

java -jar target/application.jar

If the application starts successfully, you can move on to containerization.


5. Create the Dockerfile

Place the Dockerfile at the root of the project:

my-spring-app/
├── src/
├── pom.xml
├── mvnw
├── mvnw.cmd
└── Dockerfile

Example:

FROM eclipse-temurin:21-jre

WORKDIR /app

COPY target/*.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "app.jar"]

Using a JRE-oriented runtime image can reduce the final image compared with using a full JDK image, depending on the base image and application requirements.


6. Build the Docker Image

After building the JAR:

docker build -t springboot-app:1.0 .

Docker reads the Dockerfile and creates an image.

Check the image:

docker images

You should see something similar to:

REPOSITORY      TAG       IMAGE ID
springboot-app  1.0       abc123

7. Run the Docker Container

Start the application:

docker run -d \
  --name springboot-container \
  -p 8080:8080 \
  springboot-app:1.0

The mapping:

Host Port 8080
      |
      v
Container Port 8080

Now the application can be accessed through:

http://localhost:8080

8. Verify the Container

List running containers:

docker ps

View application logs:

docker logs springboot-container

Follow logs:

docker logs -f springboot-container

Open a shell inside the container when supported by the image:

docker exec -it springboot-container sh

Stop the container:

docker stop springboot-container

Remove it:

docker rm springboot-container

9. Docker Port Mapping

The following command:

docker run -p 8080:8080 springboot-app:1.0

means:

Host                 Container
------------------   ----------------
localhost:8080  ---> application:8080

The first port is the host port.

The second port is the container port.

You can therefore expose the container on another host port:

docker run -p 9090:8080 springboot-app:1.0

Now:

localhost:9090
      |
      v
container:8080

10. Make Spring Boot Listen on the Correct Interface

Inside a container, the application should normally listen on all interfaces rather than only localhost.

For example:

server.address=0.0.0.0
server.port=8080

In many Spring Boot deployments, binding to the default address works appropriately, but explicitly configuring the address can make the container networking intent clear.

If the application only listens on:

127.0.0.1

external access to the container may fail even when Docker port mapping is configured correctly.


11. Use Environment Variables for Configuration

Do not hard-code environment-specific configuration into the Docker image.

Avoid:

spring.datasource.url=jdbc:mysql://production-db:3306/app
spring.datasource.username=admin
spring.datasource.password=super-secret

Prefer environment variables:

spring.datasource.url=${DB_URL}
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}

Then provide them when starting the container:

docker run -d \
  -p 8080:8080 \
  -e DB_URL="jdbc:mysql://database:3306/app" \
  -e DB_USERNAME="app_user" \
  -e DB_PASSWORD="secret" \
  springboot-app:1.0

For production, sensitive secrets should be managed through a dedicated secret-management mechanism rather than exposed casually in shell history or deployment files.


12. Externalize Application Configuration

A container image should ideally remain environment-independent.

Think:

Same Image
   |
   +--> Development Configuration
   |
   +--> Staging Configuration
   |
   +--> Production Configuration

The image should not need to be rebuilt simply because the database endpoint changed.

Spring Boot supports external configuration through:

  • Environment variables
  • Command-line arguments
  • Configuration files
  • Profiles
  • Secret/configuration systems

This allows the same application artifact to move through environments.


13. Spring Profiles with Docker

You can activate a Spring profile through an environment variable:

docker run -e SPRING_PROFILES_ACTIVE=prod springboot-app:1.0

Or:

spring.profiles.active=${SPRING_PROFILES_ACTIVE:default}

A common setup is:

application.yml
application-dev.yml
application-test.yml
application-prod.yml

Keep secrets out of source-controlled configuration files.


14. Create a .dockerignore

A .dockerignore prevents unnecessary files from being sent to the Docker build context.

Example:

.git
.gitignore
.idea
.vscode
*.log
node_modules
README.md
Dockerfile*
docker-compose*.yml

Depending on your build strategy, you may also exclude generated artifacts if the Dockerfile builds the application itself.

The correct .dockerignore depends on how your Docker build is designed.


15. Multi-Stage Docker Builds

Instead of building the JAR outside Docker, Docker can perform the build in one stage and run it in a smaller runtime stage.

Example:

FROM eclipse-temurin:21-jdk AS build

WORKDIR /workspace

COPY . .

RUN ./mvnw clean package -DskipTests

FROM eclipse-temurin:21-jre

WORKDIR /app

COPY --from=build /workspace/target/*.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "app.jar"]

Conceptually:

Build Stage
    |
    +--> Source Code
    +--> Maven
    +--> JDK
    |
    +--> application.jar
              |
              v
Runtime Stage
    |
    +--> JRE
    +--> application.jar

The final image does not need to contain the complete source tree or build toolchain.


16. Layered Spring Boot JARs

Spring Boot can create layered JARs that allow Docker image layers to be reused more effectively.

The basic idea is to separate relatively stable dependencies from frequently changing application code.

Conceptually:

Docker Layers
├── Dependencies
├── Spring Boot Loader
├── Snapshot Dependencies
└── Application Code

If only application code changes, Docker can potentially reuse unchanged dependency layers.

This can improve build and deployment efficiency.


17. Container Security

A production container should avoid unnecessary privileges.

One useful practice is running the application as a non-root user.

Example:

FROM eclipse-temurin:21-jre

WORKDIR /app

RUN useradd --system --create-home spring

COPY target/*.jar app.jar

USER spring

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "app.jar"]

The exact user-management commands depend on the base image.

Other security practices include:

  • Use trusted base images.
  • Keep base images updated.
  • Minimize installed packages.
  • Scan images for vulnerabilities.
  • Avoid embedding secrets.
  • Run as non-root where practical.
  • Use read-only filesystems where compatible.
  • Limit Linux capabilities where appropriate.
  • Pin image versions deliberately for reproducibility.

18. Health Checks

A production deployment should know whether the application is actually healthy.

Spring Boot Actuator can expose health information.

For example:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Configuration might include:

management.endpoints.web.exposure.include=health

A health endpoint can then be used by infrastructure to determine whether the application is ready to receive traffic.

For example:

/actuator/health

A container being "running" does not necessarily mean the application is ready.


19. Liveness vs Readiness

These concepts are especially important in container orchestration.

Liveness

Answers:

Is the application process alive?

If liveness fails repeatedly, the orchestrator may restart the container.

Readiness

Answers:

Is the application ready to receive traffic?

A service may be alive but not ready because it is still:

  • Starting
  • Connecting to dependencies
  • Initializing resources
  • Recovering from a temporary condition

Separating liveness and readiness improves deployment behavior.


20. Docker Compose for Local Development

For applications with dependencies such as MySQL and Redis, Docker Compose can simplify local development.

Example:

services:

  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      DB_URL: jdbc:mysql://mysql:3306/app
      DB_USERNAME: app
      DB_PASSWORD: password
    depends_on:
      - mysql

  mysql:
    image: mysql:8
    environment:
      MYSQL_DATABASE: app
      MYSQL_USER: app
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: rootpassword
    ports:
      - "3306:3306"

Start:

docker compose up -d

Stop:

docker compose down

Docker Compose is excellent for local multi-container environments, although production deployments often use managed services or orchestration platforms.


Deploying the Dockerized Spring Boot Application on AWS

21. AWS Deployment Architecture

A simple AWS container architecture can look like:

Developer
    |
    v
Git Repository
    |
    v
CI/CD Pipeline
    |
    v
Container Registry
    |
    v
AWS Compute
    |
    +--> Application Container
    |
    +--> Load Balancer
    |
    +--> Database

AWS offers several ways to run containers.

Common choices include:

  • Amazon ECS
  • Amazon EKS
  • AWS App Runner
  • EC2 with Docker
  • AWS Fargate as a serverless compute option for ECS tasks

The right choice depends on operational requirements, scale, team expertise, and architecture.


22. Why Use Amazon ECR?

Amazon Elastic Container Registry (ECR) is a managed container image registry.

The deployment flow becomes:

Local Machine / CI
       |
       v
docker build
       |
       v
Docker Image
       |
       v
Amazon ECR
       |
       v
AWS Compute Service

Instead of transferring Docker images directly between machines, the deployment platform pulls a versioned image from the registry.


23. Create an ECR Repository

Create a repository using the AWS CLI:

aws ecr create-repository \
  --repository-name springboot-app

The repository stores your Docker images.

A good production convention is to use meaningful image names and immutable version tags.


24. Authenticate Docker with ECR

A typical login flow is:

aws ecr get-login-password --region <region> \
  | docker login \
  --username AWS \
  --password-stdin <account-id>.dkr.ecr.<region>.amazonaws.com

Authentication allows Docker to push images to the ECR repository.


25. Tag the Docker Image

Suppose the local image is:

springboot-app:1.0

Tag it for ECR:

docker tag springboot-app:1.0 \
  <account-id>.dkr.ecr.<region>.amazonaws.com/springboot-app:1.0

Now the image has a registry-qualified name.


26. Push the Image to ECR

docker push \
  <account-id>.dkr.ecr.<region>.amazonaws.com/springboot-app:1.0

The deployment pipeline now has a portable artifact:

ECR
└── springboot-app
    └── 1.0

For production, unique version tags such as a Git commit SHA are often safer than repeatedly moving a generic latest tag.

Example:

springboot-app:8f31c2a

This makes rollbacks much easier.


Deploying with Amazon ECS and Fargate

27. What Is ECS?

Amazon Elastic Container Service (ECS) is AWS's managed container orchestration service.

A simplified ECS architecture is:

ECS Cluster
    |
    +--> Service
          |
          +--> Task
                |
                +--> Container

ECS manages desired container instances/tasks according to your service configuration.


28. What Is Fargate?

AWS Fargate provides serverless compute for containers.

With Fargate, you specify the resources your task needs rather than managing the underlying servers yourself.

Conceptually:

ECS Service
    |
    v
Fargate Task
    |
    v
Spring Boot Container

This reduces the amount of infrastructure management required compared with running Docker directly on EC2.


29. ECS Task Definition

A task definition describes how your container should run.

Conceptual example:

{
  "family": "springboot-app",
  "containerDefinitions": [
    {
      "name": "springboot-app",
      "image": "<account>.dkr.ecr.<region>.amazonaws.com/springboot-app:1.0",
      "portMappings": [
        {
          "containerPort": 8080,
          "protocol": "tcp"
        }
      ],
      "essential": true
    }
  ]
}

A real production task definition will generally include additional settings such as:

  • CPU
  • Memory
  • IAM roles
  • Logging
  • Environment variables
  • Secrets
  • Health checks
  • Networking configuration
  • Resource limits

30. ECS Service

An ECS service maintains a desired number of running tasks.

For example:

Desired Count = 3

ECS Service
   |
   +--> Task 1
   +--> Task 2
   +--> Task 3

If a task stops unexpectedly, ECS can start another task to maintain the desired count.

This gives you a basic foundation for high availability and horizontal scaling.


31. Load Balancing

A production application normally should not expose every task directly to the internet.

A common architecture is:

Internet
   |
   v
Application Load Balancer
   |
   +--------+--------+
   |        |        |
   v        v        v
Task 1    Task 2    Task 3

The load balancer distributes incoming requests across healthy application tasks.

It can also perform health checks and remove unhealthy targets from service.


32. AWS Networking

A typical production architecture uses a VPC:

VPC
 |
 +--> Public Subnets
 |      |
 |      +--> Load Balancer
 |
 +--> Private Subnets
        |
        +--> Application Tasks
        |
        +--> Database

A common security model is:

Internet
   |
   v
Load Balancer
   |
   v
Application
   |
   v
Database

The database should generally not be directly accessible from the public internet.

Security groups should allow only the required traffic between components.


33. Database Connectivity

If the Spring Boot application uses a managed database such as Amazon RDS, configure the database connection through environment variables or a secret-management system.

For example:

spring.datasource.url=${DB_URL}
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}

Architecture:

Spring Boot Container
       |
       v
Private Network
       |
       v
RDS

The application container and database should be configured so that only the necessary network traffic is allowed.


34. Secrets Management

Do not place production credentials directly inside:

ENV DB_PASSWORD=super-secret

and do not commit credentials to Git.

Instead, use an appropriate secret-management service such as AWS Secrets Manager or AWS Systems Manager Parameter Store, together with IAM permissions.

Conceptually:

ECS Task
   |
   v
IAM Role
   |
   v
Secret Store
   |
   v
Database Credentials

This keeps secrets outside the Docker image.


35. Logging

Containers should generally write application logs to standard output and standard error.

For example:

System.out
System.err

or through a logging framework configured for console output.

AWS container services can then route logs to a centralized logging service such as Amazon CloudWatch Logs.

Conceptually:

Spring Boot
    |
    v
Container stdout
    |
    v
CloudWatch Logs

Centralized logging is critical for debugging distributed applications.


36. Graceful Shutdown

Container orchestration platforms may stop tasks during:

  • Deployments
  • Scaling
  • Failures
  • Infrastructure changes

The application should shut down gracefully.

Spring Boot supports graceful shutdown configuration, for example:

server.shutdown=graceful

The goal is to allow in-flight requests to finish where possible rather than abruptly terminating active work.

This becomes especially important when running multiple replicas behind a load balancer.


37. Health Checks in ECS

The container or load balancer can use a health endpoint such as:

/actuator/health

Conceptually:

Load Balancer
      |
      | health check
      v
GET /actuator/health
      |
      +---- UP ------> Receive traffic
      |
      +---- DOWN ----> Remove from rotation

A health check should represent actual readiness for the traffic the service is expected to handle.


38. Scaling

Suppose traffic increases:

Normal Traffic
    |
    v
2 Tasks

During a traffic spike:

High Traffic
    |
    v
5 Tasks

ECS can be configured to scale task count based on metrics such as:

  • CPU utilization
  • Memory utilization
  • Request-related metrics
  • Custom CloudWatch metrics

Horizontal scaling is one of the major advantages of containerized services.


39. Deployment Strategy

A safe production deployment should avoid replacing every healthy instance at exactly the same moment.

A common deployment flow is:

Version 1
Task 1   Task 2   Task 3
   |
   v
Deploy Version 2
   |
   +--> Start new task
   +--> Health check
   +--> Shift traffic
   +--> Replace old task

This reduces downtime and provides a path toward safer rolling deployments.


40. Immutable Image Versions

Instead of:

springboot-app:latest

prefer immutable version identifiers:

springboot-app:1.0.0
springboot-app:1.0.1
springboot-app:8f31c2a

Deployment:

Production
    |
    v
Image 8f31c2a

If something goes wrong:

Production
    |
    v
Image 7bd12ef

Rollback becomes a matter of selecting a known-good image version.


41. CI/CD Pipeline

A production deployment can be automated:

Developer Push
      |
      v
Git Repository
      |
      v
Run Tests
      |
      v
Build Spring Boot JAR
      |
      v
Build Docker Image
      |
      v
Security Scan
      |
      v
Push Image to ECR
      |
      v
Deploy ECS Service
      |
      v
Health Checks
      |
      v
Production

Possible AWS-native or third-party components can automate these steps.

The exact CI/CD platform can vary; the core principle is that the Docker image becomes the deployable artifact.


42. Example CI/CD Commands

A simplified pipeline might execute:

./mvnw clean verify

Then:

docker build -t springboot-app:$GIT_COMMIT .

Then:

docker tag springboot-app:$GIT_COMMIT \
  $ECR_REPOSITORY:$GIT_COMMIT

Then:

docker push $ECR_REPOSITORY:$GIT_COMMIT

Finally, update the ECS service/task definition to use the new image.

The exact commands depend on the CI/CD platform and AWS deployment configuration.


43. Docker Image Optimization

A smaller image can improve:

  • Pull time
  • Deployment time
  • Storage usage
  • Startup overhead
  • Security surface area

Useful techniques include:

Use a suitable runtime image

FROM eclipse-temurin:21-jre

instead of unnecessarily shipping a full build environment.

Use multi-stage builds

Build tools stay in the build stage.

Avoid unnecessary files

Use .dockerignore.

Keep dependencies controlled

Remove unused libraries from the application.

Consider layered JARs

They can improve layer reuse.


44. JVM Configuration in Containers

Java applications run inside resource-limited containers.

Make sure the JVM is configured appropriately for containerized environments.

For example, modern JVMs can use container resource limits to make memory decisions, but application-specific tuning may still be necessary.

Avoid blindly assigning a huge heap:

-Xmx8g

to a container with only a few gigabytes of memory.

The container's CPU and memory limits should be considered together with:

  • Heap
  • Metaspace
  • Native memory
  • Thread stacks
  • Direct buffers
  • Application overhead

A container can be killed by the operating system if it exceeds its memory limit.


45. Graceful Error Handling

A production Spring Boot service should distinguish between:

4xx -> Client/request problems
5xx -> Server-side failures

Use centralized exception handling where appropriate:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<?> handleNotFound(
            ResourceNotFoundException ex) {

        return ResponseEntity
                .status(HttpStatus.NOT_FOUND)
                .body(ex.getMessage());
    }
}

This is not Docker-specific, but it becomes especially important when the application is running behind load balancers and multiple containers.


46. Container Observability

Production container deployments should provide visibility into:

Logs
Metrics
Traces
Health

Useful metrics include:

  • Request count
  • Error rate
  • Latency
  • CPU
  • Memory
  • JVM heap usage
  • Database connection pool usage
  • Thread pool utilization

For a microservice architecture, distributed tracing can help identify where latency or failures originate.


47. Common Deployment Problems

Problem 1: Application works locally but not in Docker

Check:

server.address
Port mapping
Environment variables
Database hostname
Container logs

Remember that:

localhost

inside a container refers to the container itself, not your host machine or another container.


Problem 2: Database connection fails

Do not use:

localhost

as the database hostname unless the database is actually inside the same container.

Use the appropriate service name, private DNS name, or managed database endpoint.


Problem 3: Container exits immediately

Check:

docker ps -a
docker logs <container>

Common causes include:

  • Application startup exception
  • Missing environment variable
  • Invalid configuration
  • Database connection failure
  • Incorrect JAR path
  • Incorrect Java command

Problem 4: Port is not reachable

Verify:

docker ps

and confirm:

Host Port -> Container Port

Also verify:

  • Application is listening on the expected interface
  • AWS security groups allow required traffic
  • Load balancer target configuration is correct
  • Network ACL/VPC configuration is not blocking traffic

48. Common Docker Mistakes

Mistake 1: Storing secrets in the image

Avoid:

ENV PASSWORD=secret

Mistake 2: Using latest everywhere

It makes deployments and rollbacks harder to audit.

Mistake 3: Running everything as root

Use a non-root user where practical.

Mistake 4: Shipping unnecessary build tools

Use multi-stage builds.

Mistake 5: Ignoring health checks

A running process is not necessarily a healthy application.

Mistake 6: Treating containers like virtual machines

A container should generally run a focused application process rather than becoming an unmanaged server environment.

Mistake 7: Putting configuration inside the image

Keep environment-specific configuration external.


49. End-to-End Deployment Flow

The complete process can be summarized as:

1. Develop Spring Boot Application
              |
              v
2. Run Unit/Integration Tests
              |
              v
3. Build JAR
              |
              v
4. Create Docker Image
              |
              v
5. Run Container Locally
              |
              v
6. Verify Health Endpoint
              |
              v
7. Authenticate with AWS ECR
              |
              v
8. Tag Image
              |
              v
9. Push Image to ECR
              |
              v
10. Update ECS Task Definition
              |
              v
11. Deploy ECS Service
              |
              v
12. Load Balancer Health Check
              |
              v
13. Application Receives Traffic

50. Production Architecture

A more complete AWS architecture can look like:

                         Internet
                            |
                            v
                    Application Load
                       Balancer
                            |
             +--------------+--------------+
             |              |              |
             v              v              v
         ECS Task       ECS Task       ECS Task
             |              |              |
             +--------------+--------------+
                            |
                            v
                     Spring Boot App
                            |
             +--------------+--------------+
             |                             |
             v                             v
          Redis                           RDS
             |
             v
       Cache / Sessions

The exact architecture depends on the application.

For a microservices system, each service may have its own container image and independent deployment lifecycle.


51. Spring Boot Microservices + Docker

For a microservice architecture:

                   API Gateway
                       |
        +--------------+--------------+
        |              |              |
        v              v              v
   User Service   Order Service   Payment Service
        |              |              |
      MySQL          MySQL          MySQL

Each service can have its own Docker image:

user-service:1.2.0
order-service:3.1.0
payment-service:2.4.0

This allows teams to deploy and scale services independently.

Containerization therefore fits naturally with microservice architectures.


52. Docker vs Virtual Machines

A simplified comparison:

Virtual Machine
+--------------------------+
| Application              |
| Libraries                |
| Guest OS                 |
| Hypervisor               |
+--------------------------+

Container:

Container
+--------------------------+
| Application              |
| Libraries                |
| Container Runtime        |
+--------------------------+
        |
        v
Host OS Kernel

Containers generally share the host kernel, which can make them more lightweight than full virtual machines.

Containers are not a replacement for every VM use case, but they are highly useful for application packaging and deployment.


53. Security Checklist

Before production deployment, verify:

[ ] No secrets committed to Git
[ ] No secrets baked into Docker image
[ ] Non-root container where practical
[ ] Base image is trusted and maintained
[ ] Image vulnerabilities scanned
[ ] IAM permissions follow least privilege
[ ] Database is not publicly exposed unnecessarily
[ ] Security groups are restrictive
[ ] HTTPS/TLS configured
[ ] Health checks configured
[ ] Logs centralized
[ ] Metrics monitored
[ ] Image versions are traceable
[ ] Rollback procedure tested
[ ] Container resource limits configured

54. Deployment Checklist

Application

[ ] Spring Boot application starts successfully
[ ] Tests pass
[ ] Health endpoint works
[ ] Configuration is externalized
[ ] Graceful shutdown configured

Docker

[ ] Dockerfile created
[ ] .dockerignore created
[ ] Image builds successfully
[ ] Container starts successfully
[ ] Port mapping verified
[ ] Image scanned

AWS

[ ] ECR repository created
[ ] IAM permissions configured
[ ] Image pushed to ECR
[ ] ECS cluster configured
[ ] Task definition configured
[ ] ECS service configured
[ ] Load balancer configured
[ ] Health checks configured
[ ] Security groups configured
[ ] Logs configured
[ ] Scaling configured

55. Practical Command Summary

Build Spring Boot

./mvnw clean package

Build Docker Image

docker build -t springboot-app:1.0 .

Run Container

docker run -d \
  --name springboot-container \
  -p 8080:8080 \
  springboot-app:1.0

View Containers

docker ps

View Logs

docker logs -f springboot-container

Stop Container

docker stop springboot-container

Remove Container

docker rm springboot-container

Tag Image

docker tag springboot-app:1.0 \
  <account-id>.dkr.ecr.<region>.amazonaws.com/springboot-app:1.0

Push Image

docker push \
  <account-id>.dkr.ecr.<region>.amazonaws.com/springboot-app:1.0

56. Final Takeaway

Containerizing a Spring Boot application is more than putting a JAR inside a Docker image.

A production-ready deployment should consider the entire lifecycle:

Code
  |
  v
Test
  |
  v
Build
  |
  v
Containerize
  |
  v
Scan
  |
  v
Registry
  |
  v
Deploy
  |
  v
Health Check
  |
  v
Observe
  |
  v
Scale
  |
  v
Rollback

The key principle is to make the Docker image a reproducible, versioned deployment artifact while keeping environment-specific configuration and secrets outside the image.

For AWS deployments, services such as ECR, ECS/Fargate, load balancers, CloudWatch, IAM, and managed databases can be combined to create a scalable production environment.

Once this workflow is understood, moving a Spring Boot application from a developer machine to a production AWS container platform becomes a structured engineering process rather than a collection of manual deployment steps.

Design & Developed by Saif Baba MS
© 2026. All rights reserved.