0001-docker-local-development.md
ADR 0001: Local Docker development for WebVOWL + OWL2VOWL
| Metadata | Value |
|----------|-------|
| Status | Accepted (implemented in this repository) |
| Date | 2026-06-04 |
| Deciders | VisualDataWeb maintainers / local dev workflow |
| Supersedes | wget-based root Dockerfile on upstream master |
Context
WebVOWL needs a browser UI and an OWL2VOWL backend on the same origin (/convert, /serverTimeStamp). Upstream Docker docs build an image that downloads webvowl_1.1.7.war from vowl.visualdataweb.org. That host is compromised or unreachable (HTTP 520/403, corrupt HTML served as WAR). See #212, #203, #180.
Constraints:
- Small images where possible (multi-stage, no nginx/supervisor unless required).
- Volume mounts for ontologies (
/data) and optional frontend overlay (deploy/). - Do not change application build toolchains (Java 8, Maven as-is, Node 12 / Webpack 1 / Grunt).
- Bump only container base image tags (Tomcat 9.0.118, Maven 3.9.16, Temurin 8 on Noble, Node 12 Alpine — see
docker/DockerfileARGs). - All deliverables live inside Git repositories (WebVOWL + OWL2VOWL), not in a parent folder outside clones.
Local checkout: WebVOWL repository only. OWL2VOWL is not cloned on the host.
Decision
- Default:
docker-compose.yml+docker/Dockerfile(full stack). - OWL2VOWL at image build time:
git clonein the Maven stage (OWL2VOWL_GIT_URL/OWL2VOWL_GIT_REF, defaultmaster). No Composeadditional_contextsand no sibling directory. - Multi-stage build:
- Maven
3.9-eclipse-temurin-8→owl2vowl.war - Node
12-alpine→npm install --ignore-scripts+npm run release - Tomcat
9.0.118-jdk8-temurin-noble→ explode WAR intoROOT, overlaydeploy/
- Maven
- Single Tomcat
ROOT(same design as PR #215). - Reject PR #214 nginx/Java 17 split compose for this workflow.
- Frontend-only variant:
docker/Dockerfile.frontend+docker-compose.frontend.yml. - OWL2VOWL documents sibling checkout in
OWL2VOWL/doc/docker/README.md;.dockerignoreexcludes largeontologies/when used as build context. - Hardening: non-root
tomcat/owl2vowlusers, image + composeHEALTHCHECK,no-new-privileges, JRE runtime after WAR explode in JDK stage. - CI/CD:
.github/workflows/docker-ci.yml(PR/build test),docker-release.yml(push tagged images toghcr.io).
Rationale
| Approach | Why chosen / rejected |
|----------|----------------------|
| wget WAR | Broken (#212). |
| Sibling ../OWL2VOWL checkout | Replaced by git clone inside docker/Dockerfile (network at build time). |
| PR #215 | Correct merge model; arm64 fix: --ignore-scripts. |
| PR #214 | Java 17 + nginx rejected. |
| Two services, two ports, no proxy | Breaks relative /convert (#195). |
| doc/Docker legacy | /data volume pattern kept; inotify batch job not ported. |
Consequences
Positive
- No external WAR download; converter on same origin.
- ~358 MB runtime image (2026-06-04, arm64).
- Mount
./data; optional./deployoverlay.
Negative / follow-ups
- Merged build needs network to clone OWL2VOWL; pin
OWL2VOWL_GIT_REFfor reproducible releases. - Node 12 / Java 8 EOL.
- #111 Docker Hub not addressed.
- Align upstream PR #215 with this layout.
Verification (2026-06-04)
Environment: Docker 29.4, macOS arm64.
cd WebVOWL
docker compose build && docker compose up -d
curl -sf http://localhost:8080/serverTimeStamp
# POST foaf.rdf to /convert (any local OWL file)
Implementation map (WebVOWL)
| Path | Role |
|------|------|
| docker-compose.yml | Full stack (OWL2VOWL cloned in build) |
| docker-compose.frontend.yml | UI only |
| docker/Dockerfile | Merged image |
| docker/Dockerfile.frontend | Frontend-only image |
| docker/README.md | Operator guide (security, GHCR) |
| .github/workflows/docker-ci.yml | PR / main build + smoke test |
| .github/workflows/docker-release.yml | Publish to GHCR on tag v* |
| .dockerignore | WebVOWL build context |
| data/ | Host mount → /data |
| docs/adr/0001-… | This ADR |
Implementation map (OWL2VOWL)
| Path | Role |
|------|------|
| doc/docker/README.md | Sibling checkout + standalone JAR image |
| .dockerignore | Exclude ontologies/ from Docker context |
| Dockerfile | Standalone converter (non-root, healthcheck) |
| .github/workflows/docker-ci.yml | PR / main build + smoke test |
| .github/workflows/docker-release.yml | GHCR on tag v* |
Related GitHub issues (WebVOWL)
| # | State | Title | Relevance | |---|-------|-------|-----------| | 212 | OPEN | Docker compose: wget HTTP 520 | Primary | | 203 | OPEN | README Docker instructions do not work | Fixed here | | 202 | OPEN | Temporary fix as website is down | Same root cause | | 195 | OPEN | Could not establish OWL2VOWL connection | Fixed with merged image | | 201 | OPEN | OWL2VOWL service error | Related | | 180 | CLOSED | Unable to download war release | Historical | | 206 | CLOSED | Service is down | Domain context | | 183 | OPEN | WebVOWL cannot be rebuild | Addressed via source build | | 111 | OPEN | Docker Hub image | Not implemented | | 100 | CLOSED | Add Dockerfile | Original Docker support |
Related GitHub pull requests (WebVOWL)
| # | State | Title | Notes | |---|-------|-------|-------| | 215 | OPEN | Build from source in Docker | Align with this ADR | | 214 | CLOSED | Modernize Docker (Java 17, nginx) | Rejected scope | | 213 | CLOSED | Duplicate of #214 | | | 114 | OPEN | chore(docker): update image | wget-based; obsolete | | 207 | DRAFT | Dockerfile page amd64 | Partial | | 181 | MERGED | Fixed Docker File | | | 170 | MERGED | Dockerized WebVOWL | | | 102 | MERGED | Fix #100 Add Docker | |
Related GitHub (OWL2VOWL)
| # | State | Title | Notes |
|---|-------|-------|-------|
| 47 | MERGED | Dockerize | Standalone OWL2VOWL/Dockerfile; merged build uses Maven stage in WebVOWL |
References
- docker/README.md
- doc/Docker/README.md — legacy inotify image
- OWL2VOWL doc/docker/README.md — sibling layout
- TIB WebVOWL