---
title: "Minikube with Docker Driver on Apple Silicon"
description: "Running Minikube with the Docker driver on Apple Silicon (M4 Pro) for native ARM64 container execution without emulation overhead."
url: https://agent-zone.ai/knowledge/infrastructure/minikube-docker-driver/
section: knowledge
date: 2026-02-21
categories: ["infrastructure"]
tags: ["minikube","docker","arm64","apple-silicon"]
skills: ["local-k8s-setup","minikube-configuration"]
tools: ["minikube","docker","kubectl"]
levels: ["beginner"]
word_count: 559
formats:
  json: https://agent-zone.ai/knowledge/infrastructure/minikube-docker-driver/index.json
  html: https://agent-zone.ai/knowledge/infrastructure/minikube-docker-driver/?format=html
  api: https://api.agent-zone.ai/api/v1/knowledge/search?q=Minikube+with+Docker+Driver+on+Apple+Silicon
---


## Why the Docker Driver on ARM64

When running Minikube on Apple Silicon (M1/M2/M3/M4), the driver you choose determines whether your containers run natively or through emulation. The Docker driver runs containers directly on the host architecture — ARM64 — with zero emulation overhead.

This matters because QEMU user-mode emulation, which kicks in when you try to run amd64 images on ARM64, cannot reliably execute Go binaries. The specific failure is a crash in `lfstack.push`, deep in Go's runtime memory management. This is not a fixable application bug — it is a fundamental incompatibility between QEMU's user-mode emulation and Go's lock-free stack implementation.

## Starting Minikube with Docker

```bash
minikube start --driver=docker
```

This creates a Kubernetes cluster where the node itself is a Docker container running on your Mac. Since Docker Desktop on Apple Silicon runs a native ARM64 Linux VM, all containers inside minikube execute as native ARM64 binaries.

To make Docker the default driver permanently:

```bash
minikube config set driver docker
```

## Building Images into Minikube's Docker

Minikube runs its own Docker daemon inside the cluster node. To build images that minikube can use without pulling from a registry, point your shell at minikube's Docker:

```bash
eval $(minikube docker-env)
docker build -t myapp:latest .
```

After this, `docker images` lists images inside the minikube node, not your host. To switch back to your host Docker:

```bash
eval $(minikube docker-env -u)
```

When deploying with these local images, set `imagePullPolicy: Never` in your pod spec so Kubernetes does not try to pull from a remote registry:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp
          image: myapp:latest
          imagePullPolicy: Never
          ports:
            - containerPort: 8080
```

## Port Forwarding to Local Services

Two common ways to reach services running inside minikube:

**minikube service** opens a tunnel and gives you a URL:

```bash
minikube service myapp --url
# http://127.0.0.1:52341
```

**kubectl port-forward** maps a local port to a pod or service:

```bash
kubectl port-forward svc/myapp 8080:8080
```

The `minikube service` approach handles NodePort services cleanly. `kubectl port-forward` works with any service type and gives you explicit port control.

## Resource Management

The Docker driver shares your host's resources dynamically. Unlike the VM-based drivers (HyperKit, QEMU), which pre-allocate a fixed amount of CPU and memory at start time, the Docker driver lets containers use whatever the host has available, subject to Docker Desktop's own resource limits.

You can still set limits at start time to cap usage:

```bash
minikube start --driver=docker --cpus=4 --memory=8192
```

Check what minikube thinks it has:

```bash
kubectl describe node minikube | grep -A 5 "Capacity:"
```

## The containerd/QEMU Gotcha

Minikube's containerd runtime does not use Rosetta for translating amd64 images. If you deploy an image that only has an amd64 manifest, containerd falls back to QEMU user-mode emulation to run it. This is where Go binaries crash.

The fix is to always use ARM64-native images. Check an image's architecture:

```bash
docker inspect --format='{{.Architecture}}' myimage:latest
```

For images that do not publish ARM64 variants (for example, Mattermost), you need to build your own from source or from ARM64 binary tarballs. There is no workaround that makes QEMU reliably run Go on ARM64 — the emulation gap is at the CPU instruction level.

## Quick Reference

| Task | Command |
|------|---------|
| Start cluster | `minikube start --driver=docker` |
| Use minikube Docker | `eval $(minikube docker-env)` |
| Build local image | `docker build -t app:v1 .` |
| Access service | `minikube service <name> --url` |
| Check architecture | `docker inspect --format='{{.Architecture}}' <image>` |
| Stop cluster | `minikube stop` |
| Delete cluster | `minikube delete` |

