ABEJA Tech Blog

中の人の興味のある情報を発信していきます

【年末大掃除】開発環境VMの再作成 - apt・brew・asdf・Dockerを使い分けたパッケージ管理

はじめに

プラットフォームアプリケーショングループの平原です。 こちらはABEJAアドベントカレンダー2025の21日目の記事です。 私の所属するチームでは開発環境としてGoogle Cloud上のVMを使用しています。 請求の管理のためにVMを置くGoogle Cloud プロジェクトを変更しようということになり、 VMのお引越しをすることになりました。

そこで、OSがUbuntu 22.04 LTSで少し古くなってきたのと、 これまでの開発でストレージ拡張を何度か行ってストレージが大きくなってしまっていたため、 これを機にVMを作り直すことにしました。

前の環境では、適当にインストールしてアップデートやバージョン管理がおざなりになっていたのを反省して、 移行しながら直近の業務で使うツールを管理しやすいように入れていったので、備忘録的に記事にしています。

色々とガチャガチャいじりましたが、大まかな方針としては「バージョン管理が必要ないツールはaptやHomebrewなどのパッケージマネージャやツール自体のセルフアップデートに任せる」「バージョン管理が必要なツールはasdfmiseなどのバージョン管理ツールに任せる」「インストールに苦戦するものはDockerに任せる」に落ち着きそうです。

VMの構築

新規のVMの立ち上げなので、 インストール前にやっておくことをさらっとメモします。

インスタンスの起動(OS選択)

OSはUbuntu 24.04 LTSを選択しました。 よくUbuntuを利用するので慣れているというのもありますが、 長期サポートで5年間のセキュリティアップデートとメンテナンスアップデートが保証されているのが安心感があります。

ファイアウォール設定

VMはクラウド上にあるのでSSHで作業することになります。 当然インターネットに公開することになるのですが、 職場からのみアクセスできるようにファイアウォールを設定しておくと安心です。

自動シャットダウン

ついつい後で使うかもと放置して立ち上げっぱなしになってしまうこともあるので、 原価が上がらないように自動シャットダウンを仕込んでおきます。 cronで設定すれば、EC2(AWS)とVM(Google Cloud)どちらでも動きます。

# 夜10時(JST)にシャットダウンする
(sudo crontab -l; echo "0 13 * * * /usr/sbin/shutdown -h now") | sudo crontab -

OSのアップデートを受け取る

Ubuntuの長期サポートのバージョンを選択しましたが、 アップデートしないことにはその恩恵を受け取れません。 他のツール群も同様に定期的にアップデートする必要があるため、 これらのコマンドをひとまとめにしておきます。 取り急ぎ、aptの更新を毎朝行うスクリプトとして登録します。 apt経由で入れたパッケージも一緒にアップデートされます。

# ~/.bashrc
morning-routine() {
  sudo apt update
  sudo apt upgrade
  sudo apt autoremove
  sudo apt autoclean
}

こうしておくと、毎朝起動時にmorning-routineと叩くだけで環境が綺麗に保たれるはずです。

最新で使いたい系ツールのインストール

apt管理のツール

aptで管理されるツールはapt update && apt upgradeでアップデートされます。

build-essential

後ほど、Homebrewを入れるので、その前に入れておく必要があります。

sudo apt install build-essential

Docker

Dockerは開発で必須ですね。公式の簡易インストールスクリプトで入れると、aptのリポジトリに追加されるので、こちらもaptと一緒にアップデートしてくれます。

Ubuntu | Docker Docs

curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER

direnv

環境変数を用意しておく必要があるプロジェクトがあるので、入力の手間を省くために導入します。

sudo apt install direnv

インストール時は特に言われないですが、起動するために~/.bashrcに仕込みが必要です。

direnv/docs/hook.md at master · direnv/direnv · GitHub

# ~/.bashrc

# for direnv
eval "$(direnv hook bash)"

セルフアップデート機能ありツール

セルフアップデート機能があるものは定期的にアップデートしておけば、常に最新バージョンを保つことができます。

gcloud

業務では主にGoogle Cloudを使用しているため、CLIツールが必須です。 ファイルを展開するだけなので格納場所に悩みますが、 ユーザーのホームディレクトリにインストールすることにします。 Homebrew経由でも入れられそうですが、 gcloudによるパッケージ管理体系がよくわかっておらず、 セルフアップデート機能もあるので、 直接入れてしまいます。

クイックスタート: Google Cloud CLI をインストールする  |  Google Cloud SDK  |  Google Cloud Documentation

cd
curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-linux-x86_64.tar.gz
tar -xf google-cloud-cli-linux-x86_64.tar.gz
rm google-cloud-cli-linux-x86_64.tar.gz
./google-cloud-sdk/install.sh

セルフアップデート機能があるので、毎朝実行するスクリプトに追加します。 gcloud経由で入れたパッケージも一緒にアップデートされます。

# ~/.bashrc
morning-routine() {
  sudo apt update
  sudo apt upgrade
  sudo apt autoremove
  sudo apt autoclean
  gcloud components update
}

Homebrew

aptでは手に入らないツールもたくさんあります。 そんな時は、Homebrewからインストールするとアップデートが簡単になります。 インストール方法はMacと同じようです。

Homebrew — The Missing Package Manager for macOS (or Linux)

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

インストール時に色々言われるので、忘れずに設定します。 brewの初期化用のスクリプトも忘れずに入れておきます。

# ~/.bashrc

# for homebrew
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"

セルフアップデート機能があるので、毎朝実行するスクリプトに追加します。 brew経由で入れたパッケージも一緒にアップデートされます。

# ~/.bashrc
morning-routine() {
  sudo apt update
  sudo apt upgrade
  sudo apt autoremove
  sudo apt autoclean
  brew update
  brew upgrade
  brew autoremove
  brew cleanup
  gcloud components update
}

gcloud関連パッケージ

gcloudはパッケージマネージャも兼ねています。これらもgcloudと一緒にアップデートされるので、こちらを経由して入れられると便利です。

cloud-sql-proxy

Cloud SQLとの接続をプロキシしてくれるツールです。ローカルから、認証やらファイアウォールやらをすっ飛ばしてDBにアクセスできるようになります。DBクライアントツールへの橋渡しとして便利です。(DB自体のパスワードは必要です。)

gcloud components install cloud-sql-proxy

Homebrew 関連パッケージ

asdf

アプリケーションの開発で使用するツールのバージョンをプロジェクトごとに固定できるように、 バージョン管理ツールとしてasdfを入れます。 miseでもいいかもしれません。(特にWindowsでも同じように動かしたい場合)

brew install asdf

インストール後の設定もやっておきます。

# ~/.bashrc

# for asdf
export PATH="${ASDF_DATA_DIR:-$HOME/.asdf}/shims:$PATH"
. <(asdf completion bash)

pyenv

関わるプロジェクトのほとんどで.python-versionとpoetryが使われているため、こちらを利用しています。 asdfmiseに統一したくなったらその時に統一します。

brew install pyenv

brewから提案される設定を入れておきます。

# ~/.bashrc

# for pyenv
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init - bash)"

nodenv

事情としてはpyenvと同じく、 .node-versionを使用しているプロジェクトが多いので、こちらも入れておきます。

brew install nodenv

brewから提案される設定を入れておきます。

# ~/.bashrc

# for nodenv
eval "$(nodenv init - bash)"

awscli

AWS CLIはAWSのクラウドとやり取りを行うので、 なるべく新しいバージョンを使用するのが望ましいと考えます。 公式のガイドではsnapからインストール手順が記載されていますが、 利用するツールを増やしたくないのでbrewで入れてしまいます。 もし、AWS互換サービスなどの都合でバージョンをコントロールする必要があれば、 asdf経由で入れても良いかもです。

brew install awscli

ところで、プロファイルの切り替え方法って忘れませんか? デフォルト値を設定しておくと、env | grep AWSすれば確認できて便利です。 ローカル環境にある、~/.aws/configを持ってきておくと最初からローカルと同じように使えます。

# ~/.bashrc

# for aws cli
export AWS_DEFAULT_PROFILE=<default project>

バージョン管理して使いたい系ツールのインストール

asdfpyenvnodenvを使用して入れます。

Go

バックエンドの言語としてGoを採用している箇所があるので、インストールしていきます。 Goは後方互換性を重要視されていため破壊的変更はほとんど起こらないはずですが、 バグ修正などにより軽微な仕様変更は起こるため、 謎のバグなどで時間を溶かさないためにもデプロイされる環境とバージョンを合わせたほうがよいと思います。

asdf plugin add golang
asdf install golang 1.25.3

ちなみに、Goでインストールして使うツールがある場合はパスを通しておくと便利です。 asdfでは、GOBINなどの設定もしてくれているようなので、 Goに登録されている変数から引用してみます。 ただ、グローバルに設定されたバージョンに依存することになるので、違うバージョンにインストールしないようにするなど気をつける必要がありそうです。

# for golang
export PATH="`go env GOBIN`:$PATH"

kubectl

プロダクトでEKSやGKEを使用している箇所があるため、こちらもインストールしています。 公式では、±1のマイナーバージョン(年に3つほど上がります)の差分まで保証されるようなので、 切り替えしやすいようasdfで管理します。 (インストール方法はGoと同じなので略)

poetry

最新でもいいかなと思いつつ、バージョンアップに伴い生成するtomlファイルの形式が変わってきているようです。 古いプロジェクトに合わせて、いつでもpoetryバージョンを変えられるようにしておきます。 (インストール方法はGoと同じなので略)

インストールにコツがいる系

バージョン管理を行いたいのでasdfなどで入れたいけど、 ビルドを通すのにコツが必要だったりして入れにくいツールがあったりします。 ローカルに入れておくよりは利用時の手数が増えてしまいますが、 無理にインストールせずにDockerから使うとスムーズに使えます。

psql

データベースに使用しているPostgreSQLですが、 CLIのバージョンが古かったりするとエラーが出ることがあります。 そのため、バージョンを切り替えて使用したいのですが、 asdfでインストールを試してみると、 バージョンによってビルドが通ったり通らなかったりしていました。 インストールに手間取るよりは早く動かしたいということで、とりあえずビルド済みのコマンドをDocker経由で使用することにしました。

# postgresのシェルに入ってから、自由にコマンドをたたく
 docker run --rm -it postgres:17 sh

これで、いつでも好きなバージョンのpsqlを使うことができます。 localhostにアクセスしたいときは--net hostをつけ、 ファイルをやり取りするときはボリュームのマウント(-w /tmp -v <target>:/tmp)を追加します。 (Linux上でやるとファイルのコンテナ内で作成したファイルの所有権がrootになってしまうので、そこだけ注意が必要そうです。)

おわりに

前の環境よりは管理された環境を作ることができて満足です。 年末の大掃除として開発環境を整理しておくのも良いかもしれません。

We Are Hiring!

ABEJAは、テクノロジーの社会実装に取り組んでいます。 技術はもちろん、技術をどのようにして社会やビジネスに組み込んでいくかを考えるのが好きな方は、下記採用ページからエントリーください! (新卒の方やインターンシップのエントリーもお待ちしております!) careers.abejainc.com

特に下記ポジションの募集を強化しています!ぜひ御覧ください!

トランスフォーメーション領域:データサイエンティスト

トランスフォーメーション領域:データサイエンティスト(ミドル)

トランスフォーメーション領域:データサイエンティスト(シニア)