The Furniture API includes Docker configuration for containerized deployment. This guide covers building and running the application with Docker.
Prerequisites
Ensure you have the following installed:
Docker Engine 20.10 or higher
Docker Compose V2
At least 2GB of available RAM
At least 1GB of available disk space
Docker Configuration
Dockerfile Overview
The application uses a multi-stage Dockerfile optimized for Spring Boot applications:
Dependencies Stage
Downloads Maven dependencies using the Maven wrapper: FROM eclipse-temurin:21-jdk-jammy as deps
WORKDIR /build
COPY --chmod=0755 mvnw mvnw
COPY .mvn/ .mvn/
RUN --mount=type=bind,source=pom.xml,target=pom.xml \
--mount=type=cache,target=/root/.m2 \
./mvnw dependency:go-offline -DskipTests
Build Stage
Compiles the application and creates the JAR file: FROM deps as package
WORKDIR /build
COPY ./src src/
RUN --mount=type=bind,source=pom.xml,target=pom.xml \
--mount=type=cache,target=/root/.m2 \
./mvnw package -DskipTests && \
mv target/*.jar target/app.jar
Extract Stage
Extracts Spring Boot layers for better caching: FROM package as extract
WORKDIR /build
RUN java -Djarmode=layertools -jar target/app.jar extract \
--destination target/extracted
Runtime Stage
Creates minimal runtime image with non-root user: FROM eclipse-temurin:21-jre-jammy AS final
RUN adduser --disabled-password --uid 10001 appuser
USER appuser
COPY --from=extract build/target/extracted/dependencies/ ./
COPY --from=extract build/target/extracted/spring-boot-loader/ ./
COPY --from=extract build/target/extracted/snapshot-dependencies/ ./
COPY --from=extract build/target/extracted/application/ ./
EXPOSE 8082
ENTRYPOINT [ "java" , "org.springframework.boot.loader.launch.JarLauncher" ]
The multi-stage build reduces final image size and improves build caching. Dependencies are cached separately from application code.
Building the Docker Image
Basic Build
Build the Docker image using:
docker build -t furniture-api .
Build with Tag
Build with version tag:
docker build -t furniture-api:0.0.1-SNAPSHOT .
The Dockerfile uses BuildKit syntax for improved caching. Ensure BuildKit is enabled:
Running with Docker
Run Container
Start the container with port mapping:
docker run -p 8082:8082 furniture-api
Run with Environment Variables
Pass environment variables for configuration:
docker run -p 8082:8082 \
-e DB_HOST=your-db-host \
-e DB_PORT= 5432 \
-e DB_NAME=catalog_and_inventory_db \
-e DB_USERNAME=your-username \
-e DB_PASSWORD=your-password \
furniture-api
Run in Detached Mode
Run container in background:
docker run -d -p 8082:8082 --name furniture-api furniture-api
Docker Compose Configuration
Basic Setup
The compose.yaml file defines the application service:
services :
server :
build :
context : .
ports :
- 8082:8082
With PostgreSQL Database
Extend the configuration to include PostgreSQL:
Complete Stack
With Secrets
services :
server :
build :
context : .
ports :
- 8082:8082
environment :
- DB_HOST=db
- DB_PORT=5432
- DB_NAME=catalog_and_inventory_db
- DB_USERNAME=postgres
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/catalog_and_inventory_db
depends_on :
db :
condition : service_healthy
db :
image : postgres:16-alpine
restart : always
environment :
- POSTGRES_DB=catalog_and_inventory_db
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
volumes :
- db-data:/var/lib/postgresql/data
ports :
- 5432:5432
healthcheck :
test : [ "CMD" , "pg_isready" , "-U" , "postgres" ]
interval : 10s
timeout : 5s
retries : 5
volumes :
db-data :
Create the db/password.txt file with your database password before running Docker Compose with secrets.
Docker Compose Commands
Start Services
Build and start
Build images and start all services: docker compose up --build
Run in background
Start services in detached mode:
View logs
Monitor application logs: # All services
docker compose logs -f
# Specific service
docker compose logs -f server
Stop Services
# Stop services
docker compose stop
# Stop and remove containers
docker compose down
# Stop and remove containers, volumes, and images
docker compose down -v --rmi all
Image Optimization
Layer Caching
The Dockerfile is optimized for layer caching:
Dependencies are downloaded in a separate layer
Maven cache is persisted between builds
Spring Boot layers are extracted separately
Only changed layers are rebuilt
This approach significantly speeds up rebuilds when only application code changes, as dependencies don’t need to be re-downloaded.
Image Size
The final image uses JRE instead of JDK:
FROM eclipse-temurin:21-jre-jammy AS final
This reduces image size by approximately 200-300 MB compared to using the full JDK.
Security Best Practices
Non-Root User
The application runs as a non-privileged user:
ARG UID=10001
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
appuser
USER appuser
Port Configuration
The application exposes port 8082:
Map to a different host port if needed:
docker run -p 8080:8082 furniture-api
Health Checks
Add health check to Docker Compose:
services :
server :
build :
context : .
ports :
- 8082:8082
healthcheck :
test : [ "CMD" , "curl" , "-f" , "http://localhost:8082/actuator/health" ]
interval : 30s
timeout : 10s
retries : 3
start_period : 40s
The Furniture API includes Spring Boot Actuator, which provides a /actuator/health endpoint for health checks.
Troubleshooting
Build Failures
If the build fails:
# Clear build cache
docker builder prune
# Rebuild without cache
docker build --no-cache -t furniture-api .
Container Won’t Start
Check container logs:
docker logs furniture-api
# Or with Docker Compose
docker compose logs server
Connection Issues
If the application can’t connect to the database:
Verify database container is running: docker compose ps
Check network connectivity: docker compose exec server ping db
Verify environment variables: docker compose exec server env | grep DB
Port Already in Use
If port 8082 is already in use:
services :
server :
ports :
- 8083:8082 # Map to different host port