sap-mcp-bridge: new app — five SAP MCP servers behind one nginx-proxied port
This commit is contained in:
82
apps/sap-mcp-bridge/build/Dockerfile
Normal file
82
apps/sap-mcp-bridge/build/Dockerfile
Normal file
@@ -0,0 +1,82 @@
|
||||
# syntax=docker/dockerfile:1.7
|
||||
#
|
||||
# sap-mcp-bridge
|
||||
# -------------------------------------------------------------------
|
||||
# One container, five SAP MCP servers, all reachable through a single
|
||||
# external HTTP port via an internal nginx reverse proxy. This makes
|
||||
# the container deployable behind Traefik/Runtipi where only one port
|
||||
# per app can be exposed.
|
||||
#
|
||||
# External (single port — Runtipi binds it):
|
||||
# / landing page
|
||||
# /healthz aggregate health probe
|
||||
# /cap/mcp sap-cap (cap-js-mcp-server)
|
||||
# /cap/healthz
|
||||
# /abap/mcp sap-abap-adt (mcp-abap-adt)
|
||||
# /abap/healthz
|
||||
# /odata/mcp sap-odata (btp-sap-odata-to-mcp-server)
|
||||
# /odata/healthz
|
||||
# /ui5/mcp ui5-mcp-server (ui5mcp)
|
||||
# /ui5/healthz
|
||||
# /fiori/mcp fiori-mcp-server (fiori-mcp)
|
||||
# /fiori/healthz
|
||||
#
|
||||
# Internally:
|
||||
# 127.0.0.1:9001..9005 individual supergateway HTTP endpoints
|
||||
# 127.0.0.1:8080 nginx (the only port EXPOSEd)
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
FROM node:24-bookworm-slim
|
||||
|
||||
ENV NODE_ENV=production \
|
||||
NPM_CONFIG_FUND=false \
|
||||
NPM_CONFIG_AUDIT=false \
|
||||
NPM_CONFIG_UPDATE_NOTIFIER=false
|
||||
|
||||
# tini : PID-1 init that reaps zombies and forwards SIGTERM cleanly
|
||||
# nginx : in-container reverse proxy (single externally-visible port)
|
||||
# gosu : drop privileges from root → mcp after we've chowned /workspace
|
||||
# curl : healthcheck client
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
tini ca-certificates curl nginx gosu \
|
||||
&& rm -rf /var/lib/apt/lists/* /var/log/nginx/*
|
||||
|
||||
# Install all MCP servers + the stdio<->HTTP bridge globally.
|
||||
# All versions pinned for reproducibility — a broken supergateway or
|
||||
# MCP-server release would silently break every endpoint on the next
|
||||
# rebuild. Bump deliberately, not by accident.
|
||||
RUN npm install -g --omit=dev --no-audit --no-fund \
|
||||
supergateway@3.4.3 \
|
||||
@iflow-mcp/cap-js-mcp-server@0.0.3 \
|
||||
@iflow-mcp/mcp-abap-adt@1.1.0 \
|
||||
@iflow-mcp/btp-sap-odata-to-mcp-server@1.0.0 \
|
||||
@ui5/mcp-server@0.2.11 \
|
||||
@sap-ux/fiori-mcp-server@0.6.49
|
||||
|
||||
# Non-root runtime user. Container still starts as root so the
|
||||
# entrypoint can chown /workspace; it then drops to this user via gosu.
|
||||
# (No -r flag: Debian's SYS_UID_MAX is 999, and we want UID 10001 — the
|
||||
# warning useradd -r produces is harmless but ugly in build logs.)
|
||||
RUN useradd -u 10001 -g nogroup -d /home/mcp -m mcp
|
||||
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||
|
||||
# /workspace is the project root the cap / ui5 / fiori servers operate on.
|
||||
# It's the volume mount target — host-side it's bound to a user-config path
|
||||
# from the Runtipi compose. Pre-creating it here makes "no volume bound"
|
||||
# (e.g. local docker run) still work.
|
||||
RUN mkdir -p /workspace && chown -R mcp:nogroup /workspace
|
||||
WORKDIR /workspace
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
# Cheap liveness: nginx aggregates /healthz; if it answers 200, the
|
||||
# container is "alive enough" from Traefik's perspective.
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
|
||||
CMD curl -fsS http://127.0.0.1:8080/healthz || exit 1
|
||||
|
||||
ENTRYPOINT ["/usr/bin/tini", "--"]
|
||||
CMD ["/usr/local/bin/entrypoint.sh"]
|
||||
Reference in New Issue
Block a user