はじめに
Jenkins は通常、初期化されていない状態で起動します。最初の管理者は、初期パスワードを使用してコントローラーをロック解除し、永続的な管理者アカウントを作成して、Jenkins が使用可能な状態であることを確認します。
この実験では、この初回実行時のワークフローを安全に練習します。VM 上のメインの Jenkins サービスは他の実験用に設定されているため、ポート 18080 で 2 つ目の一時的な Jenkins コントローラーを起動します。その一時的なコントローラーのみを初期化し、結果を確認した後に削除します。
分離された新しい Jenkins コントローラーの起動
このステップでは、メインの Jenkins サービスを変更することなく、新しい Jenkins コントローラーを起動します。Jenkins コントローラーは設定を /var/jenkins_home に保存するため、この実験では jenkins-init-lab-home という名前の独立した Docker ボリュームを使用します。
以下の docker run コマンドは、一時的なコントローラーをバックグラウンドで起動します。-d オプションはデタッチモードを意味し、--name はコンテナに安定した名前を付け、-p 18080:8080 はホストのポート 18080 で Jenkins を公開し、-v は分離された Jenkins ホームボリュームをマウントします。
docker run -d \
--name jenkins-init-lab \
-p 18080:8080 \
-v jenkins-init-lab-home:/var/jenkins_home \
jenkins/jenkins:latest
Docker は新しいコンテナ ID を出力します。ID は実行のたびに異なるため、長い 16 進数の値が表示されれば問題ありません。
次に、Jenkins が HTTP リクエストに応答するまで待ちます。以下のループは、HTTP ステータスコードが返されるまでローカルコントローラーの /login に問い合わせます。200 レスポンスは、ログインページが利用可能であることを意味します。
until [ "$(curl -s -o /dev/null -w '%{http_code}' http://localhost:18080/login)" = "200" ]; do
echo "Waiting for the temporary Jenkins controller..."
sleep 5
done
待機メッセージが数回表示された後、プロンプトが戻ります。コンテナとポートのマッピングを確認します。
docker ps --filter name=jenkins-init-lab --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
出力にはコンテナ名とポート 18080 が含まれているはずです。
NAMES STATUS PORTS
jenkins-init-lab Up ... 0.0.0.0:18080->8080/tcp, ...
初期管理者パスワードの取得
このステップでは、Jenkins が最初の管理者のために作成したワンタイムパスワードを取得します。Jenkins はこのパスワードをコントローラーのホームディレクトリ内の /var/jenkins_home/secrets/initialAdminPassword に保存しています。
docker exec を使用して一時的な Jenkins コンテナ内で cat を実行し、パスワードをプロジェクトディレクトリに保存します。
docker exec jenkins-init-lab cat /var/jenkins_home/secrets/initialAdminPassword > /home/labex/project/jenkins-init-password.txt
このコマンドは > リダイレクトを使用して、コマンドの出力をファイルに書き込みます。これにより、シェル変数に依存することなく、次のステップでパスワードを利用できるようになります。
ターミナルの履歴に完全な値を表示させずにファイルが空でないことを確認するため、最初の数文字のみを表示します。
cut -c1-8 /home/labex/project/jenkins-init-password.txt
以下のように、パスワードの最初の 8 文字が表示されるはずです。
1a2b3c4d
永続的な管理者アカウントの作成
このステップでは、初期パスワードを使用して lab-admin という名前の正規の Jenkins 管理者を作成します。最初のパスワードはセットアップ専用です。コントローラーの初期化後、チームが使用するのは通常の管理者アカウントです。
Jenkins はフォーム送信を「Crumb(クラム)」トークンで保護しています。Crumb はそれを要求したブラウザや HTTP セッションに紐付いているため、以下のコマンドでは Jenkins のクッキーをクッキージャーファイルに保存します。
INIT_PASSWORD=$(tr -d '\r\n' < /home/labex/project/jenkins-init-password.txt)
COOKIE_JAR=/home/labex/project/jenkins-init-cookies.txt
curl -fsS -c "${COOKIE_JAR}" -u "admin:${INIT_PASSWORD}" \
http://localhost:18080/crumbIssuer/api/json \
> /home/labex/project/jenkins-init-crumb.json
次のコマンドは、小さな Groovy スクリプトを Jenkins に送信します。このスクリプトはプライベートセキュリティレルムを作成し、lab-admin ユーザーを追加し、ログイン済みユーザーにフルコントロールを付与し、セットアップウィザードを完了済みとしてマークします。
CRUMB_FIELD=$(sed -n 's/.*"crumbRequestField":"\([^"]*\)".*/\1/p' /home/labex/project/jenkins-init-crumb.json)
CRUMB_VALUE=$(sed -n 's/.*"crumb":"\([^"]*\)".*/\1/p' /home/labex/project/jenkins-init-crumb.json)
cat > /home/labex/project/initialize-controller.groovy <<'GROOVY'
import jenkins.model.Jenkins
import jenkins.install.InstallState
import hudson.security.HudsonPrivateSecurityRealm
import hudson.security.FullControlOnceLoggedInAuthorizationStrategy
def jenkins = Jenkins.get()
def realm = new HudsonPrivateSecurityRealm(false)
realm.createAccount('lab-admin', 'LabEx-Admin-123')
jenkins.setSecurityRealm(realm)
def strategy = new FullControlOnceLoggedInAuthorizationStrategy()
strategy.setAllowAnonymousRead(false)
jenkins.setAuthorizationStrategy(strategy)
jenkins.setInstallState(InstallState.INITIAL_SETUP_COMPLETED)
jenkins.save()
println('created lab-admin and completed setup')
GROOVY
curl -fsS -b "${COOKIE_JAR}" -u "admin:${INIT_PASSWORD}" \
-H "${CRUMB_FIELD}: ${CRUMB_VALUE}" \
--data-urlencode "script@/home/labex/project/initialize-controller.groovy" \
http://localhost:18080/scriptText \
> /home/labex/project/jenkins-init-result.txt
結果ファイルを確認します。
cat /home/labex/project/jenkins-init-result.txt
期待されるメッセージは以下の通りです。
created lab-admin and completed setup
初期化されたコントローラーのダッシュボードの確認
このステップでは、一時的なコントローラーが単なるロック解除画面ではなくなったことを確認します。正常に初期化されたコントローラーは、lab-admin ユーザーを認証し、Jenkins のメインページを返すはずです。
-u を指定して curl を使用し、認証を行います。-o オプションは HTML をファイルに書き込み、-w '%{http_code}' は HTTP ステータスコードのみを表示します。
curl -s -u 'lab-admin:LabEx-Admin-123' \
-o /home/labex/project/jenkins-init-dashboard.html \
-w '%{http_code}\n' \
http://localhost:18080/
ステータスコードは以下のようになるはずです。
200
次に、保存されたダッシュボードページから Jenkins 特有のテキストを検索します。
grep -o -E 'Dashboard|Welcome to Jenkins|Jenkins' /home/labex/project/jenkins-init-dashboard.html | head
少なくとも 1 行は一致するはずです。正確な HTML は Jenkins のバージョンによって異なる場合がありますが、ページが Jenkins であることを識別できるはずです。
使い捨てコントローラーの停止と削除
このステップでは、一時的なコントローラーをクリーンアップします。メインの Jenkins サービスは他の Jenkins 実験で使用されるため、このクリーンアップは重要です。一時的なコントローラーは、初回実行時の初期化を練習するためだけのものです。
まず、一時的なコンテナを停止して削除します。
docker rm -f jenkins-init-lab
次に、その分離された Jenkins ホームボリュームを削除します。
docker volume rm jenkins-init-lab-home
最後に、一時的なコントローラーが削除されたことを確認します。
docker ps -a --filter name=jenkins-init-lab --format '{{.Names}}'
このコマンドは何も出力しないはずです。結果が空であれば、その名前のコンテナは残っていません。
まとめ
分離された Jenkins コントローラーを起動し、ワンタイムの初期管理者パスワードを取得し、永続的な管理者アカウントを作成し、初期化されたダッシュボードにアクセスできることを確認して、一時的なコントローラーをクリーンアップしました。これが、使用可能な Jenkins コントローラーの背後にある基本的な初回実行時の初期化ワークフローです。