Todo CRUD sample application built with Spring Boot 4, Spring gRPC, Spring Data JPA, Liquibase, H2, Spring Security JWT, Protovalidate, and Hibernate second-level cache backed by Caffeine/JCache. This image runs the app as a GraalVM native executable for fast startup and low memory usage.
This image exposes server-side gRPC APIs for authentication and Todo management. The application listens on the standard gRPC port 9090. When running containers on the same Docker network, connect to <container-name>:9090 with plaintext gRPC unless you add TLS at the platform edge.
ListTodosROLE_ADMIN authorization for Todo APIsInstant created_at and updated_atdocker run --name postgresql --rm -d \
-e POSTGRES_USER=appuser \
-e POSTGRES_PASSWORD=appuser \
-e POSTGRES_DB=grpcsamples \
-p 127.0.0.1:5432:5432 \
postgres:18-alpine
Generate at least a 256-bit secret:
openssl rand -hex 32
docker run --rm -p 9090:9090 \
-e SPRING_PROFILES_ACTIVE=prod \
-e SPRING_DATASOURCE_URL=jdbc:postgresql://host.docker.internal:5432/grpcsamples \
-e SPRING_DATASOURCE_USERNAME=appuser \
-e SPRING_DATASOURCE_PASSWORD=appuser \
-e SECURITY_JWT_SECRET="<paste-openssl-output>" \
suayb/spring-grpc-samples:latest-native
Or with H2 in-memory (no PostgreSQL required):
docker run --rm -p 9090:9090 \
-e SECURITY_JWT_SECRET="$(openssl rand -hex 32)" \
suayb/spring-grpc-samples:latest-native
The gRPC server is available at:
localhost:9090
grpcurl -plaintext \
-d '{"service": ""}' \
localhost:9090 \
grpc.health.v1.Health/Check
Expected response:
{
"status": "SERVING"
}
grpcurl -plaintext localhost:9090 list
Expected services include:
AuthService
TodoService
grpc.health.v1.Health
grpc.reflection.v1.ServerReflection
Seeded users:
| Username | Password | Authorities |
|---|---|---|
admin | admin | ROLE_ADMIN, ROLE_USER |
user | user | ROLE_USER |
Get an admin token:
TOKEN=$(grpcurl -plaintext \
-d '{"username":"admin","password":"admin"}' \
localhost:9090 \
AuthService/Login | jq -r '.access_token')
List todos:
grpcurl -plaintext \
-rpc-header "authorization: Bearer ${TOKEN}" \
-d '{"pageRequest":{"page":0,"size":5}}' \
localhost:9090 \
TodoService/ListTodos
Create a todo:
grpcurl -plaintext \
-rpc-header "authorization: Bearer ${TOKEN}" \
-d '{"title":"Prepare gRPC release"}' \
localhost:9090 \
TodoService/CreateTodo
Pass accept-language as gRPC metadata.
Turkish validation example:
grpcurl -plaintext \
-rpc-header "authorization: Bearer ${TOKEN}" \
-rpc-header "accept-language: tr" \
-d '{"title":"ab"}' \
localhost:9090 \
TodoService/CreateTodo
English validation example:
grpcurl -plaintext \
-rpc-header "authorization: Bearer ${TOKEN}" \
-rpc-header "accept-language: en" \
-d '{"title":"ab"}' \
localhost:9090 \
TodoService/CreateTodo
| Name | Default | Description |
|---|---|---|
SPRING_PROFILES_ACTIVE | default | Active Spring profile |
SPRING_GRPC_SERVER_PORT | 9090 | gRPC server port |
SPRING_DATASOURCE_URL | jdbc:h2:mem:spring-grpc-samples;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false | JDBC URL |
SPRING_DATASOURCE_USERNAME | sa | Database username |
SPRING_DATASOURCE_PASSWORD | (empty) | Database password |
SPRING_LIQUIBASE_ENABLED | true | Enable or disable Liquibase migrations |
SPRING_LIQUIBASE_CONTEXTS | faker | Liquibase contexts used for sample todo data |
APP_SECURITY_JWT_ISSUER | https://spring-grpc-samples.local | JWT issuer |
SECURITY_JWT_SECRET | local sample secret | JWT HMAC secret; replace for every real deployment |
APP_SECURITY_JWT_EXPIRES_IN | 1h | Access token lifetime |
Generate a 256-bit JWT secret:
openssl rand -hex 32
Auth:
AuthService/LoginTodos:
TodoService/CreateTodoTodoService/GetTodoTodoService/ListTodosTodoService/UpdateTodoTodoService/PatchTodoTodoService/DeleteTodoInfrastructure:
grpc.health.v1.Health/Checkgrpc.reflection.v1.ServerReflectionThe image exposes the standard gRPC Health Checking service.
Kubernetes example:
livenessProbe:
grpc:
port: 9090
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
grpc:
port: 9090
initialDelaySeconds: 10
periodSeconds: 10
AuthService/Login, gRPC health, and gRPC reflection are public.ROLE_ADMIN.accept-language: tr or accept-language: en metadata to localize error responses.Content type
Image
Digest
sha256:b328f89c0…
Size
34.2 MB
Last updated
about 1 month ago
docker pull suayb/spring-grpc-samples:latest-native