開発環境構築ツール「devbox」を試す
2024/10のTechnology RaderでTrialになってた。
今のところ、自分の場合:
- 環境閉じ込めたい場合はDocker。devcontainerで使うことも多い。
- Pythonだけならmise+venv。最初、mise+uvにしてたんだけど、
いつのまにかPythonバージョンがおかしくなってしまうようになったので、uvはやめた。 自分が正しくuvを理解していないのもあるが、miseだけで困ってない。 - VMが欲しいときはmultipassだけどかなり頻度が少ない
って感じで困ってはいないけど、Dockerfileとかdocker-compose.yaml書くのがめんどくさいなと思うときはあるので、devboxを試してみる。
GitHubレポジトリ
Devbox
瞬時に、簡単で予測可能な開発環境
これは何?
Devboxは、開発用に隔離されたシェルを簡単に作成できるコマンドラインツールです。まず、開発環境に必要なパッケージのリストを定義し、その定義に基づいてDevboxがアプリケーション専用の隔離された環境を作成します。
実際のところ、Devboxは
yarn
のようなパッケージマネージャーと似た動作をしますが、管理するパッケージはオペレーティングシステムレベルのものです(通常、brew
やapt-get
でインストールするようなものです)。Devboxを使うと、Nixパッケージレジストリから40万以上のパッケージバージョンをインストールすることができます。DevboxはもともとJetifyによって開発され、内部では
nix
が使用されています。
利点
チーム全員に一貫したシェル環境
プロジェクトで必要なツールのリストを
devbox.json
ファイルで宣言し、devbox shell
を実行するだけ。プロジェクトに取り組むすべてのメンバーが、同じバージョンのツールを使用できるシェル環境を手に入れます。ラップトップを汚さずに新しいツールを試せる
Devboxが作成する開発環境は、ラップトップ上の他のすべてのものから隔離されています。試してみたいツールがあるけど、ラップトップを汚したくない?そんな時は、そのツールをDevboxのシェルに追加して、不要になったら削除すればOK。ラップトップは常にクリーンなままです。
スピードを犠牲にしない
Devboxは、ラップトップ上に仮想化の余計なレイヤーを追加せず、ファイルシステムやコマンドの速度を落とさずに隔離された環境を作成します。プロジェクトの出荷準備が整ったら、それをコンテナに変換できますが、その時まで速度は維持されます。
バージョンの競合にさようなら
複数のプロジェクトで、同じバイナリの異なるバージョンが必要ですか?ラップトップに競合するバージョンをインストールする代わりに、プロジェクトごとに隔離された環境を作成し、各プロジェクトで必要なバージョンを自由に使用できます。
環境を持ち運べる
Devboxの開発環境はポータブルです。環境を一度だけ正確に宣言し、その単一の定義を以下のように複数の方法で活用できます:
- ローカルで
devbox shell
を使ってシェルを作成- VSCodeで使用するdevcontainer
- 開発と同じツールを使って本番イメージを作成できるDockerfile
- ローカル環境をそのまま反映したクラウド上のリモート開発環境
ライセンスはApache-2.0
インストール
ローカルのMacでやってみる。
インストールはリモートのスクリプトを実行する形式。自分はこのタイプ、何をやるのかがわからないので、あまり好きではない。一旦中身を見てみる。
$ curl -fsSL https://get.jetify.com/devbox
インストールスクリプトの中身
#!/bin/bash
#
# Install script
#
# Downloads and installs a binary from the given url.
set -euo pipefail
# ========================
# Customize install script
# ========================
# This script is published at get.jetify.com/devbox so users can install via:
# curl -fsSL https://get.jetify.com/devbox | bash
readonly INSTALL_DIR="/usr/local/bin"
readonly BIN="devbox"
readonly DOWNLOAD_URL="https://releases.jetify.com/devbox"
readonly TITLE="Devbox 📦 by Jetify"
readonly DESCRIPTION=$(
cat <<EOF
Instant, easy and predictable development environments.
This script downloads and installs the latest devbox binary.
EOF
)
readonly DOCS_URL="https://github.com/jetify-com/devbox"
readonly COMMUNITY_URL="https://discord.gg/jetify"
# ====================
# flags.sh
# ====================
FORCE="${FORCE:-0}"
parse_flags() {
while [ "$#" -gt 0 ]; do
case "$1" in
-f | --force)
FORCE=1
shift 1
;;
*)
error "Unknown option: $1"
exit 1
;;
esac
done
}
# ====================
# format.sh
# ====================
readonly BOLD="$(tput bold 2>/dev/null || echo '')"
readonly GREY="$(tput setaf 8 2>/dev/null || echo '')"
readonly UNDERLINE="$(tput smul 2>/dev/null || echo '')"
readonly RED="$(tput setaf 1 2>/dev/null || echo '')"
readonly GREEN="$(tput setaf 2 2>/dev/null || echo '')"
readonly YELLOW="$(tput setaf 3 2>/dev/null || echo '')"
readonly BLUE="$(tput setaf 4 2>/dev/null || echo '')"
readonly MAGENTA="$(tput setaf 5 2>/dev/null || echo '')"
readonly CYAN="$(tput setaf 6 2>/dev/null || echo '')"
readonly NO_COLOR="$(tput sgr0 2>/dev/null || echo '')"
readonly CLEAR_LAST_MSG="\033[1F\033[0K"
title() {
local -r text="$*"
printf "%s\n" "${BOLD}${MAGENTA}${text}${NO_COLOR}"
}
header() {
local -r text="$*"
printf "%s\n" "${BOLD}${text}${NO_COLOR}"
}
plain() {
local -r text="$*"
printf "%s\n" "${text}"
}
info() {
local -r text="$*"
printf "%s\n" "${BOLD}${GREY}→${NO_COLOR} ${text}"
}
warn() {
local -r text="$*"
printf "%s\n" "${YELLOW}! $*${NO_COLOR}"
}
error() {
local -r text="$*"
printf "%s\n" "${RED}✘ ${text}${NO_COLOR}" >&2
}
success() {
local -r text="$*"
printf "%s\n" "${GREEN}✓${NO_COLOR} ${text}"
}
start_task() {
local -r text="$*"
printf "%s\n" "${BOLD}${GREY}→${NO_COLOR} ${text}..."
}
end_task() {
local -r text="$*"
printf "${CLEAR_LAST_MSG}%s\n" "${GREEN}✓${NO_COLOR} ${text}... [DONE]"
}
fail_task() {
local -r text="$*"
printf "${CLEAR_LAST_MSG}%s\n" "${RED}✘ ${text}... [FAILED]${NO_COLOR}" >&2
}
confirm() {
if [ ${FORCE-} -ne 1 ]; then
printf "%s " "${MAGENTA}?${NO_COLOR} $* ${BOLD}[Y/n]${NO_COLOR}"
set +e
read -r yn </dev/tty
rc=$?
set -e
if [ $rc -ne 0 ]; then
error "Error reading from prompt (re-run with '-f' flag to auto select Yes if running in a script)"
exit 1
fi
if [ "$yn" != "y" ] && [ "$yn" != "Y" ] && [ "$yn" != "yes" ] && [ "$yn" != "" ]; then
error 'Aborting (please answer "yes" to continue)'
exit 1
fi
fi
}
delay() {
sleep 0.3
}
# =========
# util.sh
# =========
has() {
command -v "$1" 1>/dev/null 2>&1
}
download() {
local -r url="$1"
local -r file="$2"
local cmd=""
if has curl; then
cmd="curl --fail --silent --location --output $file $url"
elif has wget; then
cmd="wget --quiet --output-document=$file $url"
elif has fetch; then
cmd="fetch --quiet --output=$file $url"
else
error "No program to download files found. Please install one of: curl, wget, fetch"
error "Exiting..."
return 1
fi
if [[ ${3:-} == "--fail" ]]; then
$cmd && return 0 || rc=$?
error "Command failed (exit code $rc): ${BLUE}${cmd}${NO_COLOR}"
exit $rc
fi
$cmd && return 0 || rc=$?
return $rc
}
# ==============
# Implementation
# ==============
intro_msg() {
title "${TITLE}"
plain "${DESCRIPTION}"
printf "\n"
header "Confirm Installation Details"
plain " Location: ${GREEN}${INSTALL_DIR}/${BIN}${NO_COLOR}"
plain " Download URL: ${UNDERLINE}${BLUE}${DOWNLOAD_URL}${NO_COLOR}"
printf "\n"
}
install_flow() {
confirm "Install ${GREEN}${BIN}${NO_COLOR} to ${GREEN}${INSTALL_DIR}${NO_COLOR} (requires sudo)?"
printf "\n"
header "Downloading and Installing"
start_task "Downloading ${BIN} binary"
local -r tmp_file=$(mktemp)
download "${DOWNLOAD_URL}" "${tmp_file}" --fail
delay
end_task "Downloading ${BIN} binary"
start_task "Installing in ${INSTALL_DIR}/${BIN} (requires sudo)"
chmod +x "${tmp_file}"
$(command -v sudo || true) bash -c "mkdir -p ${INSTALL_DIR} && mv ${tmp_file} ${INSTALL_DIR}/${BIN}"
delay
end_task "Installing in ${INSTALL_DIR}/${BIN}"
delay
success "${BOLD}Successfully installed ${GREEN}${BIN}${NO_COLOR}${BOLD}${NO_COLOR} 🚀"
delay
printf "\n"
}
next_steps_msg() {
header "Next Steps"
plain " 1. ${BOLD}Learn how to use ${BIN}${NO_COLOR}"
plain " ${GREY}Run ${CYAN}${BIN} help${GREY} or read the docs at ${UNDERLINE}${BLUE}${DOCS_URL}${NO_COLOR}"
plain " 2. ${BOLD}Get help and give feedback${NO_COLOR}"
plain " ${GREY}Join our community at ${UNDERLINE}${BLUE}${COMMUNITY_URL}${NO_COLOR}"
}
main() {
parse_flags "$@"
intro_msg
install_flow
next_steps_msg
}
main "$@"
見た感じバイナリをダウンロードして配置する程度。問題なさそうなのでインストール。
$ curl -fsSL https://get.jetify.com/devbox | bash
/usr/local/bin
以下に配置されるみたい。インストールするか聞かれるので"Y"。
Devbox 📦 by Jetify
Instant, easy and predictable development environments.
This script downloads and installs the latest devbox binary.
Confirm Installation Details
Location: /usr/local/bin/devbox
Download URL: https://releases.jetify.com/devbox
? Install devbox to /usr/local/bin (requires sudo)? [Y/n] Y
sudoで確認が求められるのでパスワードを入力。
Downloading and Installing
✓ Downloading devbox binary... [DONE]
→ Installing in /usr/local/bin/devbox (requires sudo)...
Password:
インストール完了
Installing in /usr/local/bin/devbox... [DONE]
✓ Successfully installed devbox 🚀
Next Steps
1. Learn how to use devbox
Run devbox help or read the docs at https://github.com/jetify-com/devbox
2. Get help and give feedback
Join our community at https://discord.gg/jetify
バージョンを確認してみる。
$ devbox version
✓ Downloading version 0.13.5... [DONE]
✓ Verifying checksum... [DONE]
✓ Unpacking binary... [DONE]
0.13.5
Usage
$ devbox help
Instant, easy, predictable development environments
Usage:
devbox [flags]
devbox [command]
Available Commands:
add Add a new package to your devbox
auth Devbox auth commands
cache Collection of commands to interact with nix cache
completion Generate the autocompletion script for the specified shell
create Initialize a directory as a devbox project using a template
generate Generate supporting files for your project
global Manage global devbox packages
help Help about any command
info Display package info
init Initialize a directory as a devbox project
install Install all packages mentioned in devbox.json
list List installed packages
rm Remove a package from your devbox
run Run a script or command in a shell with access to your packages
search Search for nix packages
secrets Interact with devbox secrets in jetify cloud.
services Interact with devbox services.
shell Start a new shell with access to your packages
shellenv Print shell commands that create a Devbox Environment in the shell
update Update packages in your devbox
version Print version information
Flags:
-h, --help help for devbox
-q, --quiet suppresses logs
Use "devbox [command] --help" for more information about a command.
開発環境の作成
開発環境を作成してみる。
適当なディレクトリを作成。
$ mkdir devbox-test && cd devbox-test
devbox init
で環境の初期設定。
$ devbox init
ディレクトリ内にdevbox.json
が作成される。コード管理する場合はこのファイルも含めればよいみたい。
$ ls
devbox.json
{
"$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.13.5/.schema/devbox.schema.json",
"packages": [],
"shell": {
"init_hook": [
"echo 'Welcome to devbox!' > /dev/null"
],
"scripts": {
"test": [
"echo \"Error: no test specified\" && exit 1"
]
}
}
}
この環境にパッケージをインストールする。パッケージはdevbox search
で検索できる。試しにpythonのパッケージを検索してみる。
$ devbox search python3
Found 40+ results for "python3":
* python (3.13.0, 3.13.0rc3, 3.13.0rc2, 3.13.0rc1, 3.13.0b4, 3.13.0b3, 3.13.0b2, 3.13.0b1, 3.13.0a6, 3.13.0a5 ...)
* gnatcoll-python3 (24.0.0, 23.0.0, 22.0.0, 21.0.0)
* python310Packages.avro-python3 (1.10.2)
* python310Packages.mecab-python3 (1.0.8, 1.0.7, 1.0.6, 1.0.5, 1.0.4)
* python310Packages.python3-application (3.0.6, 3.0.4, 3.0.3)
* python310Packages.python3-eventlib (0.3.0)
* python310Packages.python3-gnutls (3.1.9)
* python310Packages.python3-openid (3.2.0)
* python310Packages.python3-saml (1.15.0, 1.14.0, 1.12.0)
* python311Packages.avro-python3 (1.10.2)
Warning: Showing top 10 results and truncated versions. Use --show-all to show all.
Node.jsだとこんな感じ。
$ devbox search nodejs
Found 3+ results for "nodejs":
* nodejs (22.9.0, 22.8.0, 22.6.0, 22.5.1, 22.4.1, 22.3.0, 22.2.0, 22.0.0, 21.7.3, 21.7.2 ...)
* nodejs-slim (22.9.0, 22.8.0, 22.6.0, 22.5.1, 22.4.1, 22.3.0, 22.2.0, 22.0.0, 21.7.3, 21.7.2 ...)
* nodejs_latest (19.7.0, 19.1.0, 19.0.1, 18.4.0, 18.3.0, 18.2.0, 18.1.0, 18.0.0, 16.14.2, 16.14.0 ...)
Warning: Showing top 10 results and truncated versions. Use --show-all to show all.
少しインフラ的なものを試してみる。
$ devbox search postgres
Found 25+ results for "postgres":
* postgres-lsp (0-unstable-2024-03-24, 2024-01-11, 2023-10-20, 2023-09-21, 2023-08-23, 2023-08-08)
* gnatcoll-postgres (24.0.0, 23.0.0, 22.0.0, 21.0.0)
* prometheus-postgres-exporter (0.15.0, 0.14.0, 0.13.2, 0.13.1, 0.13.0, 0.12.1, 0.12.0, 0.11.1, 0.11.0, 0.10.1 ...)
* postgresql (16.4, 15.7, 15.6, 15.5, 15.4, 14.9, 14.8, 14.7, 14.6, 14.5 ...)
* postgresql95 (9.5.25, 9.5.24, 9.5.23, 9.5.22, 9.5.21)
* postgresql96 (9.6.24, 9.6.23, 9.6.22, 9.6.21, 9.6.20, 9.6.19, 9.6.18, 9.6.17)
* postgresqlTestHook
* postgrest (12.0.2)
* postgresql_10 (10.22, 10.21, 10.20, 10.19, 10.18, 10.17, 10.16, 10.15, 10.14, 10.13 ...)
* postgresql_11 (11.21, 11.20, 11.19, 11.18, 11.17, 11.16, 11.15, 11.14, 11.13, 11.12 ...)
Warning: Showing top 10 results and truncated versions. Use --show-all to show all.
ライブラリよりなものも。
$ devbox search openai
Found 28+ results for "openai":
* openai (1.51.0, 1.50.2, 1.47.1, 1.46.0, 1.45.1, 1.44.0, 1.43.0, 1.42.0, 1.40.8, 1.39.0 ...)
* openai-full (0.28.1, 0.28.0, 0.27.8, 0.27.7, 0.27.6v2, 0.27.5, 0.27.4, 0.27.2, 0.27.1, 0.27.0)
* openai-whisper (20240930, 20240927, 20231117, 20230918, 20230314, 20230124, 2022-09-30, 2022-09-23)
* openai-triton-llvm (17.0.0-c5dede880d17, 14.0.6-f28c006a5895)
* openai-whisper-cpp (1.7.0, 1.6.2, 1.5.4, 1.5.2, 1.4.2, 1.4.0, 1.2.1, 1.2.0, 1.0.4)
* python310Packages.openai (1.6.1, 1.6.0, 1.5.0, 1.3.7, 0.28.1, 0.28.0, 0.27.9, 0.27.8, 0.27.7, 0.27.6v2 ...)
* python311Packages.openai (1.51.0, 1.50.2, 1.47.1, 1.46.0, 1.45.1, 1.44.0, 1.43.0, 1.42.0, 1.40.8, 1.39.0 ...)
* python312Packages.openai (1.51.0, 1.50.2, 1.47.1, 1.46.0, 1.45.1, 1.44.0, 1.43.0, 1.42.0, 1.40.8, 1.39.0 ...)
* python38Packages.openai (0.11.5, 0.11.4)
* python39Packages.openai (0.25.0, 0.24.0, 0.23.1, 0.23.0, 0.22.1, 0.22.0, 0.20.0, 0.19.0, 0.18.1, 0.18.0 ...)
Warning: Showing top 10 results and truncated versions. Use --show-all to show all.
なるほど、いろいろあるけど、これがnixパッケージというやつなのかな?ちょっとまだよくわからないけど、とりあえずまずはpython-3.11をインストールしてみる。パッケージ追加はdevbox add
。
$ devbox add python@3.11
Nixがないのでインストールする。
Nix is not installed. Devbox will attempt to install it.
Press enter to continue or ctrl-c to exit.
Nixインストール時のメッセージ
Switching to the Multi-user Installer
Welcome to the Multi-User Nix Installation
This installation tool will set up your computer with the Nix package
manager. This will happen in a few stages:
1. Make sure your computer doesn't already have Nix. If it does, I
will show you instructions on how to clean up your old install.
2. Show you what I am going to install and where. Then I will ask
if you are ready to continue.
3. Create the system users (uids [351..382]) and groups (gid 350)
that the Nix daemon uses to run builds. To create system users
in a different range, exit and run this tool again with
NIX_FIRST_BUILD_UID set.
4. Perform the basic installation of the Nix files daemon.
5. Configure your shell to import special Nix Profile files, so you
can use Nix.
6. Start the Nix daemon.
Would you like to see a more detailed list of what I will do?
No TTY, assuming you would say yes :)
I will:
- make sure your computer doesn't already have Nix files
(if it does, I will tell you how to clean them up.)
- create local users (see the list above for the users I'll make)
- create a local group (nixbld)
- install Nix in /nix
- create a configuration file in /etc/nix
- set up the "default profile" by creating some Nix-related files in
/var/root
- back up /etc/bashrc to /etc/bashrc.backup-before-nix
- update /etc/bashrc to include some Nix configuration
- back up /etc/zshrc to /etc/zshrc.backup-before-nix
- update /etc/zshrc to include some Nix configuration
- create a Nix volume and a LaunchDaemon to mount it
- create a LaunchDaemon (at /Library/LaunchDaemons/org.nixos.nix-daemon.plist) for nix-daemon
Ready to continue?
No TTY, assuming you would say yes :)
---- let's talk about sudo -----------------------------------------------------
This script is going to call sudo a lot. Normally, it would show you
exactly what commands it is running and why. However, the script is
run in a headless fashion, like this:
$ curl -L https://nixos.org/nix/install | sh
or maybe in a CI pipeline. Because of that, I'm going to skip the
verbose output in the interest of brevity.
If you would like to
see the output, try like this:
$ curl -L -o install-nix https://nixos.org/nix/install
$ sh ./install-nix
~~> Fixing any leftover Nix volume state
Before I try to install, I'll check for any existing Nix volume config
and ask for your permission to remove it (so that the installer can
start fresh). I'll also ask for permission to fix any issues I spot.
~~> Checking for artifacts of previous installs
Before I try to install, I'll check for signs Nix already is or has
been installed on this system.
---- Nix config report ---------------------------------------------------------
Temp Dir: /var/folders/5z/mnlc5_7x5dv8r528s4sg1h2r0000gn/T/tmp.70NujKP1Do
Nix Root: /nix
Build Users: 32
Build Group ID: 350
Build Group Name: nixbld
build users:
Username: UID
_nixbld1: 351
_nixbld2: 352
_nixbld3: 353
_nixbld4: 354
_nixbld5: 355
_nixbld6: 356
_nixbld7: 357
_nixbld8: 358
_nixbld9: 359
_nixbld10: 360
_nixbld11: 361
_nixbld12: 362
_nixbld13: 363
_nixbld14: 364
_nixbld15: 365
_nixbld16: 366
_nixbld17: 367
_nixbld18: 368
_nixbld19: 369
_nixbld20: 370
_nixbld21: 371
_nixbld22: 372
_nixbld23: 373
_nixbld24: 374
_nixbld25: 375
_nixbld26: 376
_nixbld27: 377
_nixbld28: 378
_nixbld29: 379
_nixbld30: 380
_nixbld31: 381
_nixbld32: 382
Ready to continue?
No TTY, assuming you would say yes :)
---- Preparing a Nix volume ----------------------------------------------------
Nix traditionally stores its data in the root directory /nix, but
macOS now (starting in 10.15 Catalina) has a read-only root directory.
To support Nix, I will create a volume and configure macOS to mount it
at /nix.
インストール時のメッセージを見ると、なかなかにシステムのコアな部分に絡む様子。ちょっとビビるけど、進めてみる。パスワードを入力
~~> Configuring /etc/synthetic.conf to make a mount-point at /nix
Password:
またここから色々と出力されるのだが、最終的に以下のように表示されればOKっぽい。
Nix installed successfully. Devbox is ready to use!
でそのままpythonパッケージもインストールされる。
Info: Adding package "python@3.11" to devbox.json
Info: Installing the following packages to the nix store: python@3.11
python NOTES:
Python in Devbox works best when used with a virtual environment (venv, virtualenv, etc.). Devbox will automatically create a virtual environment using `venv` for python3 projects, so you can install packages with pip as normal.
To activate the environment, run `. $VENV_DIR/bin/activate` or add it to the init_hook of your devbox.json
To change where your virtual environment is created, modify the $VENV_DIR environment variable in your init_hook
This plugin creates the following helper files:
* /Users/kun432/work/devbox-test/.devbox/virtenv/python/bin/venvShellHook.sh
This plugin sets the following environment variables:
* VENV_DIR=/Users/kun432/work/devbox-test/.venv
* UV_PYTHON=/Users/kun432/work/devbox-test/.devbox/nix/profile/default/bin/python
To show this information, run `devbox info python`
やっと完了。devbox.jsonが更新され、pythonがパッケージに追加される。
{
"$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.13.5/.schema/devbox.schema.json",
"packages": ["python@3.11"],
"shell": {
"init_hook": [
"echo 'Welcome to devbox!' > /dev/null"
],
"scripts": {
"test": [
"echo \"Error: no test specified\" && exit 1"
]
}
}
}
また、ディレクトリ内に環境が作成されている模様。
$ tree -a
.
├── .devbox
│ └── virtenv
│ ├── bin
│ │ └── venvShellHook.sh -> /Users/kun432/work/devbox-test/.devbox/virtenv/python/bin/venvShellHook.sh
│ └── python
│ └── bin
│ └── venvShellHook.sh
├── devbox.json
└── devbox.lock
他にもパッケージを追加することができるが、一旦これで。あとpythonパッケージインストール時にvenv周りの出力が出ていたけども、そちらも後回しで。
ではこの開発環境に入る前に、現在のpythonを確認しておく。
$ which python
/Users/kun432/.pyenv/shims/python
$ python --version
Python 3.11.9
では開発環境に入る。devbox shell
を実行。
$ devbox shell
初回は何やらいろいろ処理するので時間がかかるみたい。
Info: Ensuring packages are installed.
⢿ Computing the Devbox environment...
新しいシェルが立ち上がった。ちょいちょいwarning的なものが出てくるけど、これは自分の環境依存。
Starting a devbox shell...
bash: export: `BASH_FUNC_show_virtual_env%%=() { if [ -n "VIRTUAL_ENV_PROMPT" ]; then echo "$VIRTUAL_ENV_PROMPT"; fi}': not a valid identifier
Virtual environment directory doesn't exist. Creating new one...
The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
(devbox) bash-3.2$
devbox開発環境のpythonを確認してみると、環境内のものになっている。
(devbox) bash-3.2$ which python
/Users/kun432/work/devbox-test/.devbox/nix/profile/default/bin/python
(devbox) bash-3.2$ python --version
Python 3.11.10
ただし、pipはグローバルのものを見てしまってる。
$ which pip
/Users/kun432/.pyenv/shims/pip
pipは.venv内にあるのでactivateされていないのだろうと思う。
(devbox) bash-3.2$ find . -type f -name "pip"
./.venv/bin/pip
なるほど。.venv内にもpythonはあるけど、devboxが用意したpythonへのシンボリックリンクになってる。やはりactivateが必要だと思う。
(devbox) bash-3.2$ ls -lt .venv/bin/python
lrwxr-xr-x 1 kun432 staff 69 10 26 00:16 .venv/bin/python -> /Users/kun432/work/devbox-test/.devbox/nix/profile/default/bin/python
上のpipを見てても分かる通り、グローバルな環境のものは普通に見える
(devbox) bash-3.2$ git config --get user.email
kun432@users.noreply.github.com
開発環境から抜けると元に戻っているのがわかる。
(devbox) bash-3.2$ exit
$ which python
/Users/kun432/.pyenv/shims/python
pythonの場合
以下にいろいろな環境についての例がある。
で、pythonの場合。
なるほど、init_hook
というのがあるのでここでactivateさせれば良さそう。あと、デフォルトだと.venvは.devbox/virtenv/python/.venv
になるとあるが、自分の環境だと作業ディレクトリ直下だった。
とりあえず以下のようにdevbox.jsonを修正
{
"$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.13.5/.schema/devbox.schema.json",
"packages": ["python@3.11"],
"env": {
"VENV_DIR": ".venv"
},
"shell": {
"init_hook": [
". $VENV_DIR/bin/activate"
],
"scripts": {
"test": [
"echo \"Error: no test specified\" && exit 1"
]
}
}
}
再度devbox環境に入ってみる。
$ devbox shell
環境の確認が行われる。
Info: Ensuring packages are installed.
✓ Computed the Devbox environment.
シェルプロンプトを見る限りはactivateされてるように思える。
(.venv) (devbox) bash-3.2$
確認
(.venv) (devbox) bash-3.2$ which python
/Users/kun432/work/devbox-test/.venv/bin/python
(.venv) (devbox) bash-3.2$ which pip
/Users/kun432/work/devbox-test/.venv/bin/pip
いけてそう。
とりあえずpythonについては大体使い方や設定がわかったけど、他のパッケージを使う場合はそれぞれの固有の設定はありそうなので、個別に見ていく必要は当然ありそう。
devboxをグローバルなパッケージマネージャにすることもできるみたい。
今のところ自分はMacではHomebrewでBrewfileをレポジトリ管理しているし、Ubuntuサーバは基本的にOSが提供するパッケージを使いたいと思っている。今の状況に特に不満もないのであえて変えようとは思わないけど、別の環境が用意できたら一度試してみたい。
あと、devboxについて書かれた記事を見ていると、どうやらdevbox環境からDevcontainerやDockerの設定ファイルを生成したり、あとはREADMEなんかも出力できるみたい。
参考
とりあえずREADMEを試してみる。
$ devbox generate readme
こんな感じのREADME.mdが出力される
<!-- gen-readme start - generated by https://github.com/jetify-com/devbox/ -->
## Getting Started
This project uses [devbox](https://github.com/jetify-com/devbox) to manage its development environment.
Install devbox:
```sh
curl -fsSL https://get.jetpack.io/devbox | bash
```
Start the devbox shell:
```sh
devbox shell
```
Run a script in the devbox environment:
```sh
devbox run <script>
```
## Scripts
Scripts are custom commands that can be run using this project's environment. This project has the following scripts:
* [test](#devbox-run-test)
## Environment
```sh
UV_PYTHON="/Users/kun432/work/devbox-test/.devbox/nix/profile/default/bin/python"
VENV_DIR=".venv"
```
## Shell Init Hook
The Shell Init Hook is a script that runs whenever the devbox environment is instantiated. It runs
on `devbox shell` and on `devbox run`.
```sh
/Users/kun432/work/devbox-test/.devbox/virtenv/python/bin/venvShellHook.sh
. $VENV_DIR/bin/activate
```
## Packages
* [python@3.11](https://www.nixhub.io/packages/python)
## Script Details
### devbox run test
```sh
echo "Error: no test specified" && exit 1
```
 
<!-- gen-readme end -->
あと、Devcontainerの設定ファイルも出力してみる。
$ devbox generate devcontainer
$ tree .devcontainer
.devcontainer
├── Dockerfile
└── devcontainer.json
{
"name": "Devbox Remote Container",
"build": {
"dockerfile": "./Dockerfile",
"context": ".."
},
"customizations": {
"vscode": {
"settings": {},
"extensions": [
"jetpack-io.devbox"
]
}
},
"remoteUser": "devbox"
}
$ cat .devcontainer/Dockerfile
FROM jetpackio/devbox:latest
# Installing your devbox project
WORKDIR /code
USER root:root
RUN mkdir -p /code && chown ${DEVBOX_USER}:${DEVBOX_USER} /code
USER ${DEVBOX_USER}:${DEVBOX_USER}
COPY devbox.json devbox.json
COPY devbox.lock devbox.lock
RUN devbox run -- echo "Installed Packages."
RUN devbox shellenv --init-hook >> ~/.profile
なるほど、このあたりをレポジトリに入れとけばセットアップ手順なんかも全部共有されると。これは便利かも。
まとめ
Nixは名前だけしか聞いたことがなくて、ちょっとややこしそう、という印象しかなかったけど、devboxを使う限りはあまり意識しなくて良さそう。ちょっとNixインストール時のメッセージにはビビるところもあったけども、今のところ自分の環境でも特に問題は起きてない。
とりあえずもう少し使い続けないと良さはわからないと思うけど、現時点では印象は悪くない。個人的にはまだDockerのほうが安心感はあるけど(完全に隔離されるし)、その分多少の手間はかかるので、ライトに環境用意したい場合に使ってみてもいいかなという印象。