Container Machineを使ってUbuntuからMacへ移行

夏休みシーズンが来ましたが、仕事の都合もあって、ガッツリ時間を確保することは叶いませんでした。とはいえ、少しずつ前進しています。

前回書いたように、開発環境をVMPlayer上のUbuntuからMacbook Airに移行しようとしています。休みの前半は、まずそのための環境整備からです。
macOSのことはほとんど忘れてしまっていて、今回も自分のためのメモの側面が強い記事です。

今回行う環境整備は、Macの上でのLinux環境の実現です。そのため、Appleが6月のWWDCで発表した「Container Machine」を導入して、Mac上で永続的にUbuntuを動作させます。そして、旧環境であるUbuntu上で、開発途中のファイルが入ったディレクトリを丸ごとtarでアーカイブして、Mac上に展開しようという目論見です。

AppleのContainerはDockerによく似ていて、Mac上でLinuxコンテナを実行することができます。DockerやContainerで使われるコンテナイメージは、Linuxアプリケーションとその実行に必要なファイルや設定をまとめたもので、そこから実行環境であるコンテナを生成します。

一方、新たに追加されたContainer Machineは、同じ技術を長期間使い続けるLinux環境を作るために利用しています。内部で行った変更は保持され、停止・再起動しても同じ環境を継続して利用できます。この点では、使い勝手は従来のVMにかなり近いものがあります。

Discover container machines - WWDC26 - Videos - Apple Developer
Meet container machines, a new tool included in Container that offers a lightweight persistent Linux environment on Mac....

The Day Apple Turned Your MacBook Into a Linux Box | by Cordero Core | Jun, 2026 | Medium

類似の技術としては、WindowsのWSL2も仮想化技術を利用しています。WSL2ではWindowsが管理する軽量なVM上でLinux kernelが動作し、その上でUbuntuなどのLinuxディストリビューションが稼働します。この時、Linuxディストリビューションのルートファイルシステムは、WSL2が用意する仮想ディスク上にインストールされます。

一方、Container MachineはLinux環境のコンテナイメージを用意し、そのイメージを初期状態として永続的なLinux環境を作成します。WSL2と用途は似ていますが、実現方法が違っています。Container Machineでは、Linux環境のルートファイルシステムをコンテナを定義するのと同じ方法で、つまりDockerfileを書いて、コンテナイメージとして構築しています。

Mac上でContainer Machineを使ってUbuntu 24.04を動作させる手順は、現時点(2026年8月)では以下の通りです:

(1)Containerの公式githubのリリースページから.pkgファイルをダウンロードしてインストールする。(8月11日現在の最新版は1.2.2)
(2)container --versionでインストールされたことを確認する。
(3)container system startで起動する。初回のみ、Containerが使用するLinuxカーネルなど必要なコンポーネントがダウンロードされます。
(4)container system statusで動作確認する。
(5)Dockerfileを用意し、コンテナイメージを作成してコンテナを起動する。

コンテナを生成する前に、考慮しておくべきことが2点あります。

・MacとLinux(コンテナ)とのファイル共有
・Rosetta終了

Macとコンテナのファイル共有ですが、Container MachineはMac側のホームディレクトリ(/Users/username)を、特に設定しなくてもデフォルトでコンテナ側にマウントします。

ただ、注意点は、Macのファイルシステムはデフォルトでは大文字小文字を区別しないという点です。

今回はLinuxで開発環境を作るので、Linuxに合わせて大文字小文字を区別するファイルシステムをMac側に追加で作成し、それをContainer Machine側にマウントすることでMacとLinuxの間でファイルを共有させます。

このために行うことは

(1)大文字小文字を区別するファイルシステムを作成する
(2)そのファイルシステムをホームディレクトリの下の指定のディレクトリ(私の場合は~/Developmentにしました)にマウントする

です。

大文字小文字を区別するファイルシステムは「ディスクユーティリティ」アプリで簡単に作成できます。新しいVolumeを作成する際に、case sensitiveを選択できます。

MacのAPFSでは、パーティションを切り直さず、既存のAPFS Containerの中に新しいVolumeを追加できます。この時、パーティションのようにあらかじめ固定サイズを割り当てる必要はなく、同じAPFS Container内のVolumeは空き領域を共有します。(Quotaでサイズ制限したり、一定サイズを予約することはVolume作成時に行えます。)

新しく作ったVolumeは、デフォルトでは/Volumes/volume-nameの下にマウントされます。しかし、Container Machineが自動でマウントするのがユーザのホームディレクトリなので、今回はこのデフォルト位置ではなくホームディレクトリの下(~/Development)にマウントします。

アンマウント・マウントは一時的には以下のコマンドで行えます。(Volumeの名称がDevelopmentの場合)

diskutil info /Volumes/Development # デバイス名(diskAsB)を確認する; AとBは数字
diskutil unmount /Volumes/Development
mkdir ~/Development
sudo mount_apfs /dev/diskAsB ~/Development

永続的にマウントポイントを変更する場合は、/etc/fstabを編集します。

なお、APFSではVolumeを指定するのに前述のdiskAsBのようなスタイルではなくUUIDを使うことが推奨されているそうです。

次に、Rosettaのフェードアウトです。

RosettaはIntelアーキテクチャのバイナリを実行するためのソフトウェアですが、macOS 28以降では古いゲームなど、一部のソフトウェアにサポート対象が限定されていく方向のようです。

個人的にはMacの上でx86のバイナリを動かす必要は特に無いので、ここは潔く(?)Rosettaをインストールせずに、イメージのビルドをarm64ネイティブに限定し、Container Machineでもarm64版のイメージだけを使用することにします。

そのための設定は、~/.config/container/config.tomlに以下の内容を追加します。(この設定はcontainer buildで使用されるbuilder VMについてRosettaを無効にするものです。通常のコンテナ実行時にRosettaを使用するかどうかは、別途container run --rosettaで指定します。)

[build]
rosetta = false

そして、containerを再起動します。

container system stop
container system start

それでは、Dockerfileを作って開発用のコンテナイメージを生成します。DockerfileはAppleの公式ドキュメントのものをベースにしています。

FROM ubuntu:24.04

ENV container container

RUN apt-get update && \
    apt-get install -y \
        dbus \
        systemd \
        openssh-server \
        net-tools \
        iproute2 \
        iputils-ping \
        curl \
        wget \
        vim-tiny \
        man \
        sudo && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* && \
    yes | unminimize

RUN > /etc/machine-id
RUN > /var/lib/dbus/machine-id

RUN systemctl set-default multi-user.target

RUN systemctl mask \
      dev-hugepages.mount \
      sys-fs-fuse-connections.mount \
      systemd-update-utmp.service \
      systemd-tmpfiles-setup.service \
      console-getty.service

RUN systemctl disable \
      networkd-dispatcher.service

RUN sed -i \
    -e 's/^AcceptEnv LANG LC_\*$/#AcceptEnv LANG LC_*/' \
    /etc/ssh/sshd_config

このファイルを特定のディレクトリ(例えば~/container-machines/ubuntu)に置きます。

そしてそのディレクトリで

container build -t ubuntu-dev:24.04 .

を実行します。-tはタグ指定、最後の”.”はbuild contextとしてカレントディレクトリを指定しています。-fを指定しない場合は、そこにあるDockerfileが使用されます。

あとは以下のように進めるとContainer MachineのLinuxに入れます。

container image ls # イメージができていることを確認
container machine create ubuntu-dev:24.04 --name ubuntu24 # イメージからcontainer machineを作成して起動
container machine ls # machineが作成されたことを確認
container machine run -n ubuntu24 # machineでコマンドを実行(コマンドを指定しない場合はshellを実行)

最後のコマンドを実行した時点で、Linuxに入った状態になります。exitで抜けられます。exitしてもContainer Machine自体は停止しません。停止する場合は

container machine stop ubuntu24

を実行します。

macOS側で~/Developmentにcdしてから、再度container machine runすると、カレントディレクトリ(~/Development)をContainer Machineに共有した状態でLinuxに入ります。

なんだか、「macOSモード」と「Linuxモード」を切り替えているような不思議な感覚です。

コメント

タイトルとURLをコピーしました