Skip to content

Commit b7b6402

Browse files
committed
feat: add multi-stage Dockerfile for building and running app
1 parent c5c6e74 commit b7b6402

File tree

8 files changed

+166
-2
lines changed

8 files changed

+166
-2
lines changed

.dockerignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.github
2+
.mvn
3+
.vscode
4+
target
5+
.codacy.yml
6+
.gitignore
7+
azure-pipelines.yml
8+
CODE_OF_CONDUCT.md
9+
codecov.yml
10+
CONTRIBUTING.md
11+
LICENSE
12+
mvnw
13+
mvnw.cmd

.github/workflows/maven.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,37 @@ jobs:
6666
with:
6767
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
6868
force-coverage-parser: jacoco -r jacoco.xml
69+
70+
container:
71+
needs: coverage
72+
runs-on: ubuntu-latest
73+
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
74+
75+
permissions:
76+
contents: read
77+
packages: write
78+
79+
steps:
80+
- name: Checkout repository
81+
uses: actions/checkout@v4.2.2
82+
83+
- name: Log in to GitHub Container Registry
84+
uses: docker/login-action@v3.4.0
85+
with:
86+
registry: ghcr.io
87+
username: ${{ github.actor }}
88+
password: ${{ secrets.GITHUB_TOKEN }}
89+
90+
- name: Set up Docker Buildx
91+
uses: docker/setup-buildx-action@v3.10.0
92+
93+
- name: Build and push Docker image to GitHub Container Registry
94+
uses: docker/build-push-action@v6.17.0
95+
with:
96+
context: .
97+
push: true
98+
platforms: linux/amd64
99+
provenance: false
100+
tags: |
101+
ghcr.io/${{ github.repository }}:latest
102+
ghcr.io/${{ github.repository }}:sha-${{ github.sha }}

Dockerfile

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# ------------------------------------------------------------------------------
2+
# Stage 1: Builder
3+
# This stage builds the application and its dependencies.
4+
# ------------------------------------------------------------------------------
5+
FROM maven:3.9-eclipse-temurin-21-alpine AS builder
6+
7+
WORKDIR /app
8+
9+
# Copy pom.xml and source code
10+
COPY pom.xml .
11+
COPY src ./src
12+
13+
# Build the application and skip tests for faster build
14+
RUN mvn clean package -DskipTests
15+
16+
# ------------------------------------------------------------------------------
17+
# Stage 2: Runtime
18+
# This stage creates the final, minimal image to run the application.
19+
# ------------------------------------------------------------------------------
20+
FROM eclipse-temurin:21-jdk-alpine AS runtime
21+
22+
WORKDIR /app
23+
24+
# Install curl for health check
25+
RUN apk add --no-cache curl
26+
27+
# Metadata labels for the image. These are useful for registries and inspection.
28+
LABEL org.opencontainers.image.title="🧪 RESTful Web Service with Spring Boot"
29+
LABEL org.opencontainers.image.description="Proof of Concept for a RESTful Web Service made with JDK 21 (LTS) and Spring Boot 3"
30+
LABEL org.opencontainers.image.licenses="MIT"
31+
LABEL org.opencontainers.image.source="https://github.com/nanotaboada/java.samples.spring.boot"
32+
33+
# https://rules.sonarsource.com/docker/RSPEC-6504/
34+
35+
# Copy application JAR file from the builder stage
36+
COPY --from=builder /app/target/*.jar ./app.jar
37+
38+
# Copy metadata docs for container registries (e.g.: GitHub Container Registry)
39+
COPY --chmod=444 README.md ./
40+
COPY --chmod=555 assets/ ./assets/
41+
42+
# Copy entrypoint and healthcheck scripts
43+
COPY --chmod=555 scripts/entrypoint.sh ./entrypoint.sh
44+
COPY --chmod=555 scripts/healthcheck.sh ./healthcheck.sh
45+
46+
# Add system user
47+
RUN addgroup -S spring && \
48+
adduser -S -G spring spring
49+
50+
USER spring
51+
52+
EXPOSE 9000
53+
EXPOSE 9001
54+
55+
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
56+
CMD ["./healthcheck.sh"]
57+
58+
ENTRYPOINT ["./entrypoint.sh"]
59+
CMD ["java", "-jar", "./app.jar"]

README.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Sample RESTful Web Service with Spring Boot
1+
# 🧪 RESTful Web Service with Spring Boot
22

33
## Status
44

@@ -27,6 +27,30 @@ http://localhost:9000/swagger/index.html
2727

2828
![API Documentation](assets/images/swagger.png)
2929

30+
## Container
31+
32+
### Docker Compose
33+
34+
This setup uses [Docker Compose](https://docs.docker.com/compose/) to build and run the app
35+
36+
#### Build the image
37+
38+
```bash
39+
docker compose build
40+
```
41+
42+
#### Start the app
43+
44+
```bash
45+
docker compose up
46+
```
47+
48+
#### Stop the app
49+
50+
```bash
51+
docker compose down
52+
```
53+
3054
## Credits
3155

3256
The solution has been coded using [Visual Studio Code](https://code.visualstudio.com/) with the [Extension Pack for Java](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack)

compose.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: java-samples-spring-boot
2+
3+
services:
4+
api:
5+
image: java-samples-spring-boot
6+
container_name: spring-app
7+
build:
8+
context: .
9+
dockerfile: Dockerfile
10+
ports:
11+
- "9000:9000"
12+
- "9001:9001"
13+
environment:
14+
- SPRING_PROFILES_ACTIVE=production
15+
restart: unless-stopped

scripts/entrypoint.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/sh
2+
set -e
3+
4+
echo "✔ Starting Spring Boot container..."
5+
6+
echo "✔ Server Port: ${SERVER_PORT:-9000}"
7+
echo "✔ Management Port: ${MANAGEMENT_PORT:-9001}"
8+
echo "✔ Active Profile(s): ${SPRING_PROFILES_ACTIVE:-default}"
9+
10+
echo "🚀 Launching Spring Boot app..."
11+
exec "$@"

scripts/healthcheck.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/sh
2+
set -e
3+
4+
# Use Actuator endpoint for health check
5+
ACTUATOR_HEALTH_URL="http://localhost:9001/actuator/health"
6+
7+
# Curl with fail-fast behavior and silent output
8+
curl --fail --silent --show-error --connect-timeout 1 --max-time 2 "$ACTUATOR_HEALTH_URL"

src/main/resources/application.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
server.port: 9000
22
management.server.port: 9001
3-
management.server.address: 127.0.0.1
3+
management.server.address: 0.0.0.0
44
management.endpoints.web.exposure.include=health,info,mappings
55

66
# http://localhost:9001/actuator/health

0 commit comments

Comments
 (0)