GitHub repo for server images to use for local development with SteeltoeOSS.
| Name | Description |
|---|---|
| steeltoe.azurecr.io/config-server | Spring Cloud Config Server |
| steeltoe.azurecr.io/eureka-server | Spring Cloud Netflix Eureka Server |
| steeltoe.azurecr.io/spring-boot-admin | Spring Boot Admin |
| steeltoe.azurecr.io/uaa-server | Cloud Foundry UAA Server |
See Common Tasks for instructions on how to run these images.
Excluding UAA, each server image (config-server, eureka-server, spring-boot-admin) has a ready-to-build Gradle project in its source/ directory. The source/ directory is regenerated from scratch by update-project.ps1 whenever the Spring Boot version or dependencies need to change.
update-project.ps1
│ 1. Download fresh project zip from start.spring.io
│ 2. Apply patches/ <-- modify Initializr-generated files
│ 3. Apply customizations/ <-- add content Initializr never generates
│ 4. Regenerate gradle.lockfile
<image>/source/ <-- committed, ready-to-build
│
build.ps1 --> bootBuildImage --> Docker image
Use patches when modifying content that Initializr generates (Java source files, application.properties). Patches are standard unified diff files applied with patch -p1.
Use customizations for content that Initializr never generates:
build.gradle.append- appended to the generatedbuild.gradle. Contains the image-build hardening: digest-pinnedbuilder/runImage, a reproduciblecreatedDate,dependencyLocking, and thebootBuildImage-->testdependency gate. An append is used rather than a patch because this block is entirely new content. A line-anchored patch at the end of a file that Initializr can restructure is fragile.overlay/- files copied verbatim over the generated project, mirroring the project layout. Contains hand-written tests and any other files Initializr would never produce (for example:BasicOrNoAuthConfig.javafor config-server).
Edit patches or customizations, not source/ directly. Then run update-project.ps1 to regenerate.
Images are built reproducibly:
- Builder and run images are pinned by digest in
build.gradle.append - Dependency versions are locked in
gradle.lockfile(regenerated byupdate-project.ps1) - The image creation timestamp is derived from the git commit, not the wall clock
The Gradle wrapper jar is not committed (.gitignore). build.ps1 downloads it from GitHub on first use and validates its SHA-256 checksum against Gradle's official distribution on every build, regardless of whether the jar was just downloaded. This defends against a tampered or substituted jar from any source.
The following tools are required to build any image in this repository:
- PowerShell or pwsh
- Docker or Podman
Config Server, Eureka, and Spring Boot Admin additionally require:
- JDK 25
- Internet access (to download the Gradle distribution and Maven dependencies on first build)
If you do not have a JDK installed, consider Scoop:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression
scoop bucket add java
scoop install java/temurin25-jdk./build.ps1 config-serverThe build runs the project's tests first and fails if any test fails.
docker imagesRun update-project.ps1 to regenerate source/ from start.spring.io and apply all patches and customizations:
.\update-project.ps1 # update all Java images
.\update-project.ps1 -Names config-server # update one image
.\update-project.ps1 -Names config-server,eureka-server # update multiple imagesRequires JDK 25 and network access (resolves dependencies to regenerate gradle.lockfile). Also requires patch in your PATH (installed with Git for Windows).
The script checks start.spring.io for a newer Spring Boot version in your current track (major.minor) and reports if a newer compatible version is available. It also resolves the current Spring Cloud or Spring Boot Admin artifact version from the Spring Cloud BOM POM and automatically updates IMAGE_VERSION when a new version is detected.
- Run
update-project.ps1- it will auto-updateIMAGE_VERSIONinmetadata/and regeneratesource/ - Review the changes in
source/(especially the lockfile) - If patches no longer apply cleanly, update the relevant patch file
- Run
./build.ps1 -Name <image>to verify the Docker image build - Commit
metadata/,patches/,customizations/, andsource/
- Edit the relevant file under
patches/orcustomizations/ - Run
update-project.ps1to regeneratesource/ - Run
./build.ps1 -Name <image>to verify the Docker image build - Commit everything
Releases are triggered by publishing a GitHub release. The release workflow builds and smoke-tests each image, then pushes the following tags:
<version>- exact version (for example:4.3.1)<major.minor>- floating minor alias (for example:4.3)<major>- floating major alias (for example:4)latest
IMAGE_REVISION allows publishing a new image for the same package version without changing the version number (for example:, after a buildpack or infrastructure fix). The lifecycle:
- Normal release:
IMAGE_REVISIONis empty --> published tag is4.3.1, floating aliases updated - Hotfix: set
IMAGE_REVISIONto2, commit, trigger a release --> published tag is4.3.1-2, floating aliases updated - Subsequent hotfixes: increment to
3,4, etc. Do not clearIMAGE_REVISIONafter each release - the number stays set so the next hotfix knows where to start - Version bump: clear
IMAGE_REVISION(back to empty) whenIMAGE_VERSIONis bumped.update-project.ps1does this automatically when it detects and applies a new version.
Via StackOverflow:
- Find the id of the stopped container:
docker ps -a - Commit it to a new image:
docker commit $CONTAINER_ID test_image - Run with a shell:
docker run -ti --entrypoint=sh test_image