cloud-sre

Apple container、Docker、Kubernetes の container は何が違うのか

Apple container、Docker、Kubernetes を同じレイヤー図で整理し、誰が image を扱い、誰が process を起動し、誰が Pod を管理するのかを分けて見る。

Jun 28, 2026
ContainersDockerKubernetesOCImacOS

Apple の container、Docker、Kubernetes はどれも container という言葉を使いますが、見ているレイヤーは同じではありません。

混乱しやすい点はここです。Kubernetes には container がありますが、Kubernetes 自身が Linux container を直接実装しているわけではありません。Pod が node に schedule されたあと、その node の kubelet が CRI runtime を呼び、runtime stack が Pod sandbox と container を作ります。

Apple の container はさらに別の設計です。OCI image を扱えますが、macOS kernel の中に Linux namespace を再現するのではなく、Linux container ごとに軽量 Linux VM を起動します。

用語の説明

用語意味
OCI imageOpen Container Initiative の image format。Docker、containerd、Kubernetes runtime、Apple container が共通して扱う土台です。
Runtimeimage と spec から実行中の process を作る component。文脈によって Docker daemon、containerd、CRI-O、runc、Apple container の runtime helper などを指します。
Namespace / cgroupLinux container の主要な隔離機能。namespace は process、network、mount などの見え方を分け、cgroup は CPU や memory などの resource を制限します。
VM-backed containercontainer process が Linux VM の中で動く形。非 Linux host で Linux container を動かすときによく使われる境界です。
Pod sandboxKubernetes/CRI における Pod の基礎実行環境。network など Pod 単位の共有境界を先に作り、application container がそこに参加します。
CRIKubernetes Container Runtime Interface。kubelet が container runtime と話すための interface です。
CNIContainer Network Interface。Kubernetes が Pod network を設定するために使う plugin interface です。

先に結論

「container の中の process は誰が起動するのか」で見ると、次のように分かれます。

Systemレイヤー最後に process を起動するもの隔離境界
Apple containermacOS 上の local OCI container tool/runtimehost の runtime helper が軽量 Linux VM を起動し、VM 内の vminitd が OCI process を起動するLinux container ごとに軽量 VM
Docker Enginelocal image、build、network、volume、container lifecycle toolDocker daemon が container runtime stack に委譲するLinux では namespace/cgroup。macOS の Docker Desktop も Linux VM が必要
Kubernetescluster orchestrationkubelet が CRI runtime を呼び、runtime が Pod sandbox と container を作るPod が schedule 単位で、container は Pod 内の process 単位

この三つは単純な置き換え関係ではありません。

Docker と Apple container は local に container を実行するレイヤーに近く、Kubernetes は複数 node 上で Pod を期待状態どおりに維持するレイヤーです。

Apple container の仕組み

Apple container は Swift で書かれた CLI と local service です。OCI image を扱うため、表面的な使い方は見慣れた形になります。

container run alpine uname -a

ただし内部では、macOS kernel に Linux container の隔離を直接任せていません。macOS には Linux namespace/cgroup の interface がありません。Apple が選んだのは VM-backed な設計です。Linux container ごとに軽量 Linux VM を用意します。

起動経路は概ね次の通りです。

container CLI
  -> container-apiserver
    -> container-core-images / container-network-vmnet / container-runtime-linux
      -> apple/containerization Swift package
        -> macOS Virtualization.framework
          -> Linux VM
            -> /sbin/vminitd
              -> OCI process

重要な点が三つあります。

一つ目は、host 側が API server と helper service に分かれていることです。Apple の technical overview では、container-apiserver、image service、network service、Linux runtime helper が分けて説明されています。CLI が Linux process を直接 fork するわけではありません。

二つ目は、Linux の境界が Virtualization.framework から来ていることです。apple/containerizationVZVirtualMachineInstanceVZVirtualMachine を包み、Linux kernel を設定し、kernel command line に init=/sbin/vminitd を渡します。

三つ目は、guest 側の vminitd です。host は vsock/gRPC で vminitd と通信し、guest Linux 内で mount、network、runtime spec、target process の起動を行わせます。

つまり Apple container は「macOS 版 runc」ではありません。OCI を向いた、macOS native な VM-backed runtime と見る方が近いです。

Docker の container はどう起動するのか

Docker の model はより古く、一般的です。

docker CLI
  -> Docker daemon
    -> container runtime stack
      -> isolated Linux process

Linux host では、container は namespace、cgroup、mount、capability などで隔離された通常の Linux process です。image が root filesystem と metadata を提供し、runtime が OCI spec に沿って環境を準備し、最後に application process を exec します。

macOS ではもう一つ境界があります。macOS kernel は Linux container を直接動かせないため、Docker Desktop は Docker Engine と Linux container を載せる Linux VM を必要とします。つまり Docker Desktop for Mac も VM-backed ですが、通常は一つの共有 Linux VM の中に複数 container を置く model です。

Apple container との大きな違いは VM の粒度です。

PointDocker Desktop for MacApple container
VM の粒度多くの場合、一つの共有 Linux VM が複数 container を載せるLinux container ごとに軽量 VM
EcosystemDocker CLI、Dockerfile、Compose、registry、BuildKit workflow が成熟しているApple Silicon/macOS native の実験的な方向で、Virtualization.framework と深く統合される
隔離感複数 container が同じ Linux VM kernel を共有するcontainer 間に VM 境界がある
Kubernetes との関係Docker は Kubernetes そのものではない。以前は dockershim が bridge していたが、現代の Kubernetes からは外れているCRI 互換 layer がなければ Kubernetes runtime にはならない

比較を「VM を使うかどうか」だけにすると本質を外します。macOS で Linux container を動かす以上、どこかに Linux は必要です。違うのは、誰が VM を管理するのか、VM の粒度はどこか、どの runtime API を持つのか、どの ecosystem に寄せているのかです。

Kubernetes の container は誰が起動するのか

Kubernetes の中心は生の container ではなく Pod です。

よくある起動経路は次のようになります。

kubectl apply / controller
  -> API Server が Pod または Deployment を保存
    -> Scheduler が node を選ぶ
      -> その node の kubelet が Pod の desired state を見る
        -> kubelet が CRI runtime を呼ぶ
          -> containerd または CRI-O が Pod sandbox を作る
            -> runtime が application container を作って起動する
              -> CNI plugin が Pod network を設定する

Kubernetes が管理するのは desired state と orchestration です。

  • この Pod が存在すべきか。
  • replica はいくつ必要か。
  • どの node に置けるか。
  • 失敗した container を再起動するか。
  • Service でどう公開するか。
  • どの Secret、ConfigMap、volume、service account が必要か。

実際の container process を作るのは node 上の runtime stack です。

現在の Kubernetes は CRI を通じて runtime と話します。よく使われる runtime は containerd と CRI-O です。Docker Engine は現在の Kubernetes で直接組み込まれた標準 runtime path ではありません。以前は kubelet と Docker Engine をつなぐ dockershim がありましたが、Kubernetes 1.24 で削除されています。

同じ Pod 内の container は通常 network namespace を共有するため、localhost で互いに通信できます。そのため Kubernetes は先に Pod sandbox を作ります。sandbox が Pod 単位の network 境界を持ち、application container がそこに参加します。

一枚の mental model

三つを同じ図に置くとこうなります。

Kubernetes
  -> kubelet on each node
    -> CRI runtime: containerd / CRI-O
      -> low-level runtime: runc / crun / VM-based runtime
        -> Linux process

Docker Engine on Linux
  -> dockerd
    -> container runtime stack
      -> Linux namespace + cgroup
        -> Linux process

Docker Desktop on macOS
  -> Docker Desktop VM
    -> Docker Engine inside Linux VM
      -> Linux container process

Apple container on macOS
  -> container-apiserver
    -> container-runtime-linux
      -> Virtualization.framework
        -> one lightweight Linux VM per container
          -> vminitd
            -> OCI process

この図で、いくつかの混乱を避けられます。

まず、Kubernetes は Docker と同種の product ではありません。Docker は local build/run に強く、Kubernetes は複数 machine 上の orchestration に強いものです。production では Kubernetes が containerd 経由で OCI image を動かし、developer machine では Docker や Apple container で image を build/test する、という組み合わせが自然です。

次に、Pod は container の名前を変えたものではありません。Pod は Kubernetes の schedule 単位であり、network などを共有する単位です。container は Pod 内の process 単位です。一つの Pod に application container だけがある場合もあれば、sidecar が入る場合もあります。

最後に、OCI image を動かせることと Kubernetes node runtime になれることは別です。Kubernetes に接続するには、Pod sandbox lifecycle、container lifecycle、logs、exec、port forwarding、stats、image service など CRI の意味論を満たす必要があります。

どう選ぶか

Mac で Linux image をすばやく実行したいなら、Docker Desktop も Apple container も候補になります。Docker の強みは成熟した ecosystem です。Dockerfile、Compose、BuildKit、registry、team workflow が揃っています。Apple container の面白さは、container ごとの軽量 VM、Swift 実装、macOS Virtualization.framework との統合です。

検証環境や production で service を長期運用するなら、議論は一つ上のレイヤーに移ります。必要なのは Kubernetes などの orchestrator、安定した node runtime、CNI、CSI、registry、monitoring、rollout strategy です。

container という言葉を理解するときは、次の境界を分けると楽です。

image format は OCI。
local runtime が image を process にする。
Kubernetes は machine 群の上で Pod を orchestrate する。
macOS で Linux container を動かすには Linux VM が必要。

このレイヤーを分けると、Apple container、Docker、Kubernetes は頭の中で競合しなくなります。三つとも container に関わりますが、担当している場所が違います。

References

  1. Apple container README: https://github.com/apple/container
  2. Apple container technical overview: https://github.com/apple/container/blob/main/docs/technical-overview.md
  3. Apple containerization README: https://github.com/apple/containerization
  4. Apple containerization VZVirtualMachineInstance: https://github.com/apple/containerization/blob/main/Sources/Containerization/VZVirtualMachineInstance.swift
  5. Docker overview: https://docs.docker.com/get-started/docker-overview/
  6. Docker Desktop Mac settings: https://docs.docker.com/desktop/settings/mac/
  7. Kubernetes Container Runtime Interface: https://kubernetes.io/docs/concepts/architecture/cri/
  8. Kubernetes container runtimes: https://kubernetes.io/docs/setup/production-environment/container-runtimes/
  9. Kubernetes Pods: https://kubernetes.io/docs/concepts/workloads/pods/
  10. Kubernetes dockershim removal FAQ: https://kubernetes.io/blog/2022/02/17/dockershim-faq/