[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6KW5EARYASXB8MN67C82C6G":3,"skill-same:01M6KW5EARYASXB8MN67C82C6G":72},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":26,"publishedAt":46,"linkOnly":47,"markdownContent":48,"markdownBody":49,"frontMatter":50,"refName":51,"commitSha":52,"skillDirectory":53,"forksCount":14,"repositoryHtmlUrl":54,"repositoryHomepageUrl":6,"ownerHtmlUrl":55,"ownerBlogUrl":6,"ownerDescription":56,"updatedAt":57,"install":58,"resources":71},"01M6KW5EARYASXB8MN67C82C6G","k6-docker",null,"Invoke this skill when the question is **how to run k6 tests via Docker** — for either local development or CI automation. This skill is the execution-infrastructure complement to the k6 scripting skills","rafsanulhasan\u002FHypermediaEngine","rafsanulhasan","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F2341142?v=4","01M6KW2HWPTZWK051N7B0HTBVG","Rafsanul Hasan","01M6KW2J0N3613382MF5DRN79H",0,"GPL-3.0","https:\u002F\u002Fgithub.com\u002Frafsanulhasan\u002FHypermediaEngine\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fk6-docker\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000011","运维与部署","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],"k6 docker","k6","docker","how","for","local development","via","how to","tests","local","either","question","execution","scripting","ci","run","development","infrastructure","automation","2026-11-10 10:12:30",false,"---\nname: k6-docker\ndescription: \"Invoke this skill when the question is **how to run k6 tests via Docker** — for either local development or CI automation. This skill is the execution-infrastructure complement to the k6 scripting skills\"\n---\n\n# k6 Docker Execution\n\n## When to Use\nInvoke this skill when the question is **how to run k6 tests via Docker** — for either local development or CI automation. This skill is the execution-infrastructure complement to the k6 scripting skills:\n\n- Use `k6-performance-testing`, `k6-stress-testing`, `k6-load-testing` to write the test scripts and configure thresholds.\n- Use **this skill** to decide how to execute those scripts via Docker.\n\nTrigger scenarios:\n- \"How do I run my k6 script without installing k6 natively?\"\n- \"How do I run k6 in Docker Compose with InfluxDB + Grafana dashboards?\"\n- \"How do I run k6 from an AI agent session (Bash tool)?\"\n- \"How do I set up CI with Docker-based k6?\"\n- \"How do I run k6 programmatically from a .NET Testcontainers fixture?\"\n\n## Official Docker Image\n\n```bash\ndocker pull grafana\u002Fk6           # latest stable (recommended for CI — pin the tag)\ndocker pull grafana\u002Fk6:0.56.0    # pinned version (reproducible builds)\ndocker pull grafana\u002Fk6:latest-with-browser  # includes Chromium for k6 Browser API\n```\n\nImage: `grafana\u002Fk6` on Docker Hub (Verified Publisher). Alpine-based, non-root user (UID 12345).\n\n## Dev-Time: Running k6 in Docker Locally\n\n### Pattern A — stdin pipe (zero setup, fastest for quick runs)\n\n```bash\n# Linux \u002F macOS\ndocker run --rm -i grafana\u002Fk6 run - \u003C script.js\n\n# Windows (PowerShell)\ncat script.js | docker run --rm -i grafana\u002Fk6 run -\n\n# With VUs, duration, and env vars\ndocker run --rm -i \\\n  -e BASE_URL=http:\u002F\u002Fhost.docker.internal:5000 \\\n  grafana\u002Fk6 run --vus 10 --duration 30s - \u003C script.js\n```\n\n### Pattern B — volume mount (for multi-file projects with test data)\n\n```bash\n# Linux \u002F macOS\ndocker run --rm -i \\\n  -v \"$PWD\":\u002Fscripts \\\n  -w \u002Fscripts \\\n  grafana\u002Fk6 run script.js\n\n# Windows (PowerShell)\ndocker run --rm -i `\n  -v \"${PWD}:\u002Fscripts\" `\n  -w \u002Fscripts `\n  grafana\u002Fk6 run script.js\n```\n\n### Reaching the Host's ASP.NET Core API from the Container\n\nThe k6 container cannot reach `localhost` on the host directly — use these patterns:\n\n| Platform | Hostname | Extra Docker Flag |\n|----------|----------|-------------------|\n| Docker Desktop (Windows \u002F macOS) | `host.docker.internal` | None — resolved automatically |\n| Docker Engine on Linux | `host.docker.internal` | `--add-host=host.docker.internal:host-gateway` |\n| Docker Engine on Linux (alt) | `172.17.0.1` | None (default bridge gateway IP) |\n\n```bash\n# Linux Docker Engine\ndocker run --rm -i \\\n  --add-host=host.docker.internal:host-gateway \\\n  -e BASE_URL=http:\u002F\u002Fhost.docker.internal:5000 \\\n  grafana\u002Fk6 run - \u003C script.js\n```\n\nIn the k6 script:\n```javascript\nconst res = http.get(`${__ENV.BASE_URL}\u002Fapi\u002Fhealth`);\n```\n\n## Dev-Time: AI Agent Session (Bash Tool)\n\n**Docker MCP cannot spawn arbitrary containers.** The MCP Gateway only manages MCP server lifecycle (mcp-find, mcp-add, mcp-remove). There is no `container-run` or `docker-exec` primordial tool. The `poci`-type docker tool in mcp-registry is unconfirmed\u002Fexperimental.\n\n**Use the `Bash` tool instead** — both Claude Code and GitHub Copilot run in the host environment with full Docker daemon access:\n\n```bash\n# Run k6 and capture summary output (synchronous — blocks until k6 exits)\ndocker run --rm -i \\\n  --add-host=host.docker.internal:host-gateway \\\n  -v \"$PWD\u002Ftests\u002Fload\":\u002Fscripts \\\n  -e BASE_URL=http:\u002F\u002Fhost.docker.internal:5000 \\\n  grafana\u002Fk6 run \u002Fscripts\u002Fload-test.js\n# k6 text summary prints to stdout — agent reads it directly\n```\n\n**Parsing results from the agent**: k6 prints pass\u002Ffail thresholds as `✓` \u002F `✗` in stdout. The agent can detect threshold results from the text summary without any JSON parsing. For structured parsing, use `handleSummary()`:\n\n```javascript\nexport function handleSummary(data) {\n  return { 'stdout': JSON.stringify(data) }; \u002F\u002F agent receives structured JSON\n}\n```\n\n**Exit code interpretation**:\n- `0` — all thresholds passed → performance is acceptable\n- `99` — threshold breached → report SLO violation to the user\n- `107` — script error → fix the test script\n\n## Dev-Time: Local Observability Stack (Docker Compose + InfluxDB v1 + Grafana)\n\nUse the built-in InfluxDB v1 output (no custom k6 build required):\n\n```yaml\n# docker-compose.observability.yml\nversion: '3.4'\n\nnetworks:\n  grafana:\n\nservices:\n  influxdb:\n    image: influxdb:1.12\n    networks: [grafana]\n    ports: [\"8086:8086\"]\n    environment:\n      - INFLUXDB_DB=k6\n\n  grafana:\n    image: grafana\u002Fgrafana:9.5.21\n    networks: [grafana]\n    ports: [\"3000:3000\"]\n    environment:\n      - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin\n      - GF_AUTH_ANONYMOUS_ENABLED=true\n      - GF_AUTH_BASIC_ENABLED=false\n    volumes:\n      - .\u002Fgrafana:\u002Fetc\u002Fgrafana\u002Fprovisioning\u002F  # auto-provisions datasource + dashboard\n\n  k6:\n    image: grafana\u002Fk6\n    networks: [grafana]\n    volumes:\n      - .\u002Ftests\u002Fload:\u002Fscripts\n```\n\n**Run a test and stream to InfluxDB**:\n```bash\ndocker compose -f docker-compose.observability.yml run --rm -T k6 run \\\n  --out influxdb=http:\u002F\u002Finfluxdb:8086\u002Fk6 \\\n  \u002Fscripts\u002Fload-test.js\n```\n\n**Open the dashboard**: `http:\u002F\u002Flocalhost:3000\u002Fd\u002FLe2Ku9NMk\u002Fk6-performance-test`\n\nAlternatively import Grafana community dashboard **ID 2587** (\"k6 Load Testing Results\") via Grafana → Dashboards → Import → ID `2587`.\n\n### Advanced: InfluxDB v2 + Grafana (requires custom k6 build)\n\nInfluxDB v2 output is NOT in the stock `grafana\u002Fk6` image. Use the official `grafana\u002Fxk6-output-influxdb` repo (includes a `Dockerfile` and `docker-compose.yml` with pre-provisioned dashboards):\n\n```\nhttps:\u002F\u002Fgithub.com\u002Fgrafana\u002Fxk6-output-influxdb\n```\n\n## Dev-Time: Programmatic k6 from .NET (Testcontainers)\n\n**There is no official `Testcontainers.K6` NuGet package** (confirmed: zero results on NuGet, May 2026). Use the generic `ContainerBuilder` API:\n\n```csharp\n\u002F\u002F NuGet: Testcontainers (v3.x)\nusing DotNet.Testcontainers.Builders;\nusing DotNet.Testcontainers.Containers;\n\nIContainer k6 = new ContainerBuilder()\n    .WithImage(\"grafana\u002Fk6:latest\")\n    .WithResourceMapping(\n        source: FilePath.Of(\"tests\u002Fload\u002Fscript.js\"),   \u002F\u002F copy from host into container\n        target: \"\u002Fscripts\u002Fscript.js\")\n    .WithEnvironment(\"BASE_URL\", \"http:\u002F\u002Fhost.docker.internal:5000\")\n    .WithOutputConsumer(Consume.RedirectStdoutAndStderrToConsole())\n    .WithWaitStrategy(Wait.ForUnixContainer().UntilContainerIsGone())\n    .WithCommand(\"run\", \"\u002Fscripts\u002Fscript.js\")\n    .Build();\n\nawait k6.StartAsync();          \u002F\u002F blocks until k6 exits\nint exitCode = await k6.GetExitCodeAsync();\nawait k6.DisposeAsync();\n\n\u002F\u002F exitCode 0 = pass; 99 = threshold fail\nAssert.That(exitCode, Is.EqualTo(0));\n```\n\n**Key rules**:\n- Use `WithResourceMapping` (not `WithBindMount`) — it is portable across host and CI environments.\n- `WithOutputConsumer(Consume.RedirectStdoutAndStderrToConsole())` streams k6 output in real time.\n- On Linux, pass `--add-host=host.docker.internal:host-gateway` via `.WithCreateParameterModifier(...)`.\n\n## CI: GitHub Actions — Native k6 (Recommended)\n\nUse `grafana\u002Fsetup-k6-action@v1` + `grafana\u002Frun-k6-action@v1`. **Do NOT use the archived `grafana\u002Fk6-action`** (deprecated July 2024).\n\n```yaml\nname: k6 Performance Tests\n\non:\n  push:\n    branches: [main]\n  pull_request:\n  schedule:\n    - cron: '0 2 * * *'\n\njobs:\n  k6-tests:\n    strategy:\n      matrix:\n        test-type: [smoke, load, stress]\n      fail-fast: false\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n\n      - name: Setup k6\n        uses: grafana\u002Fsetup-k6-action@v1\n        with:\n          k6-version: '0.56.0'  # pin for reproducibility\n\n      - name: Run k6 (${{ matrix.test-type }})\n        uses: grafana\u002Frun-k6-action@v1\n        with:\n          path: .\u002Ftests\u002Fload\u002F${{ matrix.test-type }}-test.js\n          flags: >-\n            --out json=results\u002Fk6-output.json\n            --env BASE_URL=${{ vars.API_BASE_URL }}\n            --summary-trend-stats=\"avg,min,med,max,p(90),p(95),p(99)\"\n          fail-fast: true\n\n      - name: Upload results\n        if: always()\n        uses: actions\u002Fupload-artifact@v4\n        with:\n          name: k6-results-${{ matrix.test-type }}\n          path: results\u002F\n          retention-days: 30\n```\n\n## CI: GitHub Actions — Docker-Based k6\n\nUse when you need a hermetic environment, custom xk6 extensions, or Docker Compose stack testing:\n\n```yaml\njobs:\n  k6-docker:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n\n      - name: Create results dir\n        run: mkdir -p results\n\n      - name: Run k6 in Docker\n        run: |\n          docker run --rm \\\n            -v \"$GITHUB_WORKSPACE\":\u002Fworkspace \\\n            -w \u002Fworkspace \\\n            -e BASE_URL=\"${{ vars.API_BASE_URL }}\" \\\n            -e API_KEY=\"${{ secrets.API_KEY }}\" \\\n            grafana\u002Fk6:0.56.0 run \\\n              --out json=results\u002Fk6-output.json \\\n              tests\u002Fload\u002Fload-test.js\n        # Exit code 99 (threshold fail) auto-fails the step\n\n      - name: Upload results\n        if: always()\n        uses: actions\u002Fupload-artifact@v4\n        with:\n          name: k6-docker-results\n          path: results\u002F\n          retention-days: 30\n```\n\n**Exit code 99 automatically fails the GitHub Actions step** — no extra configuration needed.\n\n## CI: Docker Compose Full-Stack (app + k6 + InfluxDB)\n\n```yaml\n# docker-compose.perf.yml\nversion: '3.4'\nnetworks:\n  perf:\n\nservices:\n  dotnet-api:\n    build: .\n    networks: [perf]\n    ports: [\"8080:8080\"]\n    healthcheck:\n      test: [\"CMD-SHELL\", \"wget -qO- http:\u002F\u002Flocalhost:8080\u002Fhealthz || exit 1\"]\n      interval: 10s\n      retries: 5\n      start_period: 30s\n      timeout: 5s\n\n  influxdb:\n    image: influxdb:1.12\n    networks: [perf]\n    environment: [INFLUXDB_DB=k6]\n\n  k6:\n    image: grafana\u002Fk6:latest\n    networks: [perf]\n    volumes: [\".\u002Ftests\u002Fload:\u002Fscripts\"]\n    command: run --out influxdb=http:\u002F\u002Finfluxdb:8086\u002Fk6 \u002Fscripts\u002Fload-test.js\n    depends_on:\n      dotnet-api:\n        condition: service_healthy  # k6 waits for API healthcheck to pass\n```\n\n**GitHub Actions step:**\n```yaml\n- name: Run full-stack load test\n  run: |\n    docker compose -f docker-compose.perf.yml up \\\n      --abort-on-container-exit \\\n      --exit-code-from k6 \\\n      --build\n```\n\n`--exit-code-from k6` forwards k6's exit code (99 on threshold failure) to the step.\n\n**ASP.NET Core healthcheck endpoint** (maps to `\u002Fhealthz`):\n```csharp\nbuilder.Services.AddHealthChecks();\napp.MapHealthChecks(\"\u002Fhealthz\");\n```\n\n## Recommended CLI Flags for CI Load Tests\n\n| Flag | When to use |\n|------|-------------|\n| `--discard-response-bodies` | **Always in CI** — reduces k6 container memory significantly and lowers GC pressure, producing more accurate latency measurements. Override per-request with `responseType: 'text'` where body is needed. |\n| `--no-connection-reuse` | Only when testing connection establishment overhead; do NOT use as default — distorts production-representative latency |\n| `--out json=\u002Foutput\u002Fraw.json` | When you need per-data-point time-series (InfluxDB, trend analysis). Expensive for long tests — compress with `.gz` extension |\n| `--summary-trend-stats=\"avg,min,med,max,p(90),p(95),p(99)\"` | Always — ensures CI artifacts contain all SLO-relevant percentiles |\n\n## Exit Code Reference\n\n| Code | Meaning | CI Action |\n|------|---------|-----------|\n| `0` | All thresholds passed | ✅ Pass |\n| `99` | **Threshold(s) failed** | ❌ Fail — SLO breach |\n| `100` | `setup()` timed out | ❌ Fail — infrastructure issue |\n| `101` | `teardown()` timed out | ❌ Fail — infrastructure issue |\n| `104` | Invalid config | ❌ Fail — fix script options |\n| `105` | SIGINT\u002FSIGTERM (user cancel) | ⚠️ Skip — not a test failure |\n| `107` | Script JS exception | ❌ Fail — fix the test script |\n| `108` | `test.abort()` called | ❌ Fail — controlled abort |\n\n## handleSummary() + Volume Mount (structured CI output)\n\n```javascript\nimport { textSummary } from 'https:\u002F\u002Fjslib.k6.io\u002Fk6-summary\u002F0.0.2\u002Findex.js';\n\nexport function handleSummary(data) {\n  return {\n    'stdout': textSummary(data, { indent: ' ', enableColors: false }),\n    '\u002Foutput\u002Fsummary.json': JSON.stringify(data),   \u002F\u002F → CI artifact via volume mount\n  };\n}\n```\n\nMount the output directory:\n```bash\ndocker run --rm -i \\\n  -v \"$PWD\u002Fresults\":\u002Foutput \\\n  -v \"$PWD\u002Fscripts\":\u002Fscripts \\\n  grafana\u002Fk6 run \u002Fscripts\u002Fload-test.js\n```\n\n`if: always()` on artifact upload ensures results are saved even on threshold failure (exit 99).\n\n## Distributed Execution: `--execution-segment`\n\nFor tests exceeding a single machine's capacity, split VUs\u002Fiterations across multiple containers:\n\n```bash\n# 4 parallel Docker containers sharing the full VU space\ndocker run grafana\u002Fk6 run \\\n  --execution-segment \"0:1\u002F4\" \\\n  --execution-segment-sequence \"0,1\u002F4,2\u002F4,3\u002F4,1\" \\\n  \u002Fscripts\u002Fload.js\n# (and 3 more containers with segments 1\u002F4:2\u002F4, 2\u002F4:3\u002F4, 3\u002F4:1)\n```\n\n**Note**: Each container produces independent metrics. Aggregate via shared InfluxDB\u002FPrometheus — there is no automatic aggregation across containers. For Kubernetes-native distributed execution with aggregation, use the k6 Operator (`grafana\u002Fk6-operator`).\n\n## Secrets Handling\n\n```yaml\n# GitHub Actions — pass secrets as Docker env vars (masked in logs automatically)\n- name: Run k6\n  run: |\n    docker run --rm -i \\\n      -e API_KEY=\"${{ secrets.API_KEY }}\" \\\n      -e BASE_URL=\"${{ vars.API_BASE_URL }}\" \\\n      grafana\u002Fk6 run - \u003C tests\u002Fload\u002Fload-test.js\n```\n\n**Never embed secrets in** `docker-compose.yml`, CLI command strings logged to stdout, or k6 script files. Use `-e KEY=VALUE` with GitHub Actions secrets — they are masked from CI logs.\n\nFor local dev, use a `.env` file (gitignored) with `docker run --env-file .env grafana\u002Fk6 ...`.\n\n## Sources\n- https:\u002F\u002Fgrafana.com\u002Fdocs\u002Fk6\u002Flatest\u002Fget-started\u002Frunning-k6\u002F — Official k6 Docker patterns\n- https:\u002F\u002Fhub.docker.com\u002Fr\u002Fgrafana\u002Fk6 — Docker Hub verified publisher image\n- https:\u002F\u002Fgithub.com\u002Fgrafana\u002Fxk6-output-influxdb — Official InfluxDB v2 compose stack\n- https:\u002F\u002Fgithub.com\u002Fgrafana\u002Frun-k6-action — run-k6-action v1 source\n- https:\u002F\u002Fgithub.com\u002Fgrafana\u002Fsetup-k6-action — setup-k6-action v1 source\n- https:\u002F\u002Fdocs.docker.com\u002Fai\u002Fmcp-catalog-and-toolkit\u002F — Docker MCP toolkit (confirms no container-run tool)\n- https:\u002F\u002Ftestcontainers.com\u002Fmodules\u002Fk6\u002F — Testcontainers K6 module (Java\u002FGo only; no .NET)\n- https:\u002F\u002Fgithub.com\u002Fgrafana\u002Fk6\u002Fblob\u002Fmaster\u002Ferrext\u002Fexitcodes\u002Fcodes.go — Exit code constants\n","# k6 Docker Execution\n\n## When to Use\nInvoke this skill when the question is **how to run k6 tests via Docker** — for either local development or CI automation. This skill is the execution-infrastructure complement to the k6 scripting skills:\n\n- Use `k6-performance-testing`, `k6-stress-testing`, `k6-load-testing` to write the test scripts and configure thresholds.\n- Use **this skill** to decide how to execute those scripts via Docker.\n\nTrigger scenarios:\n- \"How do I run my k6 script without installing k6 natively?\"\n- \"How do I run k6 in Docker Compose with InfluxDB + Grafana dashboards?\"\n- \"How do I run k6 from an AI agent session (Bash tool)?\"\n- \"How do I set up CI with Docker-based k6?\"\n- \"How do I run k6 programmatically from a .NET Testcontainers fixture?\"\n\n## Official Docker Image\n\n```bash\ndocker pull grafana\u002Fk6           # latest stable (recommended for CI — pin the tag)\ndocker pull grafana\u002Fk6:0.56.0    # pinned version (reproducible builds)\ndocker pull grafana\u002Fk6:latest-with-browser  # includes Chromium for k6 Browser API\n```\n\nImage: `grafana\u002Fk6` on Docker Hub (Verified Publisher). Alpine-based, non-root user (UID 12345).\n\n## Dev-Time: Running k6 in Docker Locally\n\n### Pattern A — stdin pipe (zero setup, fastest for quick runs)\n\n```bash\n# Linux \u002F macOS\ndocker run --rm -i grafana\u002Fk6 run - \u003C script.js\n\n# Windows (PowerShell)\ncat script.js | docker run --rm -i grafana\u002Fk6 run -\n\n# With VUs, duration, and env vars\ndocker run --rm -i \\\n  -e BASE_URL=http:\u002F\u002Fhost.docker.internal:5000 \\\n  grafana\u002Fk6 run --vus 10 --duration 30s - \u003C script.js\n```\n\n### Pattern B — volume mount (for multi-file projects with test data)\n\n```bash\n# Linux \u002F macOS\ndocker run --rm -i \\\n  -v \"$PWD\":\u002Fscripts \\\n  -w \u002Fscripts \\\n  grafana\u002Fk6 run script.js\n\n# Windows (PowerShell)\ndocker run --rm -i `\n  -v \"${PWD}:\u002Fscripts\" `\n  -w \u002Fscripts `\n  grafana\u002Fk6 run script.js\n```\n\n### Reaching the Host's ASP.NET Core API from the Container\n\nThe k6 container cannot reach `localhost` on the host directly — use these patterns:\n\n| Platform | Hostname | Extra Docker Flag |\n|----------|----------|-------------------|\n| Docker Desktop (Windows \u002F macOS) | `host.docker.internal` | None — resolved automatically |\n| Docker Engine on Linux | `host.docker.internal` | `--add-host=host.docker.internal:host-gateway` |\n| Docker Engine on Linux (alt) | `172.17.0.1` | None (default bridge gateway IP) |\n\n```bash\n# Linux Docker Engine\ndocker run --rm -i \\\n  --add-host=host.docker.internal:host-gateway \\\n  -e BASE_URL=http:\u002F\u002Fhost.docker.internal:5000 \\\n  grafana\u002Fk6 run - \u003C script.js\n```\n\nIn the k6 script:\n```javascript\nconst res = http.get(`${__ENV.BASE_URL}\u002Fapi\u002Fhealth`);\n```\n\n## Dev-Time: AI Agent Session (Bash Tool)\n\n**Docker MCP cannot spawn arbitrary containers.** The MCP Gateway only manages MCP server lifecycle (mcp-find, mcp-add, mcp-remove). There is no `container-run` or `docker-exec` primordial tool. The `poci`-type docker tool in mcp-registry is unconfirmed\u002Fexperimental.\n\n**Use the `Bash` tool instead** — both Claude Code and GitHub Copilot run in the host environment with full Docker daemon access:\n\n```bash\n# Run k6 and capture summary output (synchronous — blocks until k6 exits)\ndocker run --rm -i \\\n  --add-host=host.docker.internal:host-gateway \\\n  -v \"$PWD\u002Ftests\u002Fload\":\u002Fscripts \\\n  -e BASE_URL=http:\u002F\u002Fhost.docker.internal:5000 \\\n  grafana\u002Fk6 run \u002Fscripts\u002Fload-test.js\n# k6 text summary prints to stdout — agent reads it directly\n```\n\n**Parsing results from the agent**: k6 prints pass\u002Ffail thresholds as `✓` \u002F `✗` in stdout. The agent can detect threshold results from the text summary without any JSON parsing. For structured parsing, use `handleSummary()`:\n\n```javascript\nexport function handleSummary(data) {\n  return { 'stdout': JSON.stringify(data) }; \u002F\u002F agent receives structured JSON\n}\n```\n\n**Exit code interpretation**:\n- `0` — all thresholds passed → performance is acceptable\n- `99` — threshold breached → report SLO violation to the user\n- `107` — script error → fix the test script\n\n## Dev-Time: Local Observability Stack (Docker Compose + InfluxDB v1 + Grafana)\n\nUse the built-in InfluxDB v1 output (no custom k6 build required):\n\n```yaml\n# docker-compose.observability.yml\nversion: '3.4'\n\nnetworks:\n  grafana:\n\nservices:\n  influxdb:\n    image: influxdb:1.12\n    networks: [grafana]\n    ports: [\"8086:8086\"]\n    environment:\n      - INFLUXDB_DB=k6\n\n  grafana:\n    image: grafana\u002Fgrafana:9.5.21\n    networks: [grafana]\n    ports: [\"3000:3000\"]\n    environment:\n      - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin\n      - GF_AUTH_ANONYMOUS_ENABLED=true\n      - GF_AUTH_BASIC_ENABLED=false\n    volumes:\n      - .\u002Fgrafana:\u002Fetc\u002Fgrafana\u002Fprovisioning\u002F  # auto-provisions datasource + dashboard\n\n  k6:\n    image: grafana\u002Fk6\n    networks: [grafana]\n    volumes:\n      - .\u002Ftests\u002Fload:\u002Fscripts\n```\n\n**Run a test and stream to InfluxDB**:\n```bash\ndocker compose -f docker-compose.observability.yml run --rm -T k6 run \\\n  --out influxdb=http:\u002F\u002Finfluxdb:8086\u002Fk6 \\\n  \u002Fscripts\u002Fload-test.js\n```\n\n**Open the dashboard**: `http:\u002F\u002Flocalhost:3000\u002Fd\u002FLe2Ku9NMk\u002Fk6-performance-test`\n\nAlternatively import Grafana community dashboard **ID 2587** (\"k6 Load Testing Results\") via Grafana → Dashboards → Import → ID `2587`.\n\n### Advanced: InfluxDB v2 + Grafana (requires custom k6 build)\n\nInfluxDB v2 output is NOT in the stock `grafana\u002Fk6` image. Use the official `grafana\u002Fxk6-output-influxdb` repo (includes a `Dockerfile` and `docker-compose.yml` with pre-provisioned dashboards):\n\n```\nhttps:\u002F\u002Fgithub.com\u002Fgrafana\u002Fxk6-output-influxdb\n```\n\n## Dev-Time: Programmatic k6 from .NET (Testcontainers)\n\n**There is no official `Testcontainers.K6` NuGet package** (confirmed: zero results on NuGet, May 2026). Use the generic `ContainerBuilder` API:\n\n```csharp\n\u002F\u002F NuGet: Testcontainers (v3.x)\nusing DotNet.Testcontainers.Builders;\nusing DotNet.Testcontainers.Containers;\n\nIContainer k6 = new ContainerBuilder()\n    .WithImage(\"grafana\u002Fk6:latest\")\n    .WithResourceMapping(\n        source: FilePath.Of(\"tests\u002Fload\u002Fscript.js\"),   \u002F\u002F copy from host into container\n        target: \"\u002Fscripts\u002Fscript.js\")\n    .WithEnvironment(\"BASE_URL\", \"http:\u002F\u002Fhost.docker.internal:5000\")\n    .WithOutputConsumer(Consume.RedirectStdoutAndStderrToConsole())\n    .WithWaitStrategy(Wait.ForUnixContainer().UntilContainerIsGone())\n    .WithCommand(\"run\", \"\u002Fscripts\u002Fscript.js\")\n    .Build();\n\nawait k6.StartAsync();          \u002F\u002F blocks until k6 exits\nint exitCode = await k6.GetExitCodeAsync();\nawait k6.DisposeAsync();\n\n\u002F\u002F exitCode 0 = pass; 99 = threshold fail\nAssert.That(exitCode, Is.EqualTo(0));\n```\n\n**Key rules**:\n- Use `WithResourceMapping` (not `WithBindMount`) — it is portable across host and CI environments.\n- `WithOutputConsumer(Consume.RedirectStdoutAndStderrToConsole())` streams k6 output in real time.\n- On Linux, pass `--add-host=host.docker.internal:host-gateway` via `.WithCreateParameterModifier(...)`.\n\n## CI: GitHub Actions — Native k6 (Recommended)\n\nUse `grafana\u002Fsetup-k6-action@v1` + `grafana\u002Frun-k6-action@v1`. **Do NOT use the archived `grafana\u002Fk6-action`** (deprecated July 2024).\n\n```yaml\nname: k6 Performance Tests\n\non:\n  push:\n    branches: [main]\n  pull_request:\n  schedule:\n    - cron: '0 2 * * *'\n\njobs:\n  k6-tests:\n    strategy:\n      matrix:\n        test-type: [smoke, load, stress]\n      fail-fast: false\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n\n      - name: Setup k6\n        uses: grafana\u002Fsetup-k6-action@v1\n        with:\n          k6-version: '0.56.0'  # pin for reproducibility\n\n      - name: Run k6 (${{ matrix.test-type }})\n        uses: grafana\u002Frun-k6-action@v1\n        with:\n          path: .\u002Ftests\u002Fload\u002F${{ matrix.test-type }}-test.js\n          flags: >-\n            --out json=results\u002Fk6-output.json\n            --env BASE_URL=${{ vars.API_BASE_URL }}\n            --summary-trend-stats=\"avg,min,med,max,p(90),p(95),p(99)\"\n          fail-fast: true\n\n      - name: Upload results\n        if: always()\n        uses: actions\u002Fupload-artifact@v4\n        with:\n          name: k6-results-${{ matrix.test-type }}\n          path: results\u002F\n          retention-days: 30\n```\n\n## CI: GitHub Actions — Docker-Based k6\n\nUse when you need a hermetic environment, custom xk6 extensions, or Docker Compose stack testing:\n\n```yaml\njobs:\n  k6-docker:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n\n      - name: Create results dir\n        run: mkdir -p results\n\n      - name: Run k6 in Docker\n        run: |\n          docker run --rm \\\n            -v \"$GITHUB_WORKSPACE\":\u002Fworkspace \\\n            -w \u002Fworkspace \\\n            -e BASE_URL=\"${{ vars.API_BASE_URL }}\" \\\n            -e API_KEY=\"${{ secrets.API_KEY }}\" \\\n            grafana\u002Fk6:0.56.0 run \\\n              --out json=results\u002Fk6-output.json \\\n              tests\u002Fload\u002Fload-test.js\n        # Exit code 99 (threshold fail) auto-fails the step\n\n      - name: Upload results\n        if: always()\n        uses: actions\u002Fupload-artifact@v4\n        with:\n          name: k6-docker-results\n          path: results\u002F\n          retention-days: 30\n```\n\n**Exit code 99 automatically fails the GitHub Actions step** — no extra configuration needed.\n\n## CI: Docker Compose Full-Stack (app + k6 + InfluxDB)\n\n```yaml\n# docker-compose.perf.yml\nversion: '3.4'\nnetworks:\n  perf:\n\nservices:\n  dotnet-api:\n    build: .\n    networks: [perf]\n    ports: [\"8080:8080\"]\n    healthcheck:\n      test: [\"CMD-SHELL\", \"wget -qO- http:\u002F\u002Flocalhost:8080\u002Fhealthz || exit 1\"]\n      interval: 10s\n      retries: 5\n      start_period: 30s\n      timeout: 5s\n\n  influxdb:\n    image: influxdb:1.12\n    networks: [perf]\n    environment: [INFLUXDB_DB=k6]\n\n  k6:\n    image: grafana\u002Fk6:latest\n    networks: [perf]\n    volumes: [\".\u002Ftests\u002Fload:\u002Fscripts\"]\n    command: run --out influxdb=http:\u002F\u002Finfluxdb:8086\u002Fk6 \u002Fscripts\u002Fload-test.js\n    depends_on:\n      dotnet-api:\n        condition: service_healthy  # k6 waits for API healthcheck to pass\n```\n\n**GitHub Actions step:**\n```yaml\n- name: Run full-stack load test\n  run: |\n    docker compose -f docker-compose.perf.yml up \\\n      --abort-on-container-exit \\\n      --exit-code-from k6 \\\n      --build\n```\n\n`--exit-code-from k6` forwards k6's exit code (99 on threshold failure) to the step.\n\n**ASP.NET Core healthcheck endpoint** (maps to `\u002Fhealthz`):\n```csharp\nbuilder.Services.AddHealthChecks();\napp.MapHealthChecks(\"\u002Fhealthz\");\n```\n\n## Recommended CLI Flags for CI Load Tests\n\n| Flag | When to use |\n|------|-------------|\n| `--discard-response-bodies` | **Always in CI** — reduces k6 container memory significantly and lowers GC pressure, producing more accurate latency measurements. Override per-request with `responseType: 'text'` where body is needed. |\n| `--no-connection-reuse` | Only when testing connection establishment overhead; do NOT use as default — distorts production-representative latency |\n| `--out json=\u002Foutput\u002Fraw.json` | When you need per-data-point time-series (InfluxDB, trend analysis). Expensive for long tests — compress with `.gz` extension |\n| `--summary-trend-stats=\"avg,min,med,max,p(90),p(95),p(99)\"` | Always — ensures CI artifacts contain all SLO-relevant percentiles |\n\n## Exit Code Reference\n\n| Code | Meaning | CI Action |\n|------|---------|-----------|\n| `0` | All thresholds passed | ✅ Pass |\n| `99` | **Threshold(s) failed** | ❌ Fail — SLO breach |\n| `100` | `setup()` timed out | ❌ Fail — infrastructure issue |\n| `101` | `teardown()` timed out | ❌ Fail — infrastructure issue |\n| `104` | Invalid config | ❌ Fail — fix script options |\n| `105` | SIGINT\u002FSIGTERM (user cancel) | ⚠️ Skip — not a test failure |\n| `107` | Script JS exception | ❌ Fail — fix the test script |\n| `108` | `test.abort()` called | ❌ Fail — controlled abort |\n\n## handleSummary() + Volume Mount (structured CI output)\n\n```javascript\nimport { textSummary } from 'https:\u002F\u002Fjslib.k6.io\u002Fk6-summary\u002F0.0.2\u002Findex.js';\n\nexport function handleSummary(data) {\n  return {\n    'stdout': textSummary(data, { indent: ' ', enableColors: false }),\n    '\u002Foutput\u002Fsummary.json': JSON.stringify(data),   \u002F\u002F → CI artifact via volume mount\n  };\n}\n```\n\nMount the output directory:\n```bash\ndocker run --rm -i \\\n  -v \"$PWD\u002Fresults\":\u002Foutput \\\n  -v \"$PWD\u002Fscripts\":\u002Fscripts \\\n  grafana\u002Fk6 run \u002Fscripts\u002Fload-test.js\n```\n\n`if: always()` on artifact upload ensures results are saved even on threshold failure (exit 99).\n\n## Distributed Execution: `--execution-segment`\n\nFor tests exceeding a single machine's capacity, split VUs\u002Fiterations across multiple containers:\n\n```bash\n# 4 parallel Docker containers sharing the full VU space\ndocker run grafana\u002Fk6 run \\\n  --execution-segment \"0:1\u002F4\" \\\n  --execution-segment-sequence \"0,1\u002F4,2\u002F4,3\u002F4,1\" \\\n  \u002Fscripts\u002Fload.js\n# (and 3 more containers with segments 1\u002F4:2\u002F4, 2\u002F4:3\u002F4, 3\u002F4:1)\n```\n\n**Note**: Each container produces independent metrics. Aggregate via shared InfluxDB\u002FPrometheus — there is no automatic aggregation across containers. For Kubernetes-native distributed execution with aggregation, use the k6 Operator (`grafana\u002Fk6-operator`).\n\n## Secrets Handling\n\n```yaml\n# GitHub Actions — pass secrets as Docker env vars (masked in logs automatically)\n- name: Run k6\n  run: |\n    docker run --rm -i \\\n      -e API_KEY=\"${{ secrets.API_KEY }}\" \\\n      -e BASE_URL=\"${{ vars.API_BASE_URL }}\" \\\n      grafana\u002Fk6 run - \u003C tests\u002Fload\u002Fload-test.js\n```\n\n**Never embed secrets in** `docker-compose.yml`, CLI command strings logged to stdout, or k6 script files. Use `-e KEY=VALUE` with GitHub Actions secrets — they are masked from CI logs.\n\nFor local dev, use a `.env` file (gitignored) with `docker run --env-file .env grafana\u002Fk6 ...`.\n\n## Sources\n- https:\u002F\u002Fgrafana.com\u002Fdocs\u002Fk6\u002Flatest\u002Fget-started\u002Frunning-k6\u002F — Official k6 Docker patterns\n- https:\u002F\u002Fhub.docker.com\u002Fr\u002Fgrafana\u002Fk6 — Docker Hub verified publisher image\n- https:\u002F\u002Fgithub.com\u002Fgrafana\u002Fxk6-output-influxdb — Official InfluxDB v2 compose stack\n- https:\u002F\u002Fgithub.com\u002Fgrafana\u002Frun-k6-action — run-k6-action v1 source\n- https:\u002F\u002Fgithub.com\u002Fgrafana\u002Fsetup-k6-action — setup-k6-action v1 source\n- https:\u002F\u002Fdocs.docker.com\u002Fai\u002Fmcp-catalog-and-toolkit\u002F — Docker MCP toolkit (confirms no container-run tool)\n- https:\u002F\u002Ftestcontainers.com\u002Fmodules\u002Fk6\u002F — Testcontainers K6 module (Java\u002FGo only; no .NET)\n- https:\u002F\u002Fgithub.com\u002Fgrafana\u002Fk6\u002Fblob\u002Fmaster\u002Ferrext\u002Fexitcodes\u002Fcodes.go — Exit code constants\n",{"name":5,"description":7},"main","00b2c68281930728ee390bb16cec32b88d2caac7",".claude\u002Fskills\u002Fk6-docker","https:\u002F\u002Fgithub.com\u002Frafsanulhasan\u002FHypermediaEngine","https:\u002F\u002Fgithub.com\u002Frafsanulhasan","\r\n    MCSD || A-CSD || Software Architect\r\n\r\n","2026-06-06 07:47:06",{"source":8,"skillName":5,"commands":59,"prompt":69,"zipAvailable":70},[60,63,66],{"tool":61,"command":62},"npx","npx skills add rafsanulhasan\u002FHypermediaEngine --skill k6-docker",{"tool":64,"command":65},"bunx","bunx skills add rafsanulhasan\u002FHypermediaEngine --skill k6-docker",{"tool":67,"command":68},"pnpm","pnpm dlx skills add rafsanulhasan\u002FHypermediaEngine --skill k6-docker","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Frafsanulhasan\u002FHypermediaEngine\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fk6-docker\u002FSKILL.md",true,[],[73,101,121,140,168,189],{"skillNo":74,"name":75,"nameZh":6,"description":76,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":82,"publishedAt":46},"01M6KWEJD606FG3DBBRM0W4DKW","write-tests","Test implementation skill for HypermediaEngine. Takes a confirmed test plan from design-test-cases and produces compilable, runnable xUnit tests following project conventions. Validates coverage quality through mutation testing. Invoked by the sqa-engineer agent after the test plan is approved.","https:\u002F\u002Fgithub.com\u002Frafsanulhasan\u002FHypermediaEngine\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fwrite-tests\u002FSKILL.md",[79],{"categoryNo":80,"categoryName":81,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",[83,84,35,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,31],"write tests","write","testing","design","test","project conventions","test plan","Bash","plan","quality","xunit","read","edit","coverage","engineer","mutation testing","project","mutation",{"skillNo":102,"name":103,"nameZh":6,"description":104,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":105,"categories":106,"keywords":107,"publishedAt":46},"01M6KWEF2XQ00C1Y6QCK7YHZ1H","write-documentation","Structured documentation writing workflow for HypermediaEngine. Writes or updates README.md files at the repo root and in each project directory (src\u002F, tests\u002F, samples\u002F, etc.) based on current implementation, ADRs, and architecture decisions.","https:\u002F\u002Fgithub.com\u002Frafsanulhasan\u002FHypermediaEngine\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fwrite-documentation\u002FSKILL.md",[],[108,84,109,110,111,112,113,90,114,115,116,117,94,95,118,99,35,119,120,31],"documentation","write documentation","writing","directory","workflow","architecture","src","repo","decisions","README","files","updates","at",{"skillNo":122,"name":123,"nameZh":6,"description":124,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":125,"categories":126,"keywords":127,"publishedAt":46},"01M6KWEBDXTXAVPQ3BHS3YYYNT","write-adr","Writes a numbered Architecture Decision Record (ADR) for a significant architectural choice in the HypermediaEngine project. Invoked by the software-architect agent whenever a consequential design decision is made or ratified. Saves the ADR to docs\u002Farchitecture\u002Fdecisions\u002F.","https:\u002F\u002Fgithub.com\u002Frafsanulhasan\u002FHypermediaEngine\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fwrite-adr\u002FSKILL.md",[],[128,84,129,86,130,113,131,132,133,134,116,94,135,136,99,137,138,31,139],"adr","write adr","docs","architect","decision","choice","grep","architecture decision record","record","software","opus","architecture decision",{"skillNo":141,"name":142,"nameZh":6,"description":143,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":144,"categories":145,"keywords":152,"publishedAt":46},"01M6KWE76TM3QHGQ08PEB3KY6D","tunit-playwright-ui-testing","Comprehensive guidance for writing coded end-to-end UI tests in C# using TUnit.Playwright. Tests inherit from PageTest — the base class manages all browser lifecycle. Covers NuGet setup, PageTest inheritance, Page Object Model, browser configuration, parallelism limiting, and CI integration. Based on the official TUnit docs at https:\u002F\u002Ftunit.dev\u002Fdocs\u002Fexamples\u002Fplaywright.","https:\u002F\u002Fgithub.com\u002Frafsanulhasan\u002FHypermediaEngine\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Ftunit-playwright-ui-testing\u002FSKILL.md",[146,147],{"categoryNo":80,"categoryName":81,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":148,"categoryName":149,"taxonomyType":150,"taxonomyTypeDesc":151},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[85,153,154,155,156,157,158,110,159,160,161,41,162,163,164,165,35,166,167,31],"playwright","ui","playwright ui testing","ui testing","tunit","tunit playwright ui testing","official","dev","examples","lifecycle","model","page","inheritance","end","object",{"skillNo":169,"name":170,"nameZh":6,"description":171,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":172,"categories":173,"keywords":175,"publishedAt":46},"01M6KWE44A738GDK65QS02XJBG","triage","Task classification, decomposition, dependency mapping, and routing skill. Invoked by the triage-agent to break any user request into discrete, independently-routable work items with assigned priorities and agent chains.","https:\u002F\u002Fgithub.com\u002Frafsanulhasan\u002FHypermediaEngine\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Ftriage\u002FSKILL.md",[174],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[170,176,177,178,179,180,181,182,183,184,185,186,187,188],"routing","classification","work","user","dependency","task","priorities","decomposition","user request","mapping","with","break","request",{"skillNo":190,"name":191,"nameZh":6,"description":192,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":193,"categories":194,"keywords":199,"publishedAt":46},"01M6KWDZ3W9ZKPR7FTTTSX8H2K","system-design","Expert system design skill. Use PROACTIVELY to design systems, review architectures, and assist software engineers in learning design principles and implementing them in the code with design patterns.","https:\u002F\u002Fgithub.com\u002Frafsanulhasan\u002FHypermediaEngine\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fsystem-design\u002FSKILL.md",[195,198],{"categoryNo":196,"categoryName":197,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":148,"categoryName":149,"taxonomyType":150,"taxonomyTypeDesc":151},[86,200,201,202,203,204,205,134,94,206,207,208,209,210,211,137,212,213,186,214],"system","system design","web","design systems","learning","haiku","use","design patterns","design principles","expert","patterns","systems","architectures","principles","implementing"]