🐧

Linux 使いになりたい人向けの Intel N100 ミニ PC で構築する開発環境(13)- Git

2024/07/28に公開

はじめに

これは、Linux 使いになりたい人向けに Intel N100 ミニ PC を使って開発環境を構築する方法を解説する記事の第13弾です。第1弾はLinux 使いになりたい人向けの Intel N100 ミニ PC で構築する開発環境(1) - 構築する開発環境について にあり、そこから第2弾へと続いています。そちらからご覧ください。

ここで使用する Intel N100 ミニ PC の仕様は次のものを前提とします。

項目 内容
OS Windows 11 Pro
CPU Intel N100
メモリ 16GB
ストレージ SSD 512 GB
画面出力端子 HDMI×2
WiFi 5G/2.4G
イーサネット RJ45×1
Bluetoot BT4.2
USB USB3.0×2/USB2.0×2

このマシンで最終的に Windows と Ubuntu Desktop が使えるように環境構築することを目指します。zenn.dev を購読している人のレベルを考えると、画面キャプチャはそれほど必要がないと考えているため少なめです。また、説明についても明示しないとわかりにくいと思われるものに絞っているので少なめです。

今回は分散バージョン管理システムのソフトウェア Git の環境を用意する方法について説明します。Git は Windows、macOS、Linux に対応しているので、これを使うと、それぞれの OS で同じようにファイルのバージョン管理をすることができるようになります。

Git が使えるようになると、Windows、macOS、Linux だけでなく、WSL Ubuntu、Docker コンテナーも含めて、ファイルのバージョン管理が手軽にできるようになるため、最近の開発者にとって必須のソフトウェアとなっています。そのため、各環境で Git コマンドが使えるようにするには、どのようにインストールしておけば良いのか知っておきたいはずです。

自分が良く使う環境に合わせて、Git 環境を用意する方法は変わってきます。色々なパターンがあることを知った上で、選択すると良いでしょう。

Git とは

Git は、ソースコードやファイルの変更履歴を記録・管理するための分散型バージョン管理システムです。これを使うことで、コードの修正・コードのレビュー・ファイルのバックアップなどの作業が楽になります。

筆者はデスクトップマシン・ノートパソコン・ラズパイなどのコンピュータを複数台使っています。これらのコンピュータ間でファイルの同期やコードの修正を適用するのは、Git を使わないと気を使った作業が必要になります。

Git を使っていなかった頃は、ファイルの更新日時を確認したり、デスクトップマシンとノートパソコンとで同じファイルを別々に修正したりしないようにしていました。今は Git を使っているので、そういったことを気にせずに作業することができています。気を使う作業がなくなり、ミスによる修正の消失といったこともなくなったので、作業効率が良くなりました。

Git の基本機能は、次のようになります。

  • バージョン管理
  • ブランチ管理
  • マージ
  • リモートリポジトリ

バージョン管理の機能により、ファイルの変更を履歴として記録し、過去の状態に戻したり、差分を確認することができるようになります。

ファイルのバージョン管理をするにあたり、ファイルの変更履歴を独立して管理したくなるときがあります。そのためにブランチというものがあり、これを管理することができます。ブランチを使うと、バグフィックス用の作業と、新規機能開発用の作業があったときに、両方ともバージョン管理をしつつ、並行して作業することができます。

ブランチ機能を使って並行して作業したコードをまとめて統合したいときもあります。そのためにマージという機能があります。この機能により、複数のブランチでの変更を統合しやすくなっていて、各ブランチで編集したファイルが被っていなければ自動でまとめることができます。

リモートリポジトリの機能があるので、複数のマシンでコード共有することができます。もちろん、複数の開発者とのコード共有もしやすくなっています。

Git を使うことのメリットは、次のようになります。

  • ファイルの変更履歴の管理
  • 過去の状態への復帰
  • 複数マシンでファイル編集しても統合が簡単
  • リモートマシンとローカルマシンのファイル同期が簡単
  • タグやブランチなどの機能による開発管理やリリース管理

また、Git の特徴は、次のようになります。

  • 分散型
  • 軽量
  • バージョン管理のための機能が充実

Git は中央集権的なサーバーに依存せず、各ユーザーがリポジトリの完全な複製を持つ分散型のシステムです。そのため、オフラインでもバージョン管理をしながら作業することができます。

また、実行用のファイルはサイズが小さく、動作も軽量です。

バージョン管理のための機能が充実していて、複雑なブランチ操作や履歴管理にも対応できます。

個人的にはテキストデータやサイズが小さいファイルは、すべて Git リポジトリで管理して、バックアップする場合はリポジトリの複製を別マシンに置くようにしています。Git に慣れないと、そこまでするのは大変だと感じるかもしれません。主な用途としては、次のものがあるので、こういったものから利用して慣れていくと良いでしょう。

  • ソフトウェア開発
  • Webサイト制作
  • ドキュメント管理

ソフトウェア開発では、ソースコードの変更履歴を管理し、チームで開発を進めることができます。Webサイト制作では、HTMLやCSSなどのファイルを管理し、デザインの変更履歴を追跡することができます。ドキュメント管理では、テキストファイルや画像ファイルを管理し、過去のバージョンを参照することができます。

Git は、個人開発者から大規模なオープンソースプロジェクトまで、幅広く利用されています。

Git と VS Code

VS Code にはソース管理のための機能が最初から搭載されていて、Git がサポートされています。基本的な使い方をするなら、VS Code の GUI で Git リポジトリを操作することができます。個人的には、Git 初学者には、VS Code を使うのが良いと考えています。

VS Code の拡張機能には Git リポジトリの操作をするのに便利なものがあり、筆者は次のものを使っています。

拡張機能名 拡張機能の ID 説明
Git History donjayamanne.githistory 履歴管理に便利
Git Graph mhutchie.git-graph ブランチやタグの情報管理に便利
GitLens eamodio.gitlens ソースコード管理機能全体を強化

VS Code には git コマンドは含まれていないので、使用する環境に応じて git コマンドが使えるようにする必要があります。

VS Code は DevContainers 拡張機能、Remote SSH 拡張機能、Remote WSL 拡張機能などを使って、ホストマシン以外の環境でも Git を使うことがあります。そのため、各環境で Git が使えるように設定しておくと、Git リポジトリを使ってコード共有がしやすくなります。

個人的に、Docker コンテナーを使用するときにバインドマウントを使ってコード共有をすると、何かと開発コンテナーが使いにくくなると考えています。そのため、コード共有は Git リモートリポジトリを利用するようにしています。

このことから、いまどきの開発環境では、Git リモートリポジトリが利用できる環境が必須だと考えています。また、自分で管理できるローカルな環境で使えるプライベート Git システムも必須だと考えています。

Git と Ubuntu/WSL Ubuntu

Ubuntu/WSL Ubuntu で Git を使うには、apt コマンドでインストールできる APT (Advanced Packaging Tool) の git パッケージを使うのが手軽です。

git パッケージの情報確認

最初に、インストール可能な git パッケージについて情報を確認しましょう。パッケージの情報を見るには、apt-cache show コマンドを使います。

apt-cache show <パッケージ名>

このコマンドを使って、git パッケージの情報を表示すると、次のようになります。

$ apt-cache show git
Package: git
Architecture: amd64
Version: 1:2.34.1-1ubuntu1.11
(略)

apt コマンドで Git のインストール

それでは、apt コマンドでパッケージをインストールしましょう。最低限の機能だけで良いなら git パッケージをインストールします。

sudo apt -y install git

Git 関連のパッケージを全部インストールするなら git-all パッケージをインストールします。

sudo apt -y install git-all

最新版の git コマンドのインストール

Ubuntu/WSL Ubuntu で Git の最新版をインストールしたい場合は、公式サイトの https://git-scm.com/download/linux で紹介されている git-core の PPA(Personal Package Archive)のパッケージリポジトリを使えるように設定して、これを使って git パッケージをインストールします。

具体的には次の手順で作業します。

sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update

先ほどと同じように apt-cache show コマンドを使うと、追加した PPA のパッケージ情報を確認することができます。

インストールは apt コマンドを使って、次のようにします。

sudo apt -y install git

Git のバージョンを確認

インストールができたら、コマンドのバージョンを確認しましょう。記事執筆時点の Ubuntu 22.04 の標準パッケージでは 2.34.1 となりました。

$ git --version
git version 2.34.1

Ubuntu/WSL Ubuntu で git コマンドが使えるようになっていると、VS Code の Remote SSH 拡張機能を使って Ubuntu を使ったり、Remote WSL 拡張機能を使って WSL Ubuntu を使ったりするときに、ソースコード管理の機能が使えるようになります。

Git と Windows

Windows を使っている場合は Git for Windows をインストールして使えるようにしておくと良いでしょう。

WSL Ubuntu を主に使うようにして、Windows の方では Git は使わないという環境を用意することも可能ですが、Windows アプリを使って開発作業をしたい場合もあるはずです。そういうときに Git for Windows を使って Windows のファイルシステム上に Git リポジトリをクローンして作業することになります。そういった場合に、Git for Windows が必要です。

Git for Windows には Git Bash というアプリも同梱されていて、Ubuntu/WSL Ubuntu の bash シェルを使うのと同じような感覚で Windows のファイル操作や Git 操作ができます。Git を使うときは Git Bash を使うことにしておけば、bash 環境と PowerShell 環境の違いに悩むことはあまりありません。ただし、Ubuntu/WSL Ubuntu の bash 環境と Git Bash の環境との差はあるので、それについては意識が必要です。といっても bash と PowerShell との差ほど大きくはありませんから、Git Bash を使った方が楽なはずです。

もうひとつ、Git for Windows を使うと、GIt リモートリポジトリを使うときの認証がしやすくなります。Git for Windows には 同じマシンの Windows と WSL Ubuntu とで共通の Git リモートリポジトリ認証用の機能が含まれているので、これを使った方が認証に関する操作が楽になります。

インストール方法と Windows で設定しておくと良い事についての詳細は、下記で説明しています。この後に説明するインストール方法についてわからないことがあったら、こちらの Git for Widnows の部分を参照してください。

それでは、インストール方法について簡単に説明します。Git for Windows をインストールするにあたって一番簡単なのは winget コマンドを使う方法です。

winget install -e --id Git.Git

コマンドを実行すると、管理者権限が必要なため「このアプリがデバイスに変更を加えることを許可しますか?」という画面が表示されます。「はい」をクリックして進めます。

/images/20240126_win11eval_app/git-install.png
Git for Windows このアプリがデバイスに変更を加えることを許可しますか? の画面

実行結果の全体は次のようになります。

PS C:\Users\User> winget install -e --id Git.Git
見つかりました Git [Git.Git] バージョン 2.43.0
このアプリケーションは所有者からライセンス供与されます。
Microsoft はサードパーティのパッケージに対して責任を負わず、ライセンスも付与しません。
ダウンロード中 https://github.com/git-for-windows/git/releases/download/v2.43.0.windows.1/Git-2.43.0-64-bit.exe
  ██████████████████████████████  58.0 MB / 58.0 MB
インストーラーハッシュが正常に検証されました
パッケージのインストールを開始しています...
インストーラーは管理者として実行するように要求するため、プロンプトが表示されます。
インストールが完了しました

winget を使うと Git for Windows の設定についての調整はされずにインストールされます。ここでは説明を省略しますが、インストール後に、設定ファイルを確認して調整します。

インストールが終わると Windows のスタートメニューの「すべてのアプリ」の一覧に「Git」フォルダーが追加されます。その中に Git Bash、Git CMD、Git GUI といったメニューが含まれています。

/images/20240126_win11eval_app/windows-app-list-git.png
アプリの一覧の Git

Git を使うには、Git Bash というシェルを使います。Git for Windows の Git Bash では、内部的に MinGW-w64 プロジェクトの成果物が使われています。これを使うことで、Windows OS 内でも Ubuntu/WSL Ubuntu の bash シェルの環境で Git が使えるようになります。

Git と Docker

ここでは Git と Docker について説明します。

Git の利用ができる Docker コンテナーを使うと、Docker のホストマシンへ Git をインストールしなくても済みます。Docker が使えるマシンで、一時的に使いたいコマンドがあるときに、ここで紹介する方法を知っていると役に立ちます。ただし、Git の利用ができる Docker コンテナーを、Docker ホスト側でコマンドのように使うには、少し環境整備が大変になります。

別の方法として、コンテナーの中でプログラム開発もバージョン管理もできるようにする方法について紹介します。これは、開発コンテナー用イメージについて、開発しやすい環境をコンテナーで提供するものを選択して使うことで可能です。つまり、Docker のホストマシンで Docker コンテナーの git コマンドを使うという発想ではなく、Docker コンテナーの中で開発作業を閉じるということになります。これにより、バージョン管理をするときに Docker のホストマシンにインストールした Git を使わなくても済むようになります。

ここでは、Ubuntu/WSL Ubuntu もしくは Git Bash でコマンド実行する前提で説明します。

Docker コンテナーの Git の利用

Git を使うにあたっては、Docker を使うという方法もあります。使い勝手はよくありませんが、一時的に特定のバージョンの git コマンドを使いたいときに知っておくと役に立ちます。

とはいえ、git コマンドのように頻繁に使用するコマンドだと、ホストマシンへインストールして使うのが普通なので、ありがたみがわかりにくいことでしょう。しかし、たまにしか使わないのでホストマシンへ常時インストールしておくのは躊躇するようなコマンドについて、Docker コンテナーで簡単に使えるようなものがある場合に、ここで紹介する知識が役に立ちます。

コマンドを使い慣れていないとイメージしにくいかもしれませんが、コマンド用のコンテナーはそれなりにありますから、ここで Docker の使い方のパターンを増やしておきましょう。

例として、git コマンドが使えるイメージとして、bitnami/git イメージがあります。git コマンドについて、バージョンを確認するためだけに実行するなら簡単で、次のようにします。

docker container run --rm -it bitnami/git git --version

実際に利用しようとすると、リポジトリをバインドマウントしてコンテナー内で利用できるようにして、作業ディレクトリーをマウントしたものにする必要があります。

たとえば、repo ディレクトリーを作成して、Git リポジトリの repo/.git を作成するには、次のようにコマンド実行します。

sudo mkdir repo
docker container run --rm -it \
    -v $(pwd)/repo:/repo \
    -w /repo bitnami/git \
    git init

ここで repo ディレクトリーについて、Ubuntu/WSL Ubuntu、macOS では所有者がどのユーザーとなっているのか意識が必要になります。bitnami/git イメージを使ったコンテナーは、root ユーザーで実行されるため、repo ディレクトリーは root ユーザーの所有となります。

Docker ホスト側では repo ディレクトリーはユーザーが所有者としておきたいところでしょう。chown コマンドで repo ディレクトリーの所有者をユーザーとします。ユーザーの ID とグループ ID は、それぞれ $(id -u)$(id -g) で取得できるので、それを使っています。

sudo chown -R $(id -u):$(id -g) /repo 

コンテナーを使って repo ディレクトリーの所有者をユーザーにすることもできます。ユーザーの ID と同じユーザー ID を持つ git ユーザーをコンテナー内で作成して、repo ディレクトリーの所有者を、そのユーザーの ID とすれば良いです。その場合は、次のコマンドを実行します。

docker container run --rm -it \
    -v $(pwd)/repo:/repo \
    -w /repo bitnami/git \
    sh -c "useradd -u $(id -u) git && chown -R $(id -u) /repo"

少し複雑なので順に説明します。コンテナーを起動して <コマンド> を実行する部分は docker container run コマンドを知っていれば大丈夫でしょう。

docker container run --rm -it \
    -v $(pwd)/repo:/repo \
    -w /repo bitnami/git \
    <コマンド>

ここでの <コマンド> は、sh -c "useradd -u $(id -u) git && chown -R $(id -u) /repo" の部分になります。

まず、$(id -u) の部分は id -u の実行結果に置換されます。ここで、id -u の結果について、次のようになっていたとします。

$ id -u
1000

これにより、<コマンド> 内の $(id -u)1000 となります。そのため、<コマンド> は次の内容になります。

sh -c "useradd -u 1000 git && chown -R 1000 /repo"`

ここで、シェル sh<コマンド文字列> のコマンドを実行するときは、sh -c <コマンド文字列> と書きます。そのため、実際に実行するコマンドは次の内容になります。

useradd -u 1000 git && chown -R 1000 /repo

ここで、&& の左辺のコマンドはユーザー git を追加します。

useradd -u 1000 git

また、&& の右辺のコマンドは /repo ディレクトリー配下のファイル所有者をユーザー git のユーザー ID に変更します。

chown -R 1000 /repo

&& でコマンドをつなげると、左辺のコマンドの実行が成功したら、右辺のコマンドを実行します。

少し長いコマンドでしたが、このように順番に見ていくと、それほど難しくないことがわかるでしょう。この後も、似たようなコマンドが出てきますが、落ち着いて順番に読み解いてください。

次に、コンテナーを起動してからユーザーの ID と同じユーザー ID を持つ git ユーザーをコンテナー内で作成して、そのユーザーを使って git status コマンドを実行するようにします。

docker container run --rm -it \
    -v $(pwd)/repo:/repo \
    -w /repo bitnami/git \
    sh -c "useradd -u $(id -u) git && su git -c \"git status\""\

ここで、指定したユーザーでコマンド実行するために su コマンドを使用しています。このコマンドをターミナルで実行する場合は、su git -c "git status" とすれば良いのですが、ここではそのまま使うことができません。

そのまま使うと、sh コマンドに渡すパラメーターを囲う " について、有効範囲の指定が正しく認識されなくなってしまうという問題が起きます。これに対応するために、su git -c \"git status\" と記述します。

\ はエスケープ文字と呼ばれるもので、ここでは次に続く "sh コマンドの区切り文字ではなく、文字の " として使うという指定をするときに使います。シェルスクリプトでは良く出てくるので覚えておきましょう。

このようにすることで、sh コマンドの中で実行するコマンド文字列に " を含むことができるようになります。つまり、ここでは su git -c \"git status\"su git -c "git status" と解釈されて実行されるということになります。

さて、ここまで紹介したコマンドを組み合わせて使うことで、docker container run コマンドを単純に使った場合に発生するバインドマウントでのファイル所有者についての問題を起こさないようにすることができます。

ただし、毎回 useradd コマンドで git ユーザーを用意する必要があるので、あまり実用的ではありません。少し面倒ですが、sudo chown コマンドでホスト側で毎回直せば済む話なので、個人利用ならそれで妥協しても良いでしょう。

なお、筆者としては、sudo chown コマンドでホスト側で毎回直すという妥協はしにくかったので、もう少し実用的に使う方法を検討して Docker Compose の利用をしてみたので、それについても紹介しておきます。

Docker Compose で Git の利用

Docker Compose で Git を利用する方法では、次のようなディレクトリー構成でファイルを用意して、専用のコンテナーを起動するようにします。

bitnami-git/
├── compose.yaml
├── repo/
└── script/
    ├── down.sh
    ├── git.sh
    ├── stop.sh
    └── up.sh

ここでは repo ディレクトリーに Git リポジトリ(.git)を含ませるとします。リポジトリの初期化は、compose.yaml を使って起動したコンテナーでします。

必要なディレクトリーをファイルを、Docker ホスト側で作成しておきます。

mkdir -p bitnami-git/repo
mkdir -p bitnami-git/script
touch bitnami-git/compose.yaml
for f in down.sh git.sh stop.sh up.sh; do
    touch bitnami-git/script/${f}
done

コンテナー管理用の compose.yaml は次のようにします。

compose.yaml
name: bitnami-git
services:
  bitnami-git:
    image: bitnami/git
    container_name: bitnami-git
    tty: true
    working_dir: /repo
    volumes:
      - type: bind
        source: ${REPO_DIR:-./repo}
        target: /repo

これを使用するためのスクリプトとして、コンテナー起動用の up.shgit コマンド実行用の git.sh、コンテナー停止用の stop.sh、コンテナー破棄用の down.sh を用意します。

最初にコンテナーを起動するときに使う up.sh を用意します。

up.sh
#!/bin/sh
SCRIPT_DIR=$(dirname "$0")
PROJ_DIR=$(cd "${SCRIPT_DIR}/.." || exit 1; pwd)
COMPOSE_FILE="${PROJ_DIR}/compose.yaml"
PROJ_NAME=bitnami-git
SERVICE_NAME=${PROJ_NAME}

# コンテナー起動
docker compose -f "${COMPOSE_FILE}" up -d

# コンテナー起動の待機
until \
  docker compose ls -a | grep "${PROJ_NAME}" | grep "running"
do
    >&2 echo "${PROJ_NAME} is not available - sleeping"
    sleep 1
done

# コンテナー内に git ユーザーを追加
docker compose -p ${PROJ_NAME} exec ${SERVICE_NAME} \
    sh -c "useradd -u $(id -u) git"

次に git コマンドを実行する git.sh を用意します。

git.sh
#!/bin/sh
PROJ_NAME=bitnami-git
SERVICE_NAME=${PROJ_NAME}

# コマンドの用意
CMD="git $@"

# コンテナーで `git` コマンド実行
docker compose -p "${PROJ_NAME}" exec ${SERVICE_NAME} \
    su git -c "${CMD}"

次にコンテナーを停止する stop.sh を用意します。

stop.sh
#!/bin/sh
PROJ_NAME=bitnami-git
SERVICE_NAME=${PROJ_NAME}

# コンテナー破棄
docker compose -p "${PROJ_NAME}" stop ${SERVICE_NAME}

次にコンテナーを破棄するときに使う down.sh を用意します。

down.sh
#!/bin/sh
PROJ_NAME=bitnami-git

# コンテナー破棄
docker compose -p "${PROJ_NAME}" down

これらを使うことで、Docker を使って git コマンドが実行できるようになります。使い方は次のようになります。

まず、カレントディレクトリーを bitnami-git とします。

cd bitnami-git

それから up.sh を実行します。これで Git リポジトリを操作できる bitnami-git コンテナーが起動します。

sh script/up.sh

実際の git コマンドの代わりに git.sh を使います。

sh script/git.sh --version
sh script/git.sh init
sh script/git.sh status

コンテナーをそのまま残して、Git を使用する作業を一時的にやめる場合は stop.sh を実行します。

sh script/stop.sh

Git を使用する作業が終わってコンテナーを破棄して良いなら down.sh を実行します。

sh script/down.sh

ここで、Ubuntu/WSL Ubuntu であれば、alias コマンドで次のように設定すると、git.sh を普通の git コマンドのように使うことができるようになります。

alias git="sh $(pwd)/script/git.sh"

この設定を解除するには、unalias コマンドを使います。

unalias git

説明は以上です。Docker を使って git コマンドが使える環境を用意することができることがわかったでしょうか。

このようにして、Docker で動作するコマンドラインのツールがある場合は、コンテナーを起動しておく必要がありますが、Ubuntu/WSL Ubuntu であればホストのコマンドとほぼ同じように使うことができるようになります。Windows でも Git Bash でなら、同じようにすることができます。

Git と開発コンテナー

さて、Git の利用ができる Docker コンテナーを使う方法について説明しましたが、少し環境整備が大変だと感じたのではないでしょうか。これは、Docker ホストでコンテナー内の git コマンドを使おうとしていたので、大変なのでした。

ここでは、別の方法として、コンテナーの中でプログラム開発もバージョン管理もできるようにする方法について説明します。これは、開発コンテナー用イメージについて、開発しやすい環境をコンテナーで提供するものを選択して使うことで可能です。Docker コンテナーの中で開発作業を閉じることにより、開発環境の管理がしやすくなります。

Git が使える開発コンテナー用イメージを使って Docker コンテナーを用意すれば、VS Code のソースコード管理で Git が使えます。例えば、https://github.com/devcontainers/images/tree/main/src/typescript-node で公開されている Node.js と TypeScript に対応している mcr.microsoft.com/devcontainers/typescript-node:20-bookworm イメージを使うと、開発コンテナーへ VS Code をアタッチして TypeScript のアプリ開発をしながら Git を使ってバージョン管理することができます。

ここでは node20 という開発プロジェクト用のディレクトリーを用意したとして、開発コンテナーを使う方法について説明します。

node20/
├── .devcontainer/
│   └── devcontainer.json
└── compose.yaml

なお、説明のために開発コンテナー内の作業を永続化する部分については省略しています。コンテナーを破棄すると、コンテナー内で行った作業は消えてしまう点に注意してください。

それでは、使用するディレクトリーとファイルを用意します。

mkdir -p node20/.devcontainer
touch node20/.devcontainer/devcontainer.json
touch node20/compose.yaml

使用するコンテナー用の compose.yaml は次のようにします。

compose.yaml
name: node20
services:
  node20:
    # https://github.com/devcontainers/images/tree/main/src/typescript-node
    image: mcr.microsoft.com/devcontainers/typescript-node:20-bookworm
    container_name: node20
    hostname: node20
    tty: true
    working_dir: /home/node

プロジェクト名は name: に指定するので、ここでは node20 としています。

用意するサービスは services: に指定します。ここでは Node.js アプリを開発するコンテナー用に node20: を用意します。

このコンテナーのもとになるイメージは image: に指定します。ここでは、https://github.com/devcontainers/images/tree/main/src/typescript-node で公開されている mcr.microsoft.com/devcontainers/typescript-node:20-bookworm を使います。名前からわかるように、このイメージは Debian の bookworm をベースとして Node.js バージョン 20 の環境が用意されていて、TypeScript アプリの開発ができます。

コンテナー名は container_name:、ホスト名は hostname: で指定します。ここではどちらも node20 としています。

コンテナー名は、docker container ls コマンドなどでコンテナーを一覧表示したときに表示されます。これを確認することで、コンテナーを特定できます。

ホスト名はコンテナーへアタッチしたときのプロンプトに表示されます。サービス名と同じにしておくと、アタッチしたときに間違えることがなくなるので、指定してます。

また、このコンテナーについては、コマンドを対話的に実行できるように tty: true の指定をしています。

コンテナーの作業ディレクトリーは working_dir: に指定します。ここで使用しているイメージでは、開発用のユーザーとして node が用意されているので、ここでは、node ユーザーのホームディレクトリー /home/node を指定しています。

次に、.devcontainer/devcontainer.json を用意します。

.devcontainer/devcontainer.json
// https://github.com/devcontainers/
{
    "name": "node20",
    "dockerComposeFile": "../compose.yaml",
    "service": "node20",
    "workspaceFolder": "/home/node",
    "remoteUser": "node"
}

"name": には、この開発コンテナーの名前を指定します。

"dockerComposeFile": には使用する Docker Compose 用設定ファイルを指定します。node20/compose.yamlnode20/.devcontainer/devconainer.json からの相対位置で ../compose.yaml となります。

"service": には対象とするコンテナーのサービス名を指定します。

"workspaceFolder": にはコンテナーを開いたときに自動で開く作業用フォルダーを指定します。compose.yaml で指定した working_dir: と同じものとしておくと良いです。

"remoteUser": にはコンテナー内で開発するときに使うユーザーを指定します。mcr.microsoft.com/devcontainers/typescript-node:20-bookworm のイメージでは、あらかじめ開発用のユーザーとして node が用意されているので、それを使います。

用意ができたら、VS Code で node20 フォルダーを開きます。

code node20

VS Code の画面が表示されると、通知欄に「コンテナーで再度開く」ボタンが表示されます。これをクリックすると、開発コンテナーが起動します。また、起動した開発コンテナーには、自動で「Visual Studio Code をアタッチする」が適用されて、VS Code の画面は開発コンテナーにアタッチしたものになります。なお、開発コンテナーにアタッチしていることは、VS Code の画面で左下に開発コンテナー: node20 が表示されることからわかります。

後は、開発コンテナー: node20 の VS Code でターミナルを開いて作業します。repo ディレクトリーを作成して、git コマンドで初期化します。

コマンドの実行例を次に示します。

node ➜ ~ $ git config --global init.defaultBranch main
node ➜ ~ $ mkdir ~/repo && cd ~/repo
node ➜ ~/repo $ git init
Initialized empty Git repository in /home/node/repo/.git/
node ➜ ~/repo (main) $

最初に、デフォルトのブランチ名を main とするために git config コマンドを使って init.defaultBranch の値を main としています。

それから mkdir コマンドで ~/repo ディレクトリー(/home/node/repo ディレクトリー)を作成し、カレントディレクトリーを作成したものにしています。

次に ~/repo に Git リポジトリを用意するために git init コマンドを実行しています。

以上で、開発用のディレクトリーの準備ができました。後は 開発コンテナー:node20 の VS Code でメニューを開き、「ファイル」-「フォルダーを開く」をクリックして、表示される画面で /home/node/repo を選択します。すると、開発コンテナー:node20/home/node/repo フォルダーを開いた VS Code の画面が表示されます。

この画面で VS Code のソース管理を表示すると、~/repo にある Git リポジトリを操作することができます。

また、開発コンテナー:node20 の VS Code でターミナルを開いて、npm コマンドや tsc コマンドを使って開発作業をすることができます。当然ですが、git コマンドを使ったファイルのバージョン管理もできます。

このように、Git が使える開発コンテナーを使うことで、Docker ホスト側に git コマンドをインストールしなくても、開発時に Git を使ったバージョン管理ができるようになります。

なお、作業を終了するには、開発コンテナー:node20 の VS Code を閉じます。開発コンテナーを停止するには、次のようにコマンド実行します。

docker compose -p node20 stop

作業を再開するときは、code コマンドで node20 ディレクトリーを VS Code で開き、通知に表示される「コンテナーで再度開く」をクリックします。

code node20

開発コンテナーを破棄するには、次のコマンドを実行します。

docker compose -p node20 down

開発コンテナーを使うようになると、できるだけ開発コンテナー内で作業を完結できるようにしたいと感じるようになります。ここで紹介したような便利な開発コンテナーを活用することで、効率良い開発ができるようになります。

Git 関連のコマンドラインツール

Git を使うにあたっては、基本的に VS Code や bash を使いますが、便利な Git 関連のコマンドラインツールもあるので紹介しておきます。ここでは次の 2 つについて説明します。

  • tig
  • lazygit

いずれも Ubuntu/WSL Ubuntu で使えることを確認しています。

tig

tig は、Git リポジトリを操作するためのテキストユーザーインタフェースのツールで、GPL 2.0 License で利用できる OSS です。ターミナル上で vim ライクな操作で、コミットログの閲覧、ファイルの差分確認、ステージング、コミット、ブランチ操作などが快適に行えます。

git コマンドと比較して、視覚的に操作する機能を提供しているため、直感的に操作ができて、Git リポジトリを効率的に管理できます。

公式の Web サイトは https://jonas.github.io/tig にあり、ソースコードは https://github.com/jonas/tig で公開されています。

筆者は VS Code が使えないターミナル環境で、開発ツールをインストールしても良い場合に使っています。

tig の特徴は次のとおりです。

  • 視覚的な操作が可能
  • vim ライクな操作
  • 豊富な機能

tig では、コミットログやファイル差分などを視覚的に確認できます。ただし、ターミナルで動作するアプリになれていないと操作にとまどうかもしれません。とはいえ、使い方がわかって慣れてくれば、軽快に動作して視覚的に操作できるため、git コマンドを使うよりも使いやすいと感じるはずです。

また、カーソルの移動が vim と同じ hjkl キーを使うなど、操作方法は vim と似ています。Linux を使っていると vim での操作はある程度は慣れているはずなので、それほど困ることはないはずです。

なお、基本的な Git の機能に対応しているので、コミット、ブランチ操作、マージ、リベースなど、普段良く使う操作を実行できます。

Ubuntu/WSL Ubuntu では apt コマンドでインストールできます。

sudo apt-get -y install tig

Homebrew が使える環境なら、brew コマンドでインストールすることもできます。

brew install tig

なお、筆者の方針としては Ubuntu/WSL Ubuntu でのパッケージ管理については、brew よりも apt コマンドでインストールする方を優先としています。どちらのパッケージでインストールしたものかについては把握していないと、両方でインストールしてしまうことが起き、無用なトラブルの元になることがあるので、気をつけましょう。

tig の基本的な操作方法は以下の通りです。

キー 説明
カーソル カーソルを移動
hjkl vim と同じようにカーソルを移動
Enter 選択した項目を開く
q 終了
s ステータスビューを表示
l ログビューを表示
t ツリービューを表示
C コミットを実行

lazygit

lazygit は、Git リポジトリを操作するためのテキストユーザーインタフェースのツールで、MIT License で利用できる OSS です。lazydocker コマンドに慣れているなら、tig よりも使いやすいと感じるかもしれません。

lazygit を使うと、ターミナル上で vim ライクな操作で、コミットログの閲覧、ファイルの差分確認、ステージング、コミット、ブランチ操作などが快適に行えます。lazygit の方が tig よりも軽量なようですが、tig コマンドほど普及はしていません。

公式サイトは https://github.com/jesseduffield/lazygit になります。

インストールは Homebrew を使うのが簡単です。brew コマンドでインストールすることができます。

brew install jesseduffield/lazygit/lazygit

Ubuntu/WSL Ubuntu では、次のスクリプト install_lazygit.sh を使ってインストールすることもできます。

install_lazygit.sh
#!/bin/sh
VERSION_URL=https://api.github.com/repos/jesseduffield/lazygit/releases/latest
DL_URL=https://github.com/jesseduffield/lazygit/releases/latest/download
LAZYGIT_VERSION=$(curl -s "${VERSION_URL}" | grep -Po '"tag_name": "v\K[^"]*')
curl -Lo lazygit.tar.gz "${DL_URL}/lazygit_${LAZYGIT_VERSION}_Linux_x86_64.tar.gz"
tar xf lazygit.tar.gz lazygit
sudo install lazygit /usr/local/bin

インストール用スクリプトを用意したら実行します。内部的に sudo コマンドを使っているので、実行時にユーザーのパスワード入力が必要です。

sh ./install_lazygit.sh

これで、/usr/local/bin/lazygit が使えるようになります。

なお、各 OS 用のバイナリーファイルもあります。それを使う場合は、次の URL からバイナリーのアーカイブファイルをダウンロードして、展開したものを PATH が通っているディレクトリーへ置けばよいです。

Discussion