LoginSignup
1
0

なるべくダウンタイムなくコンテナを差し替える

Last updated at Posted at 2023-08-13

頻繁にコンテナを差し替える必要があったのですが、コンテナイメージのダウンロード時間もそれなりにかかりますし、処理の手順を間違えてもダウンタイムが長くなってしまうので良い方法を考えていました。

よって以下の shell script を作成しました。

echo -------- pre --------
docker pull ${あなたのコンテナを指定}:latest
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)

echo -------- run --------
docker run -d -p 80:3000 ${あなたのコンテナを指定}:latest

echo -------- clean --------
docker image prune -a -f

事前にコンテナイメージをダウンロードしておき、そのまま落とした直後のコンテナイメージを指定して起動、使われなくなったイメージは prune で削除。これでとても楽にコンテナが差し替え出来るようになりました。

このスクリプトを活用してコンテナイメージに最新版が登場したら自動的に差し替えて、完了時に slack へ更新通知を送るスクリプトを用意してみましょう。

#!/bin/bash

# 注意事項
# - 本スクリプトは対象のコンテナが1つである時に利用すること
# - docker ps -a で一斉にコンテナ停止、削除を行なう為です
# - 対象のコンテナが複数ある場合は、コンテナ名等を指定して個別に処理するロジックに変更して下さい

# 変数
last_image_hash_file="last_image_hash.txt"
remote_image_url="${your-container-image}"
slack_webhook_url="https://hooks.slack.com/services/***********"

# 前回のイメージハッシュを読み込む
if [ -f "$last_image_hash_file" ]; then
    last_image_hash=$(cat "$last_image_hash_file")
else
    last_image_hash=""
fi

# リモートイメージのハッシュを取得
old_container_id=$(docker ps -q)
remote_image_hash=$(docker pull $remote_image_url | awk '/Digest:/ {print $2}')

# エラーハンドリング関数
handle_error() {
    echo "エラーが発生しました。"
    curl -X POST -H 'Content-type: application/json' -d "{\"text\": \"エラーが発生しています。古いコンテナイメージで起動します。\"}" $slack_webhook_url

    if [ -n "$old_container_id" ]; then
        echo "古いコンテナを再起動します。"
        docker start "$old_container_id"
    else
        echo "古いコンテナが存在しないため、スクリプトを終了します。"
        exit 1
    fi
}

# エラー時の処理を登録
trap 'handle_error' ERR

# 前回のハッシュと比較
if [ "$remote_image_hash" != "$last_image_hash" ]; then

    # コンテナ差し替え
    echo "更新を検知しました。コンテナを差し替えます。"
    docker stop $(docker ps -a -q)
    docker rm $(docker ps -a -q)

    # コンテナの起動を試みる
    if ! docker run -d -p 3000:3000 $remote_image_url; then
        # エラー発生時の処理をトリガー
        handle_error
    fi

    # 後処理
    docker image prune -a -f

    if [ -n "$slack_webhook_url" ]; then
        messages=("[ 更新通知 ]" "" "コンテナイメージ $remote_image_url を更新しました。" "最新の Hash は $remote_image_hash です")
        joined_messages=$(printf "%s\n" "${messages[@]}")
        curl -X POST -H 'Content-type: application/json' -d "{\"text\": \"$joined_messages\"}" $slack_webhook_url
    fi
    
    # 新しいハッシュをファイルに保存
    echo "リモートイメージが更新されました!"
    echo "$remote_image_hash" > "$last_image_hash_file"
else
    echo "リモートイメージは更新されていません。"
fi

上記の通り作成したら cron を設定しましょう。例えば以下の通りです。

chmod 700 /path/to/your/script.sh
crontab -e
*/5 * * * * /path/to/your/script.sh
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0