|
5 | 5 | **Version 1.2.5 released.** Fixed CI scripted tests and AKKA_REPO_TOKEN |
6 | 6 | propagation. All 16 scripted tests now pass in CI. |
7 | 7 |
|
| 8 | +**Active branch: feature/docker-dual** - Adding dual Docker image support |
| 9 | +(dev/prod) for RIDDL services deployment to GKE. |
| 10 | + |
8 | 11 | ## Work Completed (Recent) |
9 | 12 |
|
10 | 13 | ### Session Jan 28-29, 2026 - v1.2.5 Released (CI Fixes) |
@@ -144,6 +147,72 @@ Plus credentials in `~/.sbt/1.0/github.sbt`. |
144 | 147 | - ~~Parameterize dependency versions~~ ✓ |
145 | 148 | - ~~Add initial scripted tests for coverage~~ ✓ |
146 | 149 |
|
| 150 | +### 🔵 ACTIVE: Docker Dual-Image Support (feature/docker-dual) |
| 151 | + |
| 152 | +**Goal:** Add `With.Packaging.dockerDual()` helper to support building separate |
| 153 | +dev and prod Docker images for RIDDL services (MCP, Sim, Gen). |
| 154 | + |
| 155 | +**Requirements gathered in ossum-ops session (Feb 2, 2026):** |
| 156 | + |
| 157 | +| Aspect | Dev Image | Prod Image | |
| 158 | +|--------|-----------|------------| |
| 159 | +| Base | `eclipse-temurin:25-jdk-noble` | `gcr.io/distroless/java25-debian13:nonroot` | |
| 160 | +| Arch | `linux/arm64` (Apple Silicon) | `linux/amd64` (GKE) | |
| 161 | +| Tags | `:dev-latest`, `:dev-<version>` | `:latest`, `:<version>` | |
| 162 | +| Tools | JDK (jcmd, jstack, jmap) | JRE only (minimal) | |
| 163 | +| Shell | Yes (Ubuntu bash) | No (distroless) | |
| 164 | + |
| 165 | +**Design decisions:** |
| 166 | +1. Two separate images (not multi-arch buildx) |
| 167 | +2. `docker:publishLocal` defaults to dev image |
| 168 | +3. Explicit `dockerPublishProd` task for production |
| 169 | +4. CI builds only prod images |
| 170 | +5. Both use staged layout (no sbt-assembly fat JAR) |
| 171 | +6. Custom Dockerfile for prod to handle classpath with distroless |
| 172 | + |
| 173 | +**API design:** |
| 174 | +```scala |
| 175 | +// In project's build.sbt - minimal configuration |
| 176 | +.configure( |
| 177 | + With.Packaging.dockerDual( |
| 178 | + mainClass = "com.ossuminc.riddl.mcp.Main", |
| 179 | + pkgName = "riddl-mcp-server", |
| 180 | + exposedPorts = Seq(8080, 8558, 9001) |
| 181 | + ) |
| 182 | +) |
| 183 | + |
| 184 | +// Optional overrides if needed |
| 185 | +.settings( |
| 186 | + dockerRepository := Some("custom-registry.io") |
| 187 | +) |
| 188 | +``` |
| 189 | + |
| 190 | +**Implementation tasks:** |
| 191 | +- [ ] Update `Packaging.scala` with `dockerDual()` helper |
| 192 | +- [ ] Add `dockerPublishProd` task definition |
| 193 | +- [ ] Generate custom Dockerfile for distroless (via `dockerCommands`) |
| 194 | +- [ ] Set default repository to `ghcr.io/ossuminc` |
| 195 | +- [ ] Configure non-root user for both images |
| 196 | +- [ ] Add architecture settings (arm64 dev, amd64 prod) |
| 197 | +- [ ] Add tag pattern logic (`:dev-*` vs `:<version>`) |
| 198 | +- [ ] Add scripted test for docker-dual |
| 199 | +- [ ] Update README.md with documentation |
| 200 | + |
| 201 | +**Custom Dockerfile for distroless prod:** |
| 202 | +```dockerfile |
| 203 | +FROM gcr.io/distroless/java25-debian13:nonroot |
| 204 | +WORKDIR /opt/docker |
| 205 | +COPY --chown=nonroot:nonroot opt/docker/lib lib |
| 206 | +ENTRYPOINT ["java", "-cp", "/opt/docker/lib/*", "<MainClass>"] |
| 207 | +``` |
| 208 | + |
| 209 | +**References:** |
| 210 | +- [distroless Java README](https://github.com/GoogleContainerTools/distroless/blob/main/java/README.md) |
| 211 | +- [sbt-native-packager Docker](https://www.scala-sbt.org/sbt-native-packager/formats/docker.html) |
| 212 | +- ossum-ops/lago/ARCHITECTURE.md (for deployment context) |
| 213 | + |
| 214 | +--- |
| 215 | + |
147 | 216 | ### 🟡 REMAINING WORK |
148 | 217 |
|
149 | 218 | #### 1. Remove or implement NodeTarget |
|
0 commit comments