🚀

mise + uv + dbt-coreで、ゼロから爆速でdbtの環境構築

に公開
4

Summary

  1. miseで、ローカルマシン上のPythonバージョンを管理
  2. uvで、プロジェクトごとのPythonパッケージを管理
  3. dbt-coreで、dbtプロジェクトの開発環境を管理

上記の構成でdbtの環境構築をスムーズに完了できたので、手順を紹介します。
Python開発は不慣れですが、過去pipcondaで頑張っていた時と比較して、以下のメリットを実感できました。

  • 実行すべきコマンド数が少ない。
  • OSデフォルトのPython構成を汚さない。
  • Python特有のvenvのactivate/deactivateを(ほとんど)意識する必要がない。
  • mise, uvともにRust製で高速。

各ツールについて、詳細な機能・挙動・設定はAppendix以下に付記しています。
「細けぇこたぁいいんだよ!」「とりあえず最速で動かしたい」という方は読み飛ばしてOKです。

ツール間の責任範囲のイメージ

# miseに言語処理系レベルのバージョン管理を統一(asdfのalternative)
# uvにプロジェクトレベルの依存管理を統一(pipのalternative)
mise (replace asdf)
|-> Python 3.13 + uv(replace pip) -> dbt_project_A
|-> Python 3.12 + uv(replace pip) -> dbt_project_B
...

Environment

  • macOS Sequoia 15.4.1
  • zsh 5.9 (arm64-apple-darwin24.0)

Procedures

1. mise, Pythonのインストール

miseは、以下の機能を提供するRust製のCLIツールです。

  1. 言語処理系のインストールとバージョン管理(asdfとの互換性もアリ)
  2. 環境変数の管理
  3. タスクランナー

ここでは1の機能に着目し、Pythonのインストールに利用します。
asdfの後継ツールとして扱い、miseにローカル言語処理系のバージョン管理を(Python以外も含めて)統一的に任せる設計です。

まずは早速miseをインストールしていきます。macOSなのでHomebrewを使います。

$ brew install mise

$ mise -V
              _                                        __
   ____ ___  (_)_______        ___  ____        ____  / /___ _________
  / __ `__ \/ / ___/ _ \______/ _ \/ __ \______/ __ \/ / __ `/ ___/ _ \
 / / / / / / (__  )  __/_____/  __/ / / /_____/ /_/ / / /_/ / /__/  __/
/_/ /_/ /_/_/____/\___/      \___/_/ /_/     / .___/_/\__,_/\___/\___/
                                            /_/                 by @jdx
2025.5.2 macos-arm64 (2025-05-07)

miseのバージョン情報が確認できればOKです。

次にmise管理下に、Python処理系をインストールします。
miseから利用可能なバージョンの一覧は以下で取得できます。

$ mise ls-remote python
...
...
3.12.10
3.13.0
3.13-dev
3.13.1
3.13.2
3.13.3
3.14.0b1
3.14-dev
3.15-dev

ここでは、執筆時点の最新安定版であるPython 3.13.3をインストールしてみましょう。
構文はmise use <runtime>@<version>です。
-gオプションを付与して実行すると、そのバージョンがグローバルとして指定されます。

$ mise use -g python@3.13.3

$ python3 --version
Python 3.13.3

$ which python3
/Users/<your-name>/.local/share/mise/installs/python/3.13.3/bin/python3

mise use成功後にpython3のバージョンが切り替わっていればOKです✅

Appendix

複数バージョンの管理

グローバルインストールに成功すると~/.config/mise/config.tomlが生成され、インストールしたツール(ここではPython)のバージョンが指定されていることが確認できます。

$ cat ~/.config/mise/config.toml
[tools]
python = "3.13.3"

基本的には、このファイルがグローバル設定として扱われます。

プロジェクト毎のバージョン指定を行いたければ、-gオプションを外してmise useすればOKです。
./mise.tomlが生成され、実行した通りのバージョンが指定されます。
mise管理下に該当バージョンが無い場合は、先にインストールが実行されます)

$ mise use python@3.11.12

$ cat mise.toml
[tools]
python = "3.11.12"

mise ls <tool>で、インストールしたツール別に以下の情報を一覧できます。

  1. ツール名
  2. インストールしたバージョン
  3. (現在アクティブなもののみ)バージョンを定義したファイルのPATH
  4. (現在アクティブなもののみ)3で指定されたバージョン
$ mise ls python
Tool    Version  Source                      Requested
python  3.11.12
python  3.12.10
python  3.13.3   ~/.config/mise/config.toml  3.13.3

使わなくなったバージョンは、mise unuse <tool>@<version>でアンインストールできます。

mise.toml

miseは、グローバルからカレントディレクトリまでconfigとなる.tomlファイルを走査し、競合する設定がある場合は狭いスコープの記述を優先して参照します。

設定ファイルの命名ルールはこちらを参照してください。

miseの設定ファイルを一覧し、読み込み順を確認するにはmise cfgを実行しましょう。

$ pwd
~/Work/hoge

$ mise cfg
Path                         Tools
~/.config/mise/config.toml   python # グローバルのPythonバージョン定義
~/Work/hoge/mise.toml        python # プロジェクトのPythonバージョン定義(優先)
idiomatic version files

mise.python-versionなどの言語固有のバージョン定義ファイル(idiomatic version files)との互換性も備えています。

カレントディレクトリにmise.toml.python-versionが並存する場合は前者が優先されますが、mise.tomlが無い場合は.python-verisonに従ってPythonバージョンを決定します。

miseでローカルのPythonを管理しているが、他のツールでバージョン定義を行っているプロジェクトに途中参加する、といった場合に有益でしょう。

Note: 2025/05現在、idiomatic version filesがあると以下のWARNINGが出ます。

mise WARN  deprecated [idiomatic_version_file_enable_tools]:
Idiomatic version files like <your-file-path> are currently enabled by default. However, this will change in mise 2025.10.0 to instead default to disabled.

You can remove this warning by explicitly enabling idiomatic version files for python with:

    mise settings add idiomatic_version_file_enable_tools python

You can disable idiomatic version files with:

    mise settings add idiomatic_version_file_enable_tools "[]"

See https://github.com/jdx/mise/discussions/4345 for more information.

「現在はデフォルトでidiomatic version filesとの互換がenableになっているが、10月以降はデフォルトがdisableになる」との趣旨です。
ガイドに従ってidiomatic version filesの扱いを明示的に設定し、WARNINGを解消しましょう。

mise activate

miseで上記の設定ヒエラルキーとカレントディレクトリに応じて自動的にバージョンを切り替え、コマンドのPATHに反映させるには、mise activateの実行が必要です。

シェル起動時にトリガーされるように、公式推奨の通りrcファイルに追記しましょう。

$ echo 'eval "$(mise activate zsh)"' >> ~/.zshrc
autocompletion

mise -hすると分かるように、miseは多機能ゆえに多数のサブコマンドが用意されています。
shell上でこれらの自動補完(autocompletion)を有効化するには、利用しているshellに応じて公式のガイドに従ってください。

例えばbrewでzsh-completionsを入れている場合だとこうなります。

# mise用の補完スクリプトをzsh-completionsのディレクトリ(ここではhomebrew配下)に配置
$ mise completion zsh > /opt/homebrew/share/zsh-completions/_mise

2. uvのインストール

uvは、Astralによって開発されている、Rust製のPythonパッケージマネージャーです。
pippoetry等の類似ツールに対して10倍以上高速である、と謳われています。
pipのみならず、curlbrew経由でも独立したCLIツールとしてインストールでき、uv上でPython処理系自体のバージョン管理を行うこともできます。

ここでは、純粋にパッケージマネージャーとして利用します。

では、PyPIからuvをインストールしましょう。
このpipは、前項でmiseから入れたPython由来なので、OSのPythonから隔離されたmise管理下にバイナリをインストールできます。

$ which pip
/Users/<your-name>/.local/share/mise/installs/python/3.13.3/bin/pip

$ pip install uv

$ uv -V
uv 0.7.3 (3c413f74b 2025-05-07)

uvのバージョンが確認できればOKです✅

では、ディレクトリを作成し、uv initでPythonプロジェクトを初期化しましょう。

$ uv init <your-project>

./<your-project>uv経由で作成されたファイルが展開されています。

$ cd <your-project>

$ tree -aL 1
.
├── .git
├── .gitignore
├── .python-version
├── main.py
├── pyproject.toml
└── README.md

この後は、このPythonプロジェクトをもとにdbtプロジェクトを構成します。

Appendix

Pythonバージョンの指定

本記事の手順は、グローバルのPythonを利用する前提で説明しています。
チーム作業前提など、プロジェクト固有のPythonバージョンを指定する場合は、このように進めると良いでしょう。

# 専用ディレクトリを作成
$ mkdir hoge
$ cd hoge
# miseでPythonをインストールし、プロジェクトスコープでバージョン指定
$ mise use python@3.11.12
# プロジェクトスコープのPythonにuvをインストールして、Pythonプロジェクトを初期化
$ pip install uv
$ uv init
# miseを入れていればmise.tomlで、そうでなければ.python-versionでバージョンが決定される
$ tree -aL 1
.
├── .git
├── .gitignore
├── .python-version
├── main.py
├── mise.toml
├── pyproject.toml
└── README.md

3. dbt-coreのインストール

dbtとは、データ基盤の構築・運用プロセスにおいて活用される、デファクトスタンダードのデータ変換ツールです。
任意のデータウェアハウス(DWH)インスタンスと接続し、DWH上に読み込まれたデータを可視化・集計・分析に適した形に加工するために使われています。
SaaSであるdbt CloudとOSSであるdbt Coreがありますが、ここではdbt Coreを使います。

さて、いよいよdbt-coreをインストールしましょう。前項で導入したuvを活用します。
uv add <pkg>でプロジェクトの依存関係を追加し、uv run <bundled-excutable>でパッケージ同梱のコマンドを実行できます。

$ uv add dbt-core
Resolved 52 packages in 109ms
Installed 50 packages in 69ms
...

$ uv run dbt -V
Core:
  - installed: 1.9.4
  - latest:    1.9.4 - Up to date!

dbt-coreのバージョンが確認できればOKです✅

Appendix

(私見)pipではなくuvを選ぶ理由

dbtはpipでのPyPIパッケージ、またはDockerコンテナとしてインストール可能ですが、公式はpipの利用を推奨しています。
しかしpipを利用する場合(OS管理下かmise管理下かに関わらず)、パッケージにバンドルされたdbtコマンドを実行する際は、Python特有の仮想環境(venv)のactivate/deactivateを気にする必要があります。

個人的にはvenvを常に意識せざるをえないのはどうにも肌に合わず、uv run dbt <subcommand>で透過的に実行できる方が好みでした。

(dbt公式も、Pythonの仮想環境の説明にインストールページの大半を割いています……)

uv runすると.venvが作成されることから分かる通り、uvも仮想環境の仕組みを利用してパッケージ管理を行っているのですが、主要なユースケースにおいてほとんど隠蔽されているのはありがたいです。

poetry等でも同様の機能はありますが、実行スピードの点でuvに優位性がありそうですね。

4. dbtプロジェクトの立ち上げ

ではいよいよ、dbtプロジェクトを立ち上げていきましょう!🔥

adaptorのインストール

dbtは上述の通り、すでにデータがロードされたDWHの存在を前提とします。
主要なDWH, DB製品向けのadaptorが存在するので、まずは環境に応じて追加しましょう。
本記事ではローカルのpostgresを使うので、dbt-postgresを追加します。

$ uv add dbt-postgres 

$ uv run dbt -V
Core:
  - installed: 1.9.4
  - latest:    1.9.4 - Up to date!

Plugins:
  - postgres: 1.9.0 - Up to date!

dbt init

語弊を恐れず言うと、dbtはデータ加工処理を行うためのフレームワークです。
いくつもの.ymlファイル、.sqlファイルの利用が前提となっており、公式がベストプラクティスとして推奨するディレクトリ構成があります。

dbt initコマンドを使うことで、これに準じたプロジェクトを一発で構成できます。

$ uv run dbt init <your-dbt-project>

$ tree
.
├── <your-dbt-project>
│   ├── analyses
│   ├── dbt_project.yml
│   ├── macros
│   ├── models
│   │   └── example
│   │       ├── my_first_dbt_model.sql
│   │       ├── my_second_dbt_model.sql
│   │       └── schema.yml
│   ├── README.md
│   ├── seeds
│   ├── snapshots
│   └── tests
├── logs
│   └── dbt.log
├── main.py
├── mise.toml
├── pyproject.toml
├── README.md
└── uv.lock

実行すると、導入済みのadaptorに応じたpromptが表示され、回答していくと~/.dbt/profiles.yml<your-dbt-project>と同名のprofileが書き込まれます。
すでに~/.dbt/profiles.ymlにprofileを設定済みで、既存のprofileを参照したい場合は、dbt init --profile <your-profile-name>を実行しましょう。

ちなみに、adaptorが1つもinstallされていない場合はRuntime Error No adapters available.が出ますが、上掲のような雛形は問題なく作成されます。

動作確認

では、最後のステップです!

dbtプロジェクト上でdbt debugすると、基本的な項目についてテストを実行してくれます。

$ uv run dbt debug
04:57:59  Running with dbt=1.9.4
04:57:59  dbt version: 1.9.4
04:57:59  python version: 3.11.12
04:57:59  python path: /Users/<your-name>/<your-project>/.venv/bin/python
04:57:59  os info: macOS-15.4.1-arm64-arm-64bit
04:57:59  Using profiles dir at /Users/<your-name>/.dbt
04:57:59  Using profiles.yml file at /Users/<your-name>/.dbt/profiles.yml
04:57:59  Using dbt_project.yml file at /Users/<your-name>/<your-project>/<your-dbt-project>/dbt_project.yml
04:57:59  adapter type: postgres
04:57:59  adapter version: 1.9.0
04:57:59  Configuration:
04:57:59    profiles.yml file [OK found and valid]
04:57:59    dbt_project.yml file [OK found and valid]
04:57:59  Required dependencies:
04:57:59   - git [OK found]

04:57:59  Connection:
04:57:59    host: localhost
04:57:59    port: 5432
04:57:59    user: postgres
04:57:59    database: postgres
04:57:59    schema: public
04:57:59    connect_timeout: 10
04:57:59    role: None
04:57:59    search_path: None
04:57:59    keepalives_idle: 0
04:57:59    sslmode: None
04:57:59    sslcert: None
04:57:59    sslkey: None
04:57:59    sslrootcert: None
04:57:59    application_name: dbt
04:57:59    retries: 1
04:57:59  Registered adapter: postgres=1.9.0
04:57:59    Connection test: [OK connection ok]

04:57:59  All checks passed!

All checks passed!が出ればOKです、お疲れ様でした!😊

Appendix

dbt initの挙動

v1.9.4時点で、dbt initは必ずサブディレクトリを作成して、その中にdbtプロジェクトのファイルを展開します。
dbt initがカレントディレクトリを直接dbtプロジェクト化できるようなoptionが要望されていますが、執筆段階ではまだ実装されていません。

VSCodeのdbt extension

他のメジャーな言語やツールと同様、dbt-power-userというVSCodeの拡張機能が存在します。
コード補完、コードランナーなど主要な便利機能を使えますが、2点ほど注意が必要です。

  1. VSCodeのPython Interpreterには、uvが構成したvenv配下のPythonのpathを指定する
    • ex. <your-project>/.venv/bin/python
    • dbtは、uv addによって仮想環境下の依存関係として管理されているため
  2. profile定義のymlファイルは~/.dbt/profiles.ymlに配置する
    • dbt-core自体は以下の優先度でprofileを認識するが、拡張のdiagnosisは4のみを想定していると思われる
      1. --profiles-dir option
      2. DBT_PROFILES_DIR environment variable
      3. current working directory
      4. ~/.dbt/ directory

Conclusion

以上で、ゼロベースでdbtプロジェクトの立ち上げまで完了できました!
乱暴に言えば、これら数コマンドのみでdbt開発の準備が整ったわけですね👍

  1. mise use -g python@3.x.x
  2. uv init
  3. uv add dbt-<xx>
  4. uv run dbt init

本記事がどなたかの参考になれば幸いです。
Happy modeling!

References

Discussion

uasiuasi

uv も mise でインストールしておくと mise up でまとめてアップデートできて便利です。

mise use -g uv
soomattsusoomattsu

おお、知らなかったです。
本記事では、以下のようにツール間の責任範囲を明確に分けたかったのでアプローチが異なりますが、環境によってはそちらの方がシンプルかもですね。ありがとうございます!

# miseに言語処理系レベルのバージョン管理を統一
# uvにプロジェクトレベルの依存管理を統一(pipのalternative)
mise
|-> Python 3.13 + uv(replace pip)
|-> Python 3.12 + uv(replace pip)
...
syakesabasyakesaba

uvでpythonバージョン管理できますが、何故miseを使うんですか?

soomattsusoomattsu

uvでpythonバージョン管理できますが、何故miseを使うんですか?

miseはPython以外の言語も一元的に管理できるから」ですかね。本文記載の通り、asdfを互換するような用途で導入しました。

IMHOですが、言語ごとにバージョン管理ツールが分かれているとローカル開発環境の管理が煩雑なんですよね。
おっしゃる通りuvではPythonインストール&バージョン切り替えも可能なので、Pythonオンリーの環境であればハナからuvでやるのもいいと思います!