# MTConnect integration-test fixture — the official MTConnect C++ Agent, fed live data by # a standard-library SHDR adapter. # # TWO services, and both are required: # # agent mtconnect/agent (the cppagent image). Serves /probe, /current and /sample on # :5000. NOTE the repository name — the source project is `mtconnect/cppagent` # but the published image is `mtconnect/agent`; `mtconnect/cppagent` does not # exist on Docker Hub. # adapter The data source. The agent image ships only the agent binary plus schemas and # styles — there is NO bundled simulator — so without this every observation is # UNAVAILABLE forever and the suite could prove nothing about reads or streaming. # The Agent dials OUT to it (agent.cfg's Adapters block); it is not published to # the host. # # Why pinned: the `latest` tag moves and a fixture that silently changes device-model # behaviour turns a driver regression into an unexplained red. Bump deliberately. # # Usage (from the docker host, stack dir /opt/otopcua-mtconnect): # docker compose up -d --wait # docker compose down # # Or from a dev box, via the helper (see CLAUDE.md "Docker Workflow"): # lmxopcua-fix sync mtconnect # lmxopcua-fix up mtconnect # single-service-shaped stack, no profile argument services: agent: image: mtconnect/agent:2.7.0.12 container_name: otopcua-mtconnect-agent restart: "no" labels: project: lmxopcua depends_on: adapter: condition: service_started ports: # Host port is overridable because macOS squats :5000 — AirPlay Receiver # (ControlCenter) binds *:5000 and WINS the race, so `docker port` reports a healthy # publish while every request answers "403 Forbidden / Server: AirTunes". On the # Linux docker host the default is correct and needs no override. To run the fixture # on a Mac: # MTCONNECT_AGENT_HOST_PORT=5555 docker compose up -d --wait # MTCONNECT_AGENT_ENDPOINT=http://127.0.0.1:5555 dotnet test ... - "${MTCONNECT_AGENT_HOST_PORT:-5000}:5000" volumes: # Individual FILE binds, not a directory bind: /mtconnect/config is a VOLUME declared # by the image, and mounting this whole folder over it would also drop docker-compose.yml # and adapter.py into the Agent's config directory. - ./agent.cfg:/mtconnect/config/agent.cfg:ro - ./Devices.xml:/mtconnect/config/Devices.xml:ro healthcheck: # The image is alpine-based, so busybox wget is present (there is no curl). A 200 from # /probe is the real readiness signal — the port accepts connections before the device # model is parsed. test: ["CMD-SHELL", "wget -q -O /dev/null http://127.0.0.1:5000/probe || exit 1"] interval: 5s timeout: 3s retries: 12 start_period: 5s adapter: image: python:3.13-alpine container_name: otopcua-mtconnect-adapter restart: "no" labels: project: lmxopcua volumes: - ./adapter.py:/fixtures/adapter.py:ro # Stock image + a bind-mounted script: this fixture needs no `build:` step at all, unlike # the Modbus / S7 / AB fixtures whose simulators are built from a Dockerfile. command: ["python", "-u", "/fixtures/adapter.py", "--host", "0.0.0.0", "--port", "7878"] expose: - "7878" healthcheck: test: ["CMD-SHELL", "python -c \"import socket; socket.create_connection(('127.0.0.1', 7878), timeout=2).close()\" || exit 1"] interval: 5s timeout: 3s retries: 6 start_period: 3s