Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
title: The Arm migration challenge and how Docker MCP Toolkit solves it
weight: 2

### FIXED, DO NOT MODIFY
layout: learningpathall
---

## Why migrate to Arm?

Moving workloads from x86 to Arm64 has become a priority for organizations looking to reduce cloud costs and improve performance. AWS Graviton, Azure Cobalt, and Google Cloud Axion have made Arm-based computing mainstream, offering 20-40% cost savings and improved performance-per-watt for many workloads.

The challenge is that migration is not always straightforward. For most containerized applications, rebuilding a Docker image for Arm64 is enough. But when you encounter legacy applications with hand-optimized x86 assembly, AVX2 intrinsics, or architecture-specific compiler flags, the migration becomes significantly more complex.

## What makes x86-to-Arm migration hard?

Traditional migration approaches require:

- Manual code analysis for x86-specific dependencies.
- Tedious compatibility checks across multiple tools.
- Researching Arm NEON equivalents for each x86 intrinsic.
- Rewriting vectorized code and adjusting loop structures.
- Updating Dockerfiles, base images, and compiler flags.
- Debugging compilation errors on the new architecture.

For a single application with SIMD-optimized code, this can take 5-7 hours of manual work.

## What the Docker MCP Toolkit provides

The Docker MCP Toolkit is a management interface in Docker Desktop that lets you discover, configure, and run containerized MCP (Model Context Protocol) servers. It connects these servers to AI coding assistants through a unified gateway.

For Arm migration, three MCP servers work together:

- **Arm MCP Server**: Provides code scanning (`migrate_ease_scan`), Docker image architecture checking (`check_image`, `skopeo`), Arm knowledge base search (`knowledge_base_search`), and assembly performance analysis (`mca`).
- **GitHub MCP Server**: Enables repository operations including creating pull requests, managing branches, and committing changes.
- **Sequential Thinking MCP Server**: Helps the AI assistant break down complex migration decisions into logical steps.

## How AI-assisted migration works

When connected to the Docker MCP Toolkit, an AI coding assistant like GitHub Copilot can execute the entire migration workflow:

1. Use `check_image` or `skopeo` to verify if base images support `linux/arm64`.
2. Run `migrate_ease_scan` on the codebase to find x86-specific code, intrinsics, and compiler flags.
3. Use `knowledge_base_search` to find correct Arm SIMD equivalents for every x86 intrinsic.
4. Convert the code with architecture-specific accuracy.
5. Update the Dockerfile with Arm-compatible base images and compiler flags.
6. Create a pull request with all changes using the GitHub MCP Server.

What normally takes 5-7 hours of manual work takes about 25-30 minutes.

## What you will build in this Learning Path

In this Learning Path, you will migrate a real-world legacy application - a matrix multiplication benchmark written with AVX2 intrinsics for x86 - to Arm64 using GitHub Copilot and Docker MCP Toolkit.

The demo repository is available at [github.com/JoeStech/docker-blog-arm-migration](https://github.com/JoeStech/docker-blog-arm-migration).

You will:

1. Set up Docker MCP Toolkit with the Arm, GitHub, and Sequential Thinking MCP servers.
2. Connect VS Code with GitHub Copilot to the MCP Gateway.
3. Analyze the legacy x86 codebase to understand what blocks Arm migration.
4. Use AI-driven tools to automate the full migration.
5. Review the pull request created by the AI agent.

In the next section, you will install and configure the Docker MCP Toolkit.
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
title: Set up Docker MCP Toolkit with Arm, GitHub, and Sequential Thinking servers
weight: 3

### FIXED, DO NOT MODIFY
layout: learningpathall
---

## Before you begin

You need:

- Docker Desktop 4.59 or later.
- VS Code with the GitHub Copilot extension.
- A GitHub account with a personal access token.
- A machine with at least 8 GB RAM (16 GB recommended).

## Enable the Docker MCP Toolkit

1. Open Docker Desktop.
2. Go to **Settings** > **Beta features**.
3. Toggle **Enable Docker MCP Toolkit** on.
4. Click **Apply**.

After a few seconds, the **MCP Toolkit** tab appears in the left sidebar.

## Add the required MCP servers

Open the **MCP Toolkit** in Docker Desktop and select the **Catalog** tab. Add the following three servers:

### Arm MCP Server

Search for **Arm** in the catalog and add the [Arm MCP Server](https://hub.docker.com/mcp/server/arm-mcp/overview).

Configure it by setting the directory path to your local code. This allows the `migrate_ease_scan` and `mca` tools to access your source files. Click **Save** after setting the path.

The Arm MCP Server provides six tools:

| Tool | Description |
|------|-------------|
| `knowledge_base_search` | Semantic search of Arm learning resources, intrinsics documentation, and software compatibility |
| `migrate_ease_scan` | Code scanner for C++, Python, Go, JavaScript, and Java Arm compatibility analysis |
| `check_image` | Docker image architecture verification for Arm64 support |
| `skopeo` | Remote container image inspection without downloading |
| `mca` | Machine Code Analyzer for assembly performance and IPC predictions |
| `sysreport_instructions` | System architecture information gathering |

### GitHub Official MCP Server

Search for **GitHub Official** in the catalog and add the [GitHub MCP Server](https://hub.docker.com/mcp/server/github-official/overview).

Configure authentication:

1. Select the GitHub Official server.
2. Choose **Personal Access Token** as the authentication method.
3. Enter your GitHub token from **GitHub Settings** > **Developer Settings** > **Personal access tokens**.

This server lets GitHub Copilot create pull requests, manage issues, and commit changes directly to your repositories.

### Sequential Thinking MCP Server

Search for **Sequential Thinking** in the catalog and add the [Sequential Thinking MCP Server](https://hub.docker.com/mcp/server/sequentialthinking/overview).

No configuration is needed. This server helps GitHub Copilot break down complex migration decisions into logical steps.

## Connect VS Code to the MCP Gateway

1. In Docker Desktop, go to **MCP Toolkit** > **Clients** tab.
2. Scroll to **Visual Studio Code** and click **Connect**.
3. Open VS Code and click the **Extensions** icon in the left toolbar.
4. Find **MCP_DOCKER**, click the gear icon, and click **Start Server**.

## Verify the connection

Open GitHub Copilot Chat in VS Code and ask:

```text
What Arm migration tools do you have access to?
```

You should see tools from all three servers listed. If they appear, your setup is complete.

In the next section, you will examine the demo application to understand what blocks its migration to Arm64.
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
title: Understand the legacy x86 demo application
weight: 4

### FIXED, DO NOT MODIFY
layout: learningpathall
---

## Clone the demo repository

The demo application is a matrix multiplication benchmark written in C++ with AVX2 intrinsics. Clone it:

```bash
git clone https://github.com/JoeStech/docker-blog-arm-migration
cd docker-blog-arm-migration
```

## Examine the Dockerfile

Open the `Dockerfile`. There are two immediate blockers for Arm migration:

**No Arm64 support in the base image**: The `centos:6` image was built for x86 only. This container will not start on Arm hardware.

**x86-specific compiler flag**: The `-mavx2` flag tells the compiler to use AVX2 vector instructions, which do not exist on Arm processors.

```dockerfile
FROM centos:6

RUN yum install -y \
devtoolset-2-gcc \
devtoolset-2-gcc-c++ \
devtoolset-2-binutils \
make \
&& yum clean all

WORKDIR /app
COPY *.h *.cpp ./

RUN scl enable devtoolset-2 "g++ -O2 -mavx2 -o benchmark \
main.cpp \
matrix_operations.cpp \
-std=c++11"

CMD ["./benchmark"]
```

## Examine the source code

Open `matrix_operations.cpp`. The code uses x86 AVX2 intrinsics throughout:

```cpp
#include <immintrin.h> // x86-only header

// Inside the multiply function:
__m256d sum_vec = _mm256_setzero_pd();
__m256d a_vec = _mm256_loadu_pd(&data[i][k]);
sum_vec = _mm256_add_pd(sum_vec, _mm256_mul_pd(a_vec, b_vec));

// Horizontal reduction
__m128d sum_high = _mm256_extractf128_pd(sum_vec, 1);
__m128d sum_low = _mm256_castpd256_pd128(sum_vec);
```

## Why this code cannot run on Arm

There are several specific blockers:

1. **x86-exclusive header**: `#include <immintrin.h>` only exists on x86 systems. Arm uses `<arm_neon.h>` instead.

2. **AVX2 intrinsics throughout**: Every `_mm256_*` function is Intel-specific:
- `_mm256_setzero_pd()` creates a 256-bit zero vector (Arm NEON is 128-bit).
- `_mm256_loadu_pd()` loads 4 doubles at once (NEON loads 2 with `vld1q_f64`).
- `_mm256_add_pd()` and `_mm256_mul_pd()` are 256-bit operations (NEON uses 128-bit equivalents).
- `_mm256_extractf128_pd()` extracts the high 128 bits (not needed on NEON).

3. **Vector width mismatch**: AVX2 processes 4 doubles per operation. Arm NEON processes 2 doubles per operation. The entire loop structure needs adjustment.

{{% notice Note %}}
SVE/SVE2 on newer Arm cores (Neoverse V1/V2, Graviton 3/4) provides 256-bit or wider vector-length agnostic (VLA) registers, matching or exceeding AVX2 width. The Arm MCP Server knowledge base can help determine the best approach for your target hardware.
{{% /notice %}}

4. **Horizontal reduction logic**: The pattern using `_mm256_extractf128_pd` and `_mm256_castpd256_pd128` is x86-specific and must be completely rewritten.

Manual conversion requires rewriting 30+ lines of intrinsic code, adjusting loop strides, and testing numerical accuracy. This is exactly where the Docker MCP Toolkit with the Arm MCP Server becomes essential.

In the next section, you will use GitHub Copilot with the Docker MCP Toolkit to automate the entire migration.
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
---
title: Run the AI-driven Arm migration
weight: 5

### FIXED, DO NOT MODIFY
layout: learningpathall
---

## Open the project in VS Code

Open the cloned `docker-blog-arm-migration` directory in VS Code:

```bash
cd docker-blog-arm-migration
code .
```

Make sure the MCP_DOCKER server is running in VS Code (check **Extensions** > **MCP_DOCKER** > **Start Server** if needed).

## Give GitHub Copilot migration instructions

Open GitHub Copilot Chat in VS Code and paste the following prompt:

```text
Your goal is to migrate this codebase from x86 to Arm64. Use the Arm MCP
Server tools to help you with this migration.

Steps to follow:
1. Check all Dockerfiles - use check_image and/or skopeo tools to verify
Arm compatibility, changing the base image if necessary
2. Scan the codebase - run migrate_ease_scan with the appropriate language
scanner and apply the suggested changes
3. Use knowledge_base_search when you need Arm architecture guidance or
intrinsic equivalents
4. Update compiler flags and dependencies for Arm64 compatibility
5. Create a pull request with all changes using GitHub MCP Server

Important notes:
- Your current working directory is mapped to /workspace on the MCP server
- NEON lane indices must be compile-time constants, not variables
- If unsure about Arm equivalents, use knowledge_base_search to find docs
- Be sure to find out from the user or system what the target machine is,
and use the appropriate intrinsics. For instance, if neoverse (Graviton,
Axion, Cobalt) is targeted, use the latest SME/SME2.

After completing the migration:
- Create a pull request with a detailed description of changes
- Include performance predictions and cost savings in the PR description
- List all tools used and validation steps needed
```

## Watch the migration execute

GitHub Copilot orchestrates the migration through four phases using the Docker MCP Toolkit.

### Phase 1: Image analysis

Copilot uses the `skopeo` tool from the Arm MCP Server to analyze the base image:

```text
Checking centos:6 for arm64 support...
```

The tool reports that `centos:6` has no `linux/arm64` build available. This is the first blocker identified. Copilot determines that the base image must be replaced.

### Phase 2: Code scanning

Copilot runs the `migrate_ease_scan` tool with the C++ scanner:

```text
Running migrate_ease_scan with scanner: cpp
```

The scan detects:

- AVX2 intrinsics (`_mm256_*` functions) in `matrix_operations.cpp`.
- The `-mavx2` compiler flag in the Dockerfile.
- The x86-specific header `<immintrin.h>`.

Each issue includes the file location, line number, and specific code requiring modification.

### Phase 3: Knowledge base lookup and code conversion

For each x86 intrinsic found, Copilot queries the Arm MCP Server knowledge base:

```text
Searching knowledge base for: AVX2 to NEON intrinsic conversion
```

The knowledge base returns Arm documentation with the conversions:

| x86 AVX2 Intrinsic | Arm NEON Equivalent |
|---------------------|---------------------|
| `_mm256_setzero_pd()` | Two `vdupq_n_f64(0.0)` operations |
| `_mm256_loadu_pd()` | Two `vld1q_f64()` loads |
| `_mm256_add_pd()` | Two `vaddq_f64()` operations |
| `_mm256_mul_pd()` | Two `vmulq_f64()` operations |

The knowledge base also explains that AVX2 uses 256-bit vectors processing 4 doubles at once, while NEON uses 128-bit vectors processing 2 doubles. Loop strides must be adjusted accordingly.

Copilot rewrites the code using this information:

- Replaces `<immintrin.h>` with `<arm_neon.h>` inside `#ifdef __aarch64__` guards.
- Converts the AVX2 loop structure (stride 4) to NEON (stride 2).
- Rewrites the horizontal reduction for NEON.
- Updates the Dockerfile to use `ubuntu:22.04` with `TARGETARCH` for multi-arch builds.
- Changes the compiler flag from `-mavx2` to `-march=armv8-a+simd`.

### Phase 4: Create the pull request

Copilot uses the GitHub MCP Server to create a pull request with:

- All code changes (source files and Dockerfile).
- A detailed description of what was changed and why.
- Performance predictions for Arm.
- A list of all MCP tools used during the migration.

You can see an example PR at [github.com/JoeStech/docker-blog-arm-migration/pull/1](https://github.com/JoeStech/docker-blog-arm-migration/pull/1).

## Summary of changes

The migration produces these key changes:

**Dockerfile**:
- Replaced `centos:6` with `ubuntu:22.04`.
- Added `TARGETARCH` for multi-architecture builds.
- Changed `-mavx2` to `-march=armv8-a+simd` for Arm builds.

**Source code**:
- Added `#ifdef __aarch64__` architecture guards.
- Replaced all `_mm256_*` AVX2 intrinsics with NEON equivalents (`vld1q_f64`, `vaddq_f64`, `vmulq_f64`).
- Adjusted loop strides from 4 (AVX2) to 2 (NEON).
- Rewrote horizontal reduction using NEON pair-wise addition.

In the next section, you will build, test, and validate the migrated application on Arm.
Loading