WSL 上で Docker + Zephyr 開発環境を起動する手順(①〜④)
本書は Windows Docker Desktop を使わず、WSL(Ubuntu)上で Docker Engine を手動起動し、Zephyr 開発環境を Docker コンテナで構築・利用するための最小かつ実務向け手順をまとめたものです。
① WSL(Ubuntu)の準備
② Ubuntu(WSL)に Docker Engine をインストール
③ Zephyr用Docker関連ディレクトリ・ファイル作成
④ Zephyrサンプル実行手順
① WSL(Ubuntu)の準備
※古いWSL上のUbuntuを削除する場合のみ
> wsl -l -v
NAME STATE VERSION
* Ubuntu Stopped 2
> wsl --unregister Ubuntu
WSL上にUbuntuをインストール
> wsl --install Ubuntu
Ubuntu 起動後
sudo apt update
sudo apt upgrade -y
② Ubuntu(WSL)に Docker Engine をインストール
※ Windows Docker Desktop は使用しない
②-1. 旧 Docker の削除
※古いDockerを削除する場合のみ
sudo apt remove -y docker docker-engine docker.io containerd runc
②-2. Docker 公式リポジトリ登録
Docker Engineに必要なパッケージをインストール
sudo apt install -y ca-certificates curl gnupg lsb-release
Docker 公式の GPG 鍵を追加
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
Docker の公式リポジトリを追加
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
②-3. Docker Engine / compose インストール
sudo apt update
sudo apt install -y \
docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
②-4. Docker デーモン起動確認
$ sudo service docker status
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; preset: enabled)
Active: active (running) since Sat 2026-01-03 09:23:10 JST; 19s ago
TriggeredBy: ● docker.socket
Docs: https://docs.docker.com
Main PID: 7810 (dockerd)
Tasks: 13
Memory: 23.3M (peak: 25.5M)
CPU: 544ms
CGroup: /system.slice/docker.service
└─7810 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
②-5. ユーザーに Dockerへの実行権限付与
$ sudo groupadd docker
$ sudo usermod -aG docker $USER
③ Zephyr用Docker関連ディレクトリ・ファイル作成
以下のディレクトリとファイルを作成
zephyr-dev/
├ .env
├ docker-compose.yml
├ Dockerfile
└ entrypoint.sh
③-1 .env
UBUNTU_VERSION=22.04
ZEPHYR_VERSION=v4.3.0
WEST_VERSION=1.5.0
ZEPHYR_SDK_VERSION=0.16.5
- UBUNTU_VERSION
- Dockerfile の FROM ubuntu:${UBUNTU_VERSION} を決めるための値
- = イメージの土台OSのバージョン(ビルド時に使う)
- ZEPHYR_VERSION
- entrypoint.sh の west init --mr "${ZEPHYR_VERSION}" で使う値
- = Zephyr のタグ/ブランチ/コミット(実行時に使う)
- 例:v4.3.0 タグ固定で workspace を作る
- WEST_VERSION
- Dockerfile の pip install west==${WEST_VERSION} に使う値
- = west(Zephyr のメタツール)のバージョン固定(ビルド時に使う)
- ZEPHYR_SDK_VERSION
- Dockerfile の SDK ダウンロード URL と ZEPHYR_SDK_INSTALL_DIR に使う値
- = Zephyr SDK のバージョン固定(ビルド時に使う)
- 重要:.env は compose の変数展開にも使われるが、env_file: で コンテナ実行時の環境変数にも渡される
③-2 docker-compose.yml
services:
zephyr:
build:
context: .
dockerfile: Dockerfile
args:
UBUNTU_VERSION: ${UBUNTU_VERSION}
WEST_VERSION: ${WEST_VERSION}
ZEPHYR_SDK_VERSION: ${ZEPHYR_SDK_VERSION}
env_file:
- .env
volumes:
- zephyr-workspace:/workspace/zephyrproject
- zephyr-cache:/root/.cache
tty: true
volumes:
zephyr-workspace:
zephyr-cache:
- build / args
- Dockerfile の ARG に値を流し込む(=ビルド時だけ有効)
- OS / west / SDK を 再現性ある固定にできる
- env_file
- .env の中身を コンテナ内の環境変数として設定(=実行時に有効)
- entrypoint.sh が ZEPHYR_VERSION を読むために必要
- volumes(永続化の要)
- zephyr-workspace
- Zephyr ソース一式(.west、zephyr/、modules、build/ など)を永続化
- --rm でコンテナを捨てても、次回に引き継げる
- zephyr-cache
- pip や ccache 等のキャッシュ保存
- zephyr-workspace
- tty
- 対話実行(bash)やログ表示が崩れにくくなる
③-3 Dockerfile
ARG UBUNTU_VERSION=22.04
FROM ubuntu:${UBUNTU_VERSION}
ARG WEST_VERSION
ARG ZEPHYR_SDK_VERSION
ENV DEBIAN_FRONTEND=noninteractive
ENV ZEPHYR_TOOLCHAIN_VARIANT=zephyr
ENV ZEPHYR_SDK_INSTALL_DIR=/opt/zephyr-sdk-${ZEPHYR_SDK_VERSION}
# --- base packages (公式 Getting Started 準拠) ---
RUN apt-get update && apt-get install -y --no-install-recommends \
git cmake ninja-build gperf ccache \
dfu-util device-tree-compiler wget \
python3 python3-dev python3-venv python3-pip \
xz-utils file make gcc gcc-multilib g++-multilib \
libsdl2-dev \
&& rm -rf /var/lib/apt/lists/*
# --- Python venv (Zephyr 用) ---
RUN python3 -m venv /opt/zephyr/.venv \
&& /opt/zephyr/.venv/bin/pip install --upgrade pip \
&& /opt/zephyr/.venv/bin/pip install \
west==${WEST_VERSION} \
pyelftools \
jsonschema \
PyYAML \
packaging
ENV PATH="/opt/zephyr/.venv/bin:${PATH}"
# --- Zephyr SDK ---
RUN wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${ZEPHYR_SDK_VERSION}/zephyr-sdk-${ZEPHYR_SDK_VERSION}_linux-x86_64.tar.xz \
&& tar -xf zephyr-sdk-${ZEPHYR_SDK_VERSION}_linux-x86_64.tar.xz -C /opt \
&& rm zephyr-sdk-${ZEPHYR_SDK_VERSION}_linux-x86_64.tar.xz \
&& /opt/zephyr-sdk-${ZEPHYR_SDK_VERSION}/setup.sh -t all -h -c
# --- entrypoint ---
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
WORKDIR /workspace
ENTRYPOINT ["/entrypoint.sh"]
CMD ["bash"]
ポイント
ARG UBUNTU_VERSION=22.04
FROM ubuntu:${UBUNTU_VERSION}
- ベースOS
- Ubuntu のバージョン固定。
ARG WEST_VERSION
ARG ZEPHYR_SDK_VERSION
- ビルド引数
- ビルド時だけ渡される値(コンテナ実行時には自動では残らない)
- ただし後段で ENV 化しているものは実行時にも残る
ENV ZEPHYR_TOOLCHAIN_VARIANT=zephyr
ENV ZEPHYR_SDK_INSTALL_DIR=/opt/zephyr-sdk-${ZEPHYR_SDK_VERSION}
- 環境変数
- Zephyr が「Zephyr SDK を使う」前提の指定
- ZEPHYR_SDK_INSTALL_DIR は ツールチェーンの場所として west/cmake 側が参照
RUN apt-get update && apt-get install -y ...
- 必要パッケージ
- Zephyr 公式の Getting Started 相当のツール群
- cmake/ninja/gperf/dtc/python3/... が核
- rm -rf /var/lib/apt/lists/* はイメージサイズ削減
python3 -m venv /opt/zephyr/.venv
pip install west==${WEST_VERSION} ...
ENV PATH="/opt/zephyr/.venv/bin:${PATH}"
- Python venv + west
- OS の Python と依存関係を汚さない
- west をバージョン固定
- PATH に venv を入れて 常に venv の west を使う
wget ... zephyr-sdk-${ZEPHYR_SDK_VERSION}_linux-x86_64.tar.xz
tar -xf ... -C /opt
/opt/zephyr-sdk-${ZEPHYR_SDK_VERSION}/setup.sh -t all -h -c
- Zephyr SDK の導入
- SDK を /opt 配下に展開し、セットアップ
- -t all は全ターゲット導入(サイズ増だが簡単)
- 一番時間がかかる箇所
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["bash"]
- entrypoint
- コンテナ起動時に必ず entrypoint が走る
- 何も指定しないと bash が起動
④-4 entrypoint.sh(初回のみ west init)
- ボリューム上に Zephyr workspace を初期化
- 初回だけ west init/update を走らせて、次回以降はスキップ
#!/usr/bin/env bash
set -e
WORKSPACE=/workspace/zephyrproject
# west は venv のものを使う
export PATH="/opt/zephyr/.venv/bin:${PATH}"
export ZEPHYR_TOOLCHAIN_VARIANT=zephyr
export ZEPHYR_SDK_INSTALL_DIR=${ZEPHYR_SDK_INSTALL_DIR}
if [ ! -d "${WORKSPACE}/.west" ]; then
echo ">>> First time setup: initializing Zephyr workspace"
mkdir -p ${WORKSPACE}
cd ${WORKSPACE}
west init -m https://github.com/zephyrproject-rtos/zephyr.git ${ZEPHYR_VERSION}
west update
west zephyr-export
else
echo ">>> Zephyr workspace already initialized – skipping west update"
fi
exec "$@"
ポイント
WORKSPACE=/workspace/zephyrproject
mkdir -p "${WORKSPACE}"
cd "${WORKSPACE}"
- Compose の named volume がマウントされる場所
- ここに .west/ ができれば「初期化済み」と判定できる
if [ ! -d ".west" ]; then
west init ... --mr "${ZEPHYR_VERSION}" .
west update
west zephyr-export
fi
- .west が無い → 初回 → workspace 作成
- --mr "${ZEPHYR_VERSION}" が Zephyr のタグ/ブランチ固定の肝
- west zephyr-export は環境変数等を整える処理
exec "$@"
- entrypoint 自身は最後に「ユーザーが指定したコマンド」を実行する
- 例:docker compose run ... echo OK の echo OK がここで動く
④ Zephyrサンプル実行手順
④-1. 前回環境削除 ※ 環境を完全に初期状態に戻したいとき専用
- Compose で作成した コンテナ・ネットワーク・named volume をすべて削除
- zephyr-workspace / zephyr-cache も消えるため、次回起動時に west init / west update が必ず再実行される
docker compose down -v
④-2. ビルド
docker compose build --no-cache
- Docker イメージを キャッシュを使わずに再ビルド
- 通常運用では --no-cache は不要(時間がかかる)
④-3. コンテナ初回起動
docker compose run --rm zephyr echo OK
- zephyr サービスのコンテナを 1回だけ起動して即終了
- 実行前に entrypoint.sh が必ず走るため:
- west workspace 初期化
- Zephyr ソース取得
- Python 依存関係セットアップ
が正常に完了するかの スモークテスト
- OK が表示されれば 環境構築フェーズは成功
④-4. Zephyr サンプルアプリビルド
docker compose run --rm zephyr \
bash -c "cd /workspace/zephyrproject && \
west build -t run -d build"
- Zephyr の hello_world サンプルを初回ビルド
- -b qemu_x86
- ターゲットボードを QEMU(x86) に指定
- -d build
- ビルド成果物を /workspace/zephyrproject/build に固定
- named volume 上に残るため、次回コマンドから再利用可能
- CMake 設定+初回コンパイルがここで行われる
④-4. Zephyr サンプルアプリ実行
docker compose run --rm zephyr \
bash -c "cd /workspace/zephyrproject && \
west build -t run -d build"
- 直前に作成した build/ を使って QEMU 実行
- -t run
- CMake の run ターゲットを呼び出す
- 内部的には qemu-system-x86 が起動
- -d build
- どの build ディレクトリを使うかを明示
- 成功すると QEMU コンソールに以下が表示される。
Hello World! qemu_x86