GitBucket を使うことについて:Linux 使い(略)Advent Calendar 2024
はじめに
これは「Linux 使いになりたい人のための Advent Calendar 2024」の記事です。
筆者は、Web エンジニアを志望する人には、セルフホスト Git サービスを稼働させて利用することをオススメしています。もし Git を使ったことがないなら、Git を学ぶときに、セルフホスト Git サービスを稼働させることも視野に含めながら学習するのが効率的だと考えています。
GitBucket を使うことについて
前回はセルフホスト Git サービスを稼働させるにあたり、Gitea と Forgejo について使う場合について説明しました。今回は、候補にいれつつ紹介しなかった GiBucket について説明します。
GitBucket は Java の開発者なら馴染みのある技術を使って実装されています。また、実行にあたっては Java のランタイム環境が必要です。そのため、Java 開発者には推奨するのですが、そうでない場合は純粋に Gitea や Forgejo の機能と比較して選択するかしないかを判断することになります。
GitBucket については記事にしていないので、試用することを前提に、起動や停止をする方法について簡単に説明します。
GitBucket は下記の URL でコードが開発されているオープンソースプロジェクトでライセンスは Apache License Version 2.0 です。
Docker イメージ用のプロジェクトもあり、下記の URL で公開されています。
Docker で試用
試用には Docker を使うのが簡単です。
ここで用意するファイルは次のディレクトリー構成となっているとします。また、gitbucket-container
ディレクトリーを ${CONTAINER_PROJ_DIR}
と表記します。
gitbucket-container/
├── data/
└── script/
├── run.sh
└── run_v.sh
GitBucket コンテナーの試用
単純に GitBucket を使ってみるだけなら 次のコマンドを実行します。
docker container run -d \
-p 8080:8080 \
-p 29418:29418 \
ghcr.io/gitbucket/gitbucket:4.41.0
これで、http://localhost:8080 で Web UI が使えて、ssh://localhost:29418 で始まる URL の Git リモートリポジトリが使えるようになります。
初期の管理者アカウントが用意されていて、次の情報でサインインできます。
- ID: root
- Pass: root
管理者アカウントでサインインしたら、初期設定をして使えるように環境を用意します。ここでは使い方の説明は省略します。
停止するにはコンテナー ID かコンテナー名が必要です。次のコマンドで確認できます。
docker container ps | grep gitbucket
実行例は次のようになります。b0787c35f73d
がコンテナー ID で、sleepy_hopper
がコンテナー名です。
$ docker container ps | grep gitbucket
b0787c35f73d ghcr.io/gitbucket/gitbucket:4.41.0 (略)sleepy_hopper
停止は docker container stop <コンテナー ID>
のコマンドを実行します。
docker container stop b0787c35f73d
GitBucket コンテナー用スクリプト
起動用のコマンドについては、${CONTAINER_PROJ_DIR}/script/run.sh
スクリプトにしておくと実行しやすくなります。
#!/bin/sh
docker container run -d \
-p 8080:8080 \
-p 29418:29418 \
ghcr.io/gitbucket/gitbucket:4.41.0
実行するには次のようにします。
cd ${CONTAINER_PROJ_DIR}
sh script/run.sh
停止については、ワンライナーにすることもできます。そのときは awk
コマンドも利用しつつ次のようなコマンドにします。
docker container stop \
$(docker container ps | grep gitbucket | awk '{print $1}')
実行例は次のようになります。
$ docker container stop \
"$(docker container ps | grep gitbucket | awk '{print $1}')"
b0787c35f73d
こちらも script/stop.sh
スクリプトにしておくと使いやすくなります。実行前に、コンテナーが起動しているかの判定をするために if
を使うようにしてあります。
#!/bin/sh
if docker container ps | grep gitbucket > /dev/null 2>&1; then
CONTAINER_ID=$(docker container ps | grep gitbucket | awk '{print $1}')
docker container stop "${CONTAINER_ID}"
fi
実行するときは次のようにします。
cd ${CONTAINER_PROJ_DIR}
sh script/stop.sh
GitBucket コンテナー削除
停止するだけでなく、コンテナーを削除したいときは docker compose rm
コマンドを使います。停止時と同じようにスクリプト ${REPO_DIR}/script/down.sh
として用意し、それを実行すると良いでしょう。
${REPO_DIR}/script/stop.sh
とちがって、 docker compose rm
コマンド実行時にコンテナーは停止している必要があるので、先に停止が必要です。
また、停止中のコンテナーについては docker container ps
実行時に -a
オプションを追加しないと一覧に表示されません。停止中であることは、Status が Exit となっていてわかるので、この情報も使ってコンテナー ID を抽出します。
なお、停止中のコンテナーは複数存在することがあります。今回も試しに起動して、試しに停止だけしたコンテナーがあって、docker container ps -a |(略)grep Exited
にヒットするものが複数あったりしました。そういった場合は、$(docker container ps -a |(略))
の結果が「コンテナー ID のリスト」となるので for
を使って処理しておくと良いです。
整理すると、次のようになります。
#!/bin/sh
echo "stop"
SCRIPT_DIR=$(dirname "$0");
sh "${SCRIPT_DIR}/stop.sh"
echo "down"
if docker container ps -a | grep gitbucket | grep Exited > /dev/null 2>&1; then
CONTAINER_ID_LIST=$(docker container ps -a | grep gitbucket | grep Exited | awk '{print $1}')
for id in ${CONTAINER_ID_LIST}; do
docker container rm "${id}"
done
fi
GitBuckeet のデータ永続化
Docker ホストのファイルシステム上にデータの永続化をしたい場合は、データをおきたいディレクトリーをカレントにして次のように -v
オプションでバインドマウントを指定して、docker container run
コマンドを実行します。
cd ${CONTAINER_PROJ_DIR}
cd ./data
docker container run -d \
-p 8080:8080 \
-p 29418:29418 \
-v "$(pwd)":/gitbucket \
ghcr.io/gitbucket/gitbucket:4.41.0
${CONTAINER_PROJ_DIR}/data
ディレクトリーには次のようなファイルが作成されます。
$ ls
activity.log data.mv.db database.conf gist plugins tmp
${CONTAINER_PROJ_DIR}/data
ディレクトリーに移動してコマンド実行したり、data
ディレクトリーの存在チェックしたりする処理はまとめてスクリプトにしておいた方が使いやすいので、次のような ${CONTAINER_PROJ_DIR}/script/run_v.sh
を用意します。
#!/bin/sh
SCRIPT_DIR=$(dirname "$0");
DATA_DIR=$(cd "${SCRIPT_DIR}/../data" || exit 0; pwd)
if [ ! -e "${DATA_DIR}" ]; then
echo "mkdir \"${DATA_DIR}\""
mkdir -p "${DATA_DIR}"
fi
docker container run -d \
-p 8080:8080 \
-p 29418:29418 \
-v "${DATA_DIR}":/gitbucket \
ghcr.io/gitbucket/gitbucket:4.41.0
これを実行します。
cd ${CONTAINER_PROJ_DIR}
sh script/run_v.sh
コンテナー停止は ${CONTAINER_PROJ_DIR}/script/stop.sh
、コンテナー削除は ${CONTAINER_PROJ_DIR}/script/down.sh
が使えます。
Docker Compose で試用
docker container
コマンドで使う方法はわかりましたが、ここで紹介しているスクリプトはエラー処理を考慮しておらず、そこまで対応を考えると大変です。docker compose
コマンドが使える環境なら、もっとわかりやすい compose.yaml
ファイルでコンテナーを定義できます。
ここで用意するファイルは次のディレクトリー構成となっているとします。また、gitbucket
ディレクトリーを ${PROJ_DIR}
と表記します。
gitbucket/
├── compose.yaml
└── script/
├── down.sh
└── run.sh
最初に説明したとおり、docker compose
コマンドが使える環境なら、docker container
コマンドで複雑なオプションを指定してするより、compose.yaml
ファイルで宣言的に表現した方がわかりやすいです。
また、永続化データについては、バインドマウントを使うと性能問題やファイルシステムのオーナー権限問題が発生しやすいので、Docker ボリュームを使うようにした方が良いです。
ネットワーク設定については、ポート番号だけの指定だと、実は Docker ホストで使えるすべてのネットワークインタフェースについてポートを開いてしまいます。IP アドレスで使用するネットワークの指定ができるので、ここでは 127.0.0.1 だけにして制限をきつくします。
これらを考慮すると次のような gitbucket/compose.yaml
ファイルを作成することになります。
name: gitbucket
services:
gitbucket:
image: ghcr.io/gitbucket/gitbucket:4.41.0
container_name: gitbucket
hostname: gitbucket
tty: true
ports:
- 127.0.0.1:8080:8080
- 127.0.0.1:29418:29418
volumes:
- type: volume
source: gitbucket-data
target: /gitbucket
volumes:
gitbucket-data:
name: gitbucket-data
実行するには次のように docker compose
コマンドで -f
オプションで使用する compose.yaml
ファイルを指定し、サブコマンドに up
を指定します。デーモン起動するために -d
オプションも指定します。
これを script/run.sh
で用意します。
#!/bin/sh
SCRIPT_DIR=$(dirname "$0");
DC_DIR=$(cd "${SCRIPT_DIR}/.." || exit 0; pwd)
DC_FILE="${DC_DIR}/compose.yaml"
docker compose -f "${DC_FILE}" up -d
停止は docker compose down
コマンドを使います。このとき、-p <プロジェクト名>
オプションで停止する Docker Compose プロジェクトを指定します。
これを script/down.sh
で用意します。スクリプトでは basename
コマンドを使って、プロジェクト名を compose.yaml
を含むディレクトリー名から取得しています。このため、このスクリプトを使う場合は、プロジェクト名を compose.yaml
を含むディレクトリー名と一緒にする必要があります。
#!/bin/sh
SCRIPT_DIR=$(dirname "$0");
DC_DIR=$(cd "${SCRIPT_DIR}/.." || exit 0; pwd)
DC_PROJ_NAME=$(basename "${DC_DIR}")
docker compose -p "${DC_PROJ_NAME}" down
以上の環境で gitbucket のコンテナー起動は次のようになります。
cd ${PROJ_DIR}
sh script/run.sh
gitbucket のコンテナー停止は次のようになります。
cd ${PROJ_DIR}
sh script/down.sh
以上で docker container
コマンドをベースとするスクリプトを使うのと基本的には同じ環境が用意できました。ディレクトリーの準備などについては、スクリプトで用意しておけばこちらの方が使いやすそうですね。
Java ランタイム環境で試用
ここで、Java ランタイム環境がある場合は、わざわざ Docker を使って GitBucket を稼働させる必要はありません。GitBucket の本体である gitbucket.war
ファイルを入手して、これを java
コマンドで実行すれば良いです。
Java のランタイムについては種類が多くあり、どれを使うと良いかわかりにくいかと思います。いまなら Java 17 を使えば良いでしょう。ここでは Java ランタイム環境の構築については省略します。おそらく、Java を使っていない人は Docker で動かすでしょうし、すでに Java を使っている人にはわざわざ説明する必要もないはずだからです。
ここでは、次のディレクトリー構成でファイルを用意するとします。また、gitbucket-jar ディレクトリーは ${GITBUCKET_JAR_DIR}
と表記することにします。
また、「Docker Compose で試用」で用意した compose.yaml
を用意してあるディレクトリーも利用します。そちらは、${GITBUCKET_DIR}
と表記することにします。これは「Docker Compose で試用」では ${PROJ_DIR}
と表記したディレクトリーと同じ値となるとします。
gitbucket-jar/
└── script/
├── down.sh
├── init.sh
└── up.sh
JAR の入手
JAR の入手については、Web サイトや Maven リポジトリから可能ですが、Docker 環境があって、gibtucket のコンテナーを起動できる comppose.yaml
ファイルがあるなら、docker compose cp
コマンドを使うのが簡単です。手動なら次のような手順になります。
cd ${GITBUCKET_DIR}
sh script/run.sh
cd ${GITBUCKET_JAR_DIR}
docker compose -p gitbucket cp gitbucket:/opt/gitbucket.war .
cd ${GITBUCKET_DIR}
sh script/down.sh
スクリプトにすると、次のようになります。
#!/bin/sh
SCRIPT_DIR=$(dirname "$0");
GITBUCKET_JAR_DIR=$(cd "${SCRIPT_DIR}/.." || exit 0; pwd)
# GITBUCKET_DIR の指定をしない場合は、
# gitbucket-jar ディレクトリーと gitbucket ディレクトリーは
# 同じディレクトリーに置くこと
if [ -z "${GITBUCKET_DIR}" ]; then
GITBUCKET_DIR=$(cd "${GITBUCKET_JAR_DIR}/../gitbucket" || exit 0; pwd)
fi
# スリープする秒数を指定
SLEEP_NUMBER=5
if [ ! -e "${GITBUCKET_DIR}/script/run.sh" ]; then
echo "not found: ${GITBUCKET_DIR}/script/run.sh"
exit 1
fi
sh "${GITBUCKET_DIR}/script/run.sh"
# 起動するまで待機
sleep "${SLEEP_NUMBER}"
if docker compose ls | grep gitbucket | grep running > /dev/null; then
# コピー
docker compose -p gitbucket \
cp gitbucket:/opt/gitbucket.war "${GITBUCKET_JAR_DIR}/"
else
# ${SLEEP_NUMBER} 秒では起動しなかったので、ここで終了。
# 手動で "${GITBUCKET_DIR}/script/stop" 実行後、
# SLEEP_NUMBER の値を大きくして再実行が必要。
echo "not running: gitbucket"
exit 1
fi
# 停止
if [ ! -e "${GITBUCKET_DIR}/script/down.sh" ]; then
echo "not found: ${GITBUCKET_DIR}/script/down.sh"
exit 1
fi
sh "${GITBUCKET_DIR}/script/down.sh"
実行するには次のようにします。
cd ${GITBUCKET_JAR_DIR}
sh script/init.sh
Java で GitBucket 起動
入手した JAR ファイルを使って GitBucket を実行するには次のように java
コマンドの -jar
オプションで gitbucket.war
ファイルを指定するだけdす。
cd ${GITBUCKET_JAR_DIR}
java -jar gitbucket.war
これで ${HOME}/.gitbucket
に GitBucket 用のデータが用意されます。
ここで、個人利用のときは、ホームディレクトリーに出力が便利で良いのですが、システムとして使いたいときは /var/local/gitbucket
などにしたいことでしょう。その場合は、--gitbucket.home
オプションで GitBucket のデータを置くディレクトリーを指定します。
そういった対応ができるような ${GITBUCKET_JAR_DIR}/script/run.sh
を用意すると、次のようになります。ここでは、${GITBUCKET_JAR_DIR}/data
に GitBucket のデータを置くようにしてあります。
#!/bin/sh
SCRIPT_DIR=$(dirname "$0");
GITBUCKET_JAR_DIR=$(cd "${SCRIPT_DIR}/.." || exit 0; pwd)
DATA_DIR="${GITBUCKET_JAR_DIR}/data"
if [ ! -e "${DATA_DIR}" ]; then
echo "mkdir \"${DATA_DIR}\""
mkdir -p "${DATA_DIR}"
fi
if [ ! -e "${GITBUCKET_JAR_DIR}/gitbucket.war" ]; then
sh "${SCRIPT_DIR}/init.sh"
fi
java -jar "${GITBUCKET_JAR_DIR}/gitbucket.war" \
--gitbucket.home="${DATA_DIR}"
実行するには次のようにします。
cd ${GITBUCKET_JAR_DIR}
sh script/run.sh
Java で起動した GitBucket の停止
停止については、${GITBUCKET_JAR_DIR}/script/run.sh
を実行しているターミナルで Ctrl+C
を入力するか、kill
コマンドを使います。スクリプトで用意する場合は、次の内容で ${GITBUCKET_JAR_DIR}/script/down.sh
を作成します。
#!/bin/sh
# shellcheck disable=SC2009
if ps ax | grep "[g]itbucket.war" > /dev/null 2>&1 ; then
pid=$(ps ax | grep "[g]itbucket-jar/gitbucket.war" | awk '{print $1}')
kill "${pid}"
fi
これを使って GitBucket を停止には次のコマンドを実行します。
cd ${GITBUCKET_JAR_DIR}
sh script/down.sh
こちらは、コンテナーと違って、コンテナーの削除に相当するものはありません。初期化をしたい場合は、次のように ${GITBUCKET_JAR_DIR}/gitbucket.war
ファイルと ${GITBUCKET_JAR_DIR}/data
ディレクトリーを削除します。
cd ${GITBUCKET_JAR_DIR}
rm gitbucket.war
rm -fr data
おわりに
今回は GitBucket 環境を試用する方法について紹介しました。docker compose
を使えるなら、それを使うのが簡単そうだと思ったのではないでしょうか。
ただ、Java ランタイム環境があるなら、性能的には直接 java
コマンドで実行した方が有利です。Docker イメージ内でも java
コマンドで GitBucket のプログラムを実行しています。Docker は仮想環境となるので、Windows や macOS では OS 上で直接動作する Java VM を使った方が Docker 環境よりも性能はでるはずです。Linux だと Docker は同じカーネルで動作するので、性能差はほとんどないはずです。
Docker ホストの環境をクリーンにしておきたいなら、Java ランタイム環境を使うより Docker 環境を使いたいと思うことでしょう。運用もしたい場合で Java ランタイム環境を用意するのが負担でないなら、Java ランタイム環境を使いたいと思うはずです。このあたりは、どのレベルで GitBucket を動かしたいと思うかで変わってきます。
個人的には、セルフホスト Git サービスを稼働させるにあたって、GitBucket を検討したこともあり、少人数のプロジェクトで実際に使ったこともあります。当時はまだ Docker もここまで普及しておらず、その頃は Java 実装のものを使っておけば Windows、macOS、Linux のどれでも稼働できて便利だったということもあり、結構人気がありました。日本で開発されているというのも大きいです。
ということで、今回は「GitBucket も良いですよ」という話でした。
Discussion