Skip to content

Commit 5971835

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

File tree

6 files changed

+150
-1
lines changed

6 files changed

+150
-1
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: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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/healthcheck.sh ./healthcheck.sh
44+
45+
# Add system user
46+
RUN addgroup -S spring && \
47+
adduser -S -G spring spring
48+
49+
USER spring
50+
51+
EXPOSE 9000
52+
EXPOSE 9001
53+
54+
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
55+
CMD ["./healthcheck.sh"]
56+
57+
ENTRYPOINT ["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: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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+
- SERVER_PORT=9000
16+
restart: unless-stopped

scripts/healthcheck.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/sh
2+
set -e
3+
4+
# Minimal curl-based health check with timeout and error reporting
5+
curl --fail --silent --show-error --connect-timeout 1 --max-time 2 http://localhost:9000/health

0 commit comments

Comments
 (0)