2026年9月、CanonicalからImagecraftのバージョン1.
今回はこのImagecraftを使って、実際に起動可能なUbuntuの仮想マシンイメージを作る方法を解説します。
Imagecraftとは
歴史的な経緯もあり、ブート可能なUbuntuのイメージを作成するためには、様々なツールが存在しています。そのため自分でカスタムした仮想マシンイメージを作ろうとすると、従来は複数のツールを使いこなすための知識が必要でした。
現在Canonicalは、ソフトウェアや成果物のビルド処理に必要なツールの共通化を進めています。具体的な実装としては、SnapパッケージをビルドするSnapcraftや、Juju Charmのパッケージングを行うCharmcraftなどです。これらのツールは共通して、宣言的なYAML、隔離されたクリーンなビルド環境、再利用可能なプラグインといった特徴を持っています。そして数あるCraftツール群の中で、ブート可能なOSイメージを作るためのツールがImagecraftです。
Imagecraftは手順を逐一スクリプトとして記述するのではなく、作成したいイメージの構成をYAMLファイルとして宣言的に記述します。そのためYAMLファイルを見るだけで、作成されるイメージのおおまかな構成を把握できます。またテキスト形式のYAMLファイルであるため、Gitなどでバージョン管理しやすいのもメリットだと言えるでしょう。同じ定義ファイルからイメージを繰り返し生成できるため、独自のカスタムを施したイメージを継続的にビルドするといった用途にも向いています。
Imagecraftのインストール
ImagecraftはSnapパッケージとして提供されています。まずは次のコマンドでインストールしてください。
$ sudo snap install imagecraft --classic
Imagecraftはイメージのビルドを、ホストから隔離された環境で行います。今回ビルド環境にはMultipassを使用しますので、こちらもSnapパッケージからインストールしておきましょう。
$ sudo snap install multipass
仮想マシンイメージの定義
それではイメージを作ってみましょう。なお今回作成するイメージは、最後にqemu-system-x86_
まずは作業用のディレクトリを作成します。
$ mkdir ~/ubuntu-image $ cd ~/ubuntu-image
このディレクトリ内で、imagecraft initを実行してください。これで構成を記述したimagecraft.
$ imagecraft init
作成されたファイルを、テキストエディタで以下のように書き換えてください。
name: ubuntu
base: bare
build-base: ubuntu@24.04
version: '0.1'
summary: Custom Ubuntu virtual machine image
description: |
A custom Ubuntu virtual machine image
built with Imagecraft.
platforms:
amd64:
volumes:
disk:
schema: gpt
structure:
- name: rootfs
role: system-data
type: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
filesystem: ext4
filesystem-label: root
size: 8 G
- name: efi
role: system-boot
type: C12A7328-F81F-11D2-BA4B-00A0C93EC93B
filesystem: vfat
filesystem-label: uefi
size: 512M
filesystems:
default:
- device: (volume/disk/rootfs)
mount: /
- device: (volume/disk/efi)
mount: /boot/efi/
parts:
rootfs:
plugin: mmdebstrap
mmdebstrap-suite: noble
override-build: |
craftctl default
mkdir $CRAFT_PART_INSTALL/boot/efi/
cat << EOF > $CRAFT_PART_INSTALL/etc/apt/sources.list.d/ubuntu.sources
Types: deb
URIs: http://archive.ubuntu.com/ubuntu
Suites: noble noble-updates noble-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
Types: deb
URIs: http://security.ubuntu.com/ubuntu
Suites: noble-security
Components: main universe restricted multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
EOF
organize:
'*': (overlay)/
fstab:
plugin: nil
overlay-script: |
cat << EOF > $CRAFT_OVERLAY/etc/fstab
LABEL=root / ext4 discard,errors=remount-ro 0 1
LABEL=uefi /boot/efi/ vfat umask=0077 0 1
EOF
packages:
plugin: nil
overlay-packages:
- ubuntu-server-minimal
- linux-image-generic
- grub2-common
- grub-pc
- shim-signed
- login
- cloud-init
- git
- docker.io
それなりの分量がありますので、上から順番に見ていきましょう。
プロジェクトの説明
冒頭の部分は、このプロジェクトそのものについての設定です。
name: ubuntu
base: bare
build-base: ubuntu@24.04
version: '0.1'
summary: Custom Ubuntu virtual machine image
description: |
A custom Ubuntu virtual machine image
built with Imagecraft.
name、version、summary、descriptionは、それぞれイメージの名前、バージョン、簡単な概要、詳細な説明です。
baseには、ビルドするイメージのベースとなる環境を指定します。今回は既存のイメージをベースとするのではなく、mmdebstrapを使ってまっさらなルートファイルシステムを構築するためbareを指定しています。
build-baseは
ビルドするプラットフォームの設定
platformsでは、作成するイメージのプラットフォームを指定します。今回は一般的なx86_
platforms:
amd64:
ディスクとパーティションの設定
volumes以下では、作成するディスクイメージを設定します。
volumes:
disk:
schema: gpt
structure:
- name: rootfs
role: system-data
type: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
filesystem: ext4
filesystem-label: root
size: 8 G
- name: efi
role: system-boot
type: C12A7328-F81F-11D2-BA4B-00A0C93EC93B
filesystem: vfat
filesystem-label: uefi
size: 512M
schemaをgptとしているため、ここではGPT形式のパーティションテーブルが作成されます。
structure以下で、パーティションを設定します。8GBのrootfsと、512MBのefiという、2つのパーティションを作成しました。typeには、GPTのパーティションタイプGUIDを指定します。これはタイプごとに決まっており、rootfsはLinux filesystem dataなので
volumesはあくまでパーティションを定義するだけなので、これだけでは利用できません。続くfilesystems以下で、イメージのパーティションとマウントポイントのマッピングを指定します。
filesystems:
default:
- device: (volume/disk/rootfs)
mount: /
- device: (volume/disk/efi)
mount: /boot/efi/
これでビルド環境内において、rootfsパーティションが/に、efiパーティションが/boot/
なおここで指定しているのは、Imagecraftがイメージを構築する際における、各パーティションとイメージ内のマウントポイントとの対応です。この設定だけで、完成したOSが起動時にパーティションを自動的にマウントしてくれるわけではありません。起動後のOSがどのパーティションをどこへマウントするかは、後述する/etc/
Ubuntuのルートファイルシステムを作成する
parts以下では、イメージを構築するための処理を、複数のpartに分けて設定します。それぞれのpartでは、プラグインを使ってファイルを生成したり、パッケージを追加したり、任意のコマンドを実行したりできます。
parts:
rootfs:
plugin: mmdebstrap
mmdebstrap-suite: noble
override-build: |
craftctl default
mkdir $CRAFT_PART_INSTALL/boot/efi/
cat << EOF > $CRAFT_PART_INSTALL/etc/apt/sources.list.d/ubuntu.sources
Types: deb
URIs: http://archive.ubuntu.com/ubuntu
Suites: noble noble-updates noble-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
Types: deb
URIs: http://security.ubuntu.com/ubuntu
Suites: noble-security
Components: main universe restricted multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
EOF
organize:
'*': (overlay)/
parts内では、様々なプラグインを利用できます。rootfsというpartではmmdebstrapプラグインを利用して、最小のルートファイルシステムを作っています。プラグインには、それぞれ固有のキーを指定できます。ここではmmdebstrap-suiteにnobleを指定し、Ubuntu 24.
続いてoverride-buildがあります。これはプラグインが実行する通常のビルド処理を、独自の処理で上書きする指定です。
ここで重要なのが、craftctl defaultです。これは、プラグイン本来のビルド処理を明示的に実行させる指定です。というのもoverride-buildを指定すると、本来行うビルド処理全体が置き換えられてしまうのです。今回は
追加している処理は見ての通りで、EFIシステムパーティションのマウントポイントを用意した上で、APTのリポジトリをubuntu.
Imagecraftでは、各partで生成したファイルを、最終的なイメージへ配置します。このpartで作成されたルートファイルシステム全体を、最終イメージのoverlayへ配置する指定が、末尾にあるorganizeとなります。ここでは全ファイルを、overlayのルートへ配置しています。
/etc/fstabを作成する
既にパーティションとファイルシステムは設定しましたが、起動時にこれらをどこへマウントするかを、作成後のOSに教えてあげる必要があります。そのための設定が/etc/
fstab:
plugin: nil
overlay-script: |
cat << EOF > $CRAFT_OVERLAY/etc/fstab
LABEL=root / ext4 discard,errors=remount-ro 0 1
LABEL=uefi /boot/efi/ vfat umask=0077 0 1
EOF
プラグインにはnilを指定しています。nilプラグインは、特別なビルド処理を行わないプラグインです。上記のようにプラグイン固有のビルド処理が不要で、自分が指定したコマンドだけを実行したいような場合に便利です。ここではcatコマンドを実行し、ルートファイルシステムを/、EFIシステムパーティションを/boot/
必要なパッケージを追加する
最後のpackagesというpartでは、イメージに追加するパッケージを指定しています。
packages:
plugin: nil
overlay-packages:
- ubuntu-server-minimal
- linux-image-generic
- grub2-common
- grub-pc
- shim-signed
- login
- cloud-init
- git
- docker.io
ubuntu-server-minimalに加えて、LinuxカーネルやGRUBなど、Ubuntuを仮想マシンとして起動するために最低限必要なパッケージを追加しています。さらに今回はloginも明示的に追加しています。後ほどQEMUのコンソールから、ユーザー名とパスワードを入力して対話的にログインするためです。
cloud-initも追加しています。作成したOSイメージには、ホスト名やユーザー名など、仮想マシンごとに異なる情報をなるべく直接埋め込みたくありません。またパスワードを直接イメージに埋め込むと、セキュリティ的なリスクにもなるでしょう。こうした情報は、仮想マシン起動時の初期化処理で行うのが一般的です。そのためイメージには、初期化を行うcloud-initパッケージを追加しているというわけです。
最後のgitとdocker.
イメージのビルド
設定ファイルができたら、実際にイメージをビルドしてみましょう。今回はビルド環境にMultipassを利用するため、以下のコマンドでproviderを設定します。
$ sudo snap set imagecraft provider=multipass
続いて、imagecraft.
$ imagecraft pack
するとImagecraftはMultipassの仮想マシンを作成し、その中にビルド環境を用意します。今回はYAML内で指定したbuild-base: ubuntu@24.
ビルドが正常に終了すると、カレントディレクトリにdisk.
cloud-initで初期設定を行う
この段階で、作成したdisk.
今回はcloud-initに渡す設定として、user-dataとmeta-dataという2つのファイルを作成します。まずuser-dataを以下の内容で作成してください。
#cloud-config
hostname: imagecraft-test
users:
- name: ubuntu
shell: /bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
lock_passwd: false
chpasswd:
expire: false
users:
- name: ubuntu
password: ubuntuユーザーに設定するパスワード
type: text
bootcmd:
- rm -f /etc/resolv.conf
- ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
内容を簡単に説明しましょう。まずhostnameによって、仮想マシンのホスト名をimagecraft-testに設定します。users以下では、ubuntuというユーザーを作成しています。またパスワードなしでsudoを利用できるようにしています。さらにchpasswdで、ユーザーのパスワードを設定しています。
最後にあるbootcmdでは、ブートプロセス時に実行するコマンドを設定しています。
現在のUbuntuでは、DNSリゾルバーの設定ファイルである/etc/
ただしsystemd-resolvedそのものは正常に起動しており、/run/
続いてmeta-dataを以下の内容で作成します。
instance-id: imagecraft-test
local-hostname: imagecraft-test
これらのファイルをcloud-initから読み込ませるには、NoCloud形式のデータソースに変換する必要があります。以下のコマンドでcloud-image-utilsパッケージをインストールしてください。
$ sudo apt install -U -y cloud-image-utils
以下のコマンドで、user-dataとmeta-dataからseed.
$ cloud-localds seed.img user-data meta-data
仮想マシンを起動する
disk.
$ sudo apt install -U -y qemu-system-x86 ovmf
OVMFでは、UEFIのファームウェア本体と、設定を保存する領域が別々のファイルになっています。ファームウェア本体であるOVMF_
$ cp /usr/share/OVMF/OVMF_VARS_4M.fd ~/ubuntu-image/
ここまでの準備ができたら、以下のコマンドで仮想マシンを起動してください[3]。
$ qemu-system-x86_64 \ -accel kvm \ -m 4G \ -cpu host \ -smp 2 \ -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \ -drive if=pflash,format=raw,file=./OVMF_VARS_4M.fd \ -drive file=./disk.img,format=raw,index=0,media=disk \ -drive file=./seed.img,format=raw,if=virtio
仮想マシンが正常に起動すると、QEMUのウィンドウにUbuntuのログインプロンプトが表示されます。cloud-initで作成したubuntuユーザーを使ってログインできることや、パスワードなしでsudoができること、インターネットと通信ができること、gitやdockerコマンドがインストールされていることなどを確認しておきましょう。
なおdisk.
単純にUbuntuの仮想マシンが欲しいだけなら、既存のUbuntu Cloud Imageを利用する方が簡単です。ですがImagecraftのメリットは、そうした
まだ1.
imagecraft.