Dockerfile
FROM gradle:8.10.0-jdk21-alpine AS build WORKDIR /app COPY . . RUN gradle clean build --no-daemon FROM openjdk:21-jdk-slim WORKDIR /app COPY /app/build/libs/payment-0.0.1-SNAPSHOT.jar app.jar COPY . . ENV SERVER_PORT=8081 EXPOSE 8081 ENTRYPOINT ["java", "-Dspring.profiles.active=uat", "-jar", "app.jar"]
-
port
8081
is used because the container has occupied the port8080
by some process. -
We build the image in two stages, but you can also build the
jar
file in your CI worker node, so this step is not necessary. -
In the second stage we keep using
COPY . .
because we need the stored tokens for sending email by GMail Service, as well as the GCP credential in json format.
Find out the jar Filename
We can run the gradle build command once to verify the exact name of the jar
file:
and the build will be located at:
__cacert_entrypoint.sh: exec format error
-
From ChatGPT:
The error message "__cacertentrypoint.sh: exec format error" typically occurs in Docker when there's a **_mismatch between the architecture** of the system running the container and the architecture for which the executable file was compiled. This often happens when trying to run an image built for one architecture (like ARM64) on a different architecture (like x86_64), or vice versa.
-
Findout the computer processor architecture used by the docker image
docker inspect --format='{{.Architecture}}' <your-image-name>
-
Because I was using macbook air M2 to build the image, the architecture was chosen to be
ARM64
. -
If we build the image in another machine, the architecture can be different, so it can vary by using different CI/CD worker node.
-
Choose a correct one for the deployment target (in ECS we can choose
ARM64
in task definition)
build.gradle.kts
Config Main Class for the Jar file
tasks.getByName<Jar>("jar") { manifest { attributes["Main-Class"] = "com.billie.payment.PaymentApplication Kt" } }
Skip the Test
tasks.named<Test>("test") { enabled = false }
Adjust the Application.kt
@EnableScheduling @SpringBootApplication class PaymentApplication { companion object { @JvmStatic fun main(args: Array<String>) { runApplication<PaymentApplication>(*args) } } @Autowired fun someOtherInitization(someResource: SomeResource) { } }
Weird Healthcheck Failure due to slow Startup Time in ECS, Causing Rollback
Problem
If we keep health-check default config (fired per 5 seconds, 3 consecutive success as healthy, etc), then we will be being led to the following failure
which prevents ECS from rolling-update the service into latest image.
Solution
-
Edit health-check config in our target group:
-
Change the setting as follows: