GraalVM Native Imageでアプリをネイティブ化→コンテナ化し、ARM/Intelマルチアーキ対応で公開する手順

Here’s the **entire step-by-step guide** in a single Markdown file you can share or paste with one click:

````markdown
# Multi-Arch GraalVM Native Image Pipeline for “Jibber”

**You will learn how to:**
1. Clone the Jibber demo source  
2. Build a Spring Boot “uber-jar” and AOT-compile it into a native ELF using GraalVM  
3. Containerize that ELF in a minimal Debian image  
4. Cross-compile for ARM64 & AMD64 with Docker Buildx + QEMU in one command  
5. Publish the multi-arch image to GitHub Container Registry (GHCR)  
6. Verify & smoke-test on Linux/ARM and Windows/Intel  
7. *(Optional)* Make the package public & automate via GitHub Actions  

---

## 0. Prerequisites

- Docker ≥ 20.10 with Buildx  
- QEMU binfmt handlers  
- GitHub PAT in `CR_PAT` (scope: `packages:write`)  
- *(macOS/Rancher Desktop)*  
  ```bash
  sudo ln -sf $HOME/.rd/docker.sock /var/run/docker.sock
  # or
  export DOCKER_HOST=unix://$HOME/.rd/docker.sock
````

* *(Optional)* `jq` CLI

```bash
export GHUSER=<Your Github UserID>
export IMAGE=jibber
export CR_PAT=<your_GHCR_PAT>
```

---

## 1. Download the Demo

```bash
git clone --depth 1 https://github.com/graalvm/graalvm-demos.git
cd graalvm-demos/native-image/spring-boot-microservice-jibber
```

---

## 2. Create **Dockerfile.multiarch**

Save **this** in your project root as `Dockerfile.multiarch`:

```dockerfile
# syntax=docker/dockerfile:1.5

############################################################
# 1) BUILD + NATIVE (AOT) with Oracle-hosted Community Image
############################################################
FROM container-registry.oracle.com/graalvm/native-image:21 AS build

# Install Maven
RUN microdnf install -y maven && microdnf clean all

WORKDIR /workspace
COPY pom.xml ./
COPY src    ./src

# 1) mvn clean package -Pnative → target/*.jar
# 2) native:compile           → produces target/benchmark-jibber (ELF)
RUN mvn clean package -Pnative -DskipTests native:compile

##############################
# 2) RUNTIME IMAGE
##############################
FROM debian:bookworm-slim AS runtime

# Install zlib (libz.so.1) and CA certs
RUN set -eux; \
    apt-get update; \
    apt-get install -y --no-install-recommends \
      zlib1g \
      ca-certificates; \
    rm -rf /var/lib/apt/lists/*

# Copy the compiled ELF
COPY --from=build /workspace/target/benchmark-jibber /usr/local/bin/jibber
RUN chmod +x /usr/local/bin/jibber

EXPOSE 8080
ENTRYPOINT ["/usr/local/bin/jibber"]
```

> **GraalVM AOT**: the Native Image plugin performs reachability analysis, tree-shaking, and ahead-of-time compilation, yielding a standalone ELF.

---

## 3. Bootstrap Buildx + QEMU

```bash
docker buildx create --name multiarch --driver docker-container --use || true
docker run --privileged --rm tonistiigi/binfmt --install all
```

---

## 4. Authenticate to GHCR

```bash
docker logout ghcr.io || true
echo $CR_PAT | docker login ghcr.io -u $GHUSER --password-stdin
```

---

## 5. Prune & Remove Old Images

```bash
docker image rm ghcr.io/${GHUSER}/${IMAGE}:latest || true
docker buildx prune --all --force
```

---

## 6. Build & Push Multi-Arch

option 1) Build & Push Multi-Arch (Linux/macOS)
```
docker buildx build \
  --file Dockerfile.multiarch \
  --platform linux/arm64,linux/amd64 \
  --no-cache \
  --pull \
  --push \
  -t ghcr.io/naiveprince0507/my-app:latest \
  .
```
option 2) Build & Push Multi-Arch (PowerShell on Windows)

```powershell

docker buildx build `
  --file Dockerfile.multiarch `
  --platform linux/arm64,linux/amd64 `
  --no-cache `
  --pull `
  --push `
  -t ghcr.io/naiveprince0507/my-app:latest `
  .
````
---

## 7. Verify Manifest List

```bash
docker buildx imagetools inspect ghcr.io/${GHUSER}/${IMAGE}:latest --raw \
  | jq '.manifests[] 
       | select(.platform.architecture!="unknown") 
       | {os:.platform.os, arch:.platform.architecture}'
```

Should show:

```json
{ "os":"linux", "arch":"arm64" }
{ "os":"linux", "arch":"amd64" }
```

---

## 8. Smoke-Test Your Service

### Linux/ARM (e.g. M1/M2 Mac)

```bash
docker run --rm -p 8080:8080 ghcr.io/${GHUSER}/${IMAGE}:latest
```

### Windows/Intel (AMD64)

```powershell
docker run --rm -p 8080:8080 ghcr.io/${GHUSER}/${IMAGE}:latest
```

Then:

```bash
curl http://localhost:8080/jibber         # random verse
curl http://localhost:8080/actuator/health  # {"status":"UP"}
```

---

## 9. (Optional) Make Public

1. Go to **[https://github.com/users/\${GHUSER}/packages](https://github.com/users/${GHUSER}/packages)**
2. Select **jibber → Settings → Visibility → Public**

---

## 10. (Optional) CI/CD GitHub Actions

Add `.github/workflows/docker-multiarch.yml`:

```yaml
name: Publish multi-arch jibber

on:
  push:
    branches: [ main ]
    paths:
      - 'native-image/spring-boot-microservice-jibber/**'
      - 'Dockerfile.multiarch'

permissions:
  contents: read
  packages: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/build-push-action@v5
        with:
          file: Dockerfile.multiarch
          platforms: linux/amd64,linux/arm64
          push: true
          tags: |
            ghcr.io/${{ github.repository_owner }}/jibber:latest
            ghcr.io/${{ github.repository_owner }}/jibber:v${{ github.run_number }}
```

On every push to **main**, this builds both ARM64 & AMD64 and publishes `latest` and a version tag.

---

🎉 **Share this Markdown** with your team for a turnkey, multi-arch GraalVM native-image pipeline.