Skip to content

Consolidate tool Dockerfiles into a single multi-stage Dockerfile#111

Draft
Copilot wants to merge 3 commits intomainfrom
copilot/refactor-dockerfile-for-tools
Draft

Consolidate tool Dockerfiles into a single multi-stage Dockerfile#111
Copilot wants to merge 3 commits intomainfrom
copilot/refactor-dockerfile-for-tools

Conversation

Copy link

Copilot AI commented Mar 24, 2026

  • Create a single root-level Dockerfile with:
    • One Maven build stage (mavenbuilder) that builds ALL tools with -Pall
    • Separate npm/static build stages for each tool frontend (emf, emfatic, ocl, conversion, xtext)
    • Separate final service stages for each tool (emf, emfatic, ocl, conversion, xtext)
  • Each tool service stage copies only the Maven module folders needed for that tool (matching the original per-tool Dockerfile Maven profiles)
  • Verify the new Dockerfile has correct COPY paths (build context must be the repo root)
  • Run code review and CodeQL security check
Original prompt

This section details on the original issue you should resolve

<issue_title>Improve tool Docker file performance</issue_title>
<issue_description>The docker files for the various tools (/static.xxx/Dockerfile) re-run Maven repeatedly. The way this is currently written, docker has no way to identify that parts of this build are redundant.

Instead, we should have just one staged-build Dockerfile for all tool services. This would start with a stage that builds all tools in one Maven call and then we would have separate stages for building each tool, copying the required information as and when. In the main docker-compose file, we then call the appropriate stage in this central Dockerfile instead of using a separate Dockerfile for each tool.

This way, Maven has to run once and the results can then be cached by Docker across all tools. </issue_description>

<agent_instructions>Make a first refactoring of all the relevant Dockerfiles into one central Dockerfile. Ignore the comment about the central docker-compose file, which is in a separate repository and needs a separate PR there.</agent_instructions>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Refactor tool Dockerfiles into one central Dockerfile Consolidate tool Dockerfiles into a single multi-stage Dockerfile Mar 24, 2026
Copilot AI requested a review from szschaler March 24, 2026 20:29
Dockerfile Outdated

# Copy built tool and sources
COPY --from=mavenbuilder /root/.m2 /root/.m2
COPY --from=mavenbuilder /usr/src/toolfunctions /toolservice
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line, and the corresponding ones in the other service build stages, needs to only copy the folders actually needed by each tool. Check out the maven build in the respective bespoke Dockerfiles to work out which folders these are.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in f1b6062. Each tool service stage now copies only its required module folders, matching the Maven profiles from the original per-tool Dockerfiles:

  • emf: core, emf, emffunction
  • emfatic: core, emf, emfatic, emfaticfunction
  • ocl: core, eclipseocl, eclipseoclfunction
  • conversion: core, emf, epsilon, epsilonfunction
  • xtext: core, emf, xtext, xtextfunction

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a single root-level multi-stage Dockerfile that centralizes the Maven build for all tool services and then produces separate final images per tool by targeting different stages.

Changes:

  • Adds a root Dockerfile with a shared mavenbuilder stage that builds all tool modules with -Pall.
  • Adds per-tool frontend build stages (EMF, Emfatic, OCL, Conversion, Xtext) and per-tool final service stages.
  • Updates service stages to copy only the Maven module folders needed for each tool (mirroring the original per-tool profile module sets).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +36 to +56
FROM node:19-bullseye AS staticbuild-emf

WORKDIR /usr/src/mdenet-tool

COPY static.emf/package*.json ./
COPY static.emf .

RUN npm install; npm run build; chmod -R 755 dist/


# ---------------------------------------------------------------------------
# Stage 2b – Static frontend build for Emfatic
# ---------------------------------------------------------------------------
FROM node:19-bullseye AS staticbuild-emfatic

WORKDIR /usr/src/mdenet-tool

COPY static.emfatic/package*.json ./
COPY static.emfatic .

RUN npm install; npm run build; chmod -R 755 dist/
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This stage uses node:19-bullseye. Node 19 is long EOL, so continuing to build on it increases security risk and may break future dependency installs. Please switch these frontend build stages to a supported LTS base image (and keep it consistent with the Node version used in the Xtext service stage).

Copilot uses AI. Check for mistakes.
Comment on lines +79 to +82
COPY static.conversion/package*.json ./
COPY static.conversion .

RUN npm install; npm run build; chmod -R 755 dist/
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue here: npm install; npm run build; ... should use && to avoid masking failures, and npm ci is preferred for reproducible builds when package-lock.json exists.

Copilot uses AI. Check for mistakes.
Comment on lines +96 to +99
COPY xtext/static.xtext/package*.json ./
COPY xtext/static.xtext .

RUN npm install; npm run build; chmod -R 755 dist/
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue here: npm install; npm run build; ... should use && to ensure failures fail the build, and prefer npm ci for lockfile installs.

Copilot uses AI. Check for mistakes.
&& if [ "$ARCH" = "arm64" ] || [ "$ARCH" = "aarch64" ]; then NODE_ARCH="linux-arm64"; else NODE_ARCH="linux-x64"; fi \
&& NODE_RELEASE="node-v${NODE_VERSION}-${NODE_ARCH}" \
&& echo "Installing ${NODE_RELEASE}" \
&& curl --output ${NODE_RELEASE}.tar.xz https://nodejs.org/download/release/v${NODE_VERSION}/${NODE_RELEASE}.tar.xz \
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Xtext service installs Node by downloading a tarball via curl without any integrity verification (checksum/signature). This is a supply-chain risk; prefer installing Node from a trusted distribution mechanism (OS packages/Nodesource) or verify the download using published SHASUMS before extracting.

Suggested change
&& curl --output ${NODE_RELEASE}.tar.xz https://nodejs.org/download/release/v${NODE_VERSION}/${NODE_RELEASE}.tar.xz \
&& curl -fsSL -o ${NODE_RELEASE}.tar.xz https://nodejs.org/download/release/v${NODE_VERSION}/${NODE_RELEASE}.tar.xz \
&& curl -fsSL -o SHASUMS256.txt https://nodejs.org/download/release/v${NODE_VERSION}/SHASUMS256.txt \
&& grep " ${NODE_RELEASE}.tar.xz\$" SHASUMS256.txt > SHASUMS256.txt.node \
&& sha256sum -c SHASUMS256.txt.node \

Copilot uses AI. Check for mistakes.
Comment on lines +278 to +279
# The release of node to install
ENV NODE_VERSION=19.9.0
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NODE_VERSION=19.9.0 is an EOL Node release. Please switch to a currently supported LTS version to reduce CVE exposure and keep npm dependency installs working over time.

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +56
COPY static.emfatic/package*.json ./
COPY static.emfatic .

RUN npm install; npm run build; chmod -R 755 dist/
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the EMF static build: npm install; npm run build; ... should be changed to use && (to avoid masking failures) and preferably npm ci for reproducible installs when package-lock.json is present.

Copilot uses AI. Check for mistakes.
Comment on lines +66 to +69
COPY static.ocl/package*.json ./
COPY static.ocl .

RUN npm install; npm run build; chmod -R 755 dist/
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue here: using ; between npm commands can allow the Docker build to succeed even if npm install/npm run build fails (depending on the last command). Use && chaining and consider npm ci for lockfile-based installs.

Copilot uses AI. Check for mistakes.
Comment on lines +281 to +282
RUN apt-get update && apt-get install -y --no-install-recommends unzip zip xz-utils maven cron psmisc

Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apt-get update && apt-get install ... in this stage doesn't clean /var/lib/apt/lists/*, which leaves package index files in the image and increases size. Consider adding the standard cleanup (and similarly remove any temporary artifacts created during Node installation) to keep the final image leaner.

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +23
COPY services /usr/src/toolfunctions

WORKDIR /usr/src/toolfunctions

Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Maven build stage copies the entire services/ tree before running mvn, which means any change anywhere under services/ will invalidate the Docker cache for dependency download/build. To better leverage caching, copy services/pom.xml (and any other Maven metadata) first and run a dependency prefetch (or mvn -Pall -DskipTests ... as appropriate), then copy the rest of the sources and run the full build.

Suggested change
COPY services /usr/src/toolfunctions
WORKDIR /usr/src/toolfunctions
WORKDIR /usr/src/toolfunctions
# Copy Maven metadata first to leverage Docker layer caching for dependencies
COPY services/pom.xml /usr/src/toolfunctions/pom.xml
# Prefetch Maven dependencies without running tests or doing a full build
RUN mvn -Pall -DskipTests dependency:go-offline
# Now copy the full source tree and perform the actual build
COPY services /usr/src/toolfunctions

Copilot uses AI. Check for mistakes.
Comment on lines +40 to +43
COPY static.emf/package*.json ./
COPY static.emf .

RUN npm install; npm run build; chmod -R 755 dist/
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dependency caching for this frontend stage is reduced because npm install runs after copying the full source tree. Consider copying only package*.json, running npm ci, then copying the rest of the sources and running the build (also use && instead of ; to avoid masking failures).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve tool Docker file performance

3 participants