AWSコンテナサーバーのアップデートを任されたら、何から始めるか?
もし自分がインフラエンジニアとして、
会社から「コンテナサーバーの諸々をアップデートしてほしい」
と依頼されたら、何から着手するだろうか。
Dockerのバージョンを上げる?
OSのパッケージを更新する?
コンテナイメージを作り直す?
どれも必要かもしれない。
ただ、更新する対象が曖昧なまま作業を始めると、
必要な更新を見落としたり、
稼働中のアプリケーションを止めたりする可能性がある。
今回は、AWS上のEC2でDockerコンテナを動かしている環境を想定する。
AWSコンソールで分かることから確認し、
必要なところだけEC2内部を調査して、
アップデートを進める流れを整理した。
なぜアップデートを依頼されたのか?
最初に確認するのは、依頼の背景と対象範囲だ。
「コンテナサーバーを更新してほしい」と言われても、
更新したいものによって作業は変わる。
- セキュリティ監査で指摘された
→ どのソフトウェアやCVEが対象か - OSのサポートが終了する
→ OSの種類、バージョン、期限は何か - Dockerが古い
→ 現在のDocker Engineと更新先は何か - コンテナイメージが古い
→ どのアプリケーションとイメージが対象か - 長期間メンテナンスしていない
→ OS、Docker、イメージのどこに問題があるか - 不具合を解消したい
→ どんな不具合で、更新によって解消する根拠は何か
依頼者には、少なくとも次を確認したい。
- 今回のアップデートで何を解決したいのか
- 対象のEC2やアプリケーションはどれか
- 対応期限はいつか
- サービス停止を許容できるか
- 更新後に何を確認できれば完了とするか
ここが決まっていれば、調査する範囲も絞れる。
まずAWSコンソールで対象EC2を確認する
いきなりサーバーにログインする必要はない。
まずAWSコンソールで、
対象EC2とその周辺構成を確認する。
AWSコンソール
→ EC2
→ Instances
→ 対象インスタンス
最初に見たいのは次の情報だ。
- インスタンスIDとNameタグ
- 使用しているAMI
- インスタンスの状態
- アタッチされているEBSボリューム
- 所属するAuto Scaling Groupの有無
- ALBのターゲットになっているか
- Systems Managerから接続できるか
ここで、
「どのEC2を更新するのか」
「そのEC2を停止した場合にどこへ影響するのか」
を把握する。
ただし、EC2の詳細画面だけを見ても、
現在稼働中のDockerコンテナや
Docker Engineの正確なバージョンまでは通常分からない。
その情報は後でEC2内部を確認する。
更新に関係するサービスだけ確認する
AWS上にあるサービスを一通り調べる必要はない。
対象EC2の更新に関係するものを確認する。
- ALB
→ 更新中にEC2へのリクエストを止められるか - ECR
→ 稼働中のコンテナイメージの取得元か - EBS・Docker Volume
→ 更新時に失ってはいけないデータがあるか - 外部DB
→ 更新がDB接続やデータに影響するか - CloudWatchなどの監視
→ 更新後のエラーやリソース使用状況を確認できるか
例えば、ECRを使っていなければ、
ECRの調査を作業項目に入れる必要はない。
RDSを使っていなければ、
RDSのバックアップを今回の更新作業に含める必要もない。
まずは対象EC2が実際に何とつながっているかを確認する。
EC2内部でOSとDockerの状態を確認する
AWSコンソールで周辺構成を把握したら、
画面からは分からない情報を確認する。
EC2への接続方法には、
SSHのほかにAWS Systems Manager Session Managerがある。
接続せずにコマンドを実行したい場合は、
Systems Manager Run Commandを利用できる環境もある。
対象EC2で、まず次を確認する。
# OS
cat /etc/os-release
# Kernel
uname -r
# Docker Engine
docker version
# Docker Compose
docker compose version
次に、稼働中のコンテナとイメージを確認する。
# 起動中のコンテナ
docker ps
# 停止中を含むコンテナ
docker ps -a
# ホスト上のイメージ
docker image ls
# Dockerが使用しているディスク容量
docker system df
docker image lsに古いイメージが残っていても、
それが現在使われているとは限らない。
実際に動いているコンテナと、
そのコンテナが使用しているイメージを
対応付けて確認する。
Docker Composeで起動している場合は、
使用中のcompose.yamlや
環境変数の管理方法も確認する。
アップデート対象を分ける
「コンテナサーバーの更新」といっても、
更新対象は一つではない。
- ホストOS
→ OSパッケージ、Kernel - コンテナ実行環境
→ Docker Engine、containerd、Docker Compose - コンテナイメージ
→ ベースイメージ、Node.jsやPHPなどのランタイム - アプリケーション
→ 依存ライブラリ、アプリケーションコード
Docker Engineを更新しても、
コンテナの中で古いNode.jsを使い続けていれば、
その問題は解消しない。
逆に、コンテナイメージだけを更新しても、
ホストOSの問題は残る。
依頼の背景と調査結果を照らし合わせて、
今回どこまで更新するか決める。
脆弱性とサポート状況を確認する
セキュリティ対応が目的なら、
「バージョンが古そう」という印象だけで
更新対象を決めない。
- 指摘されたCVEは何か
- どのOSパッケージやイメージが対象か
- 修正済みのバージョンはどれか
- 実際にそのソフトウェアを使用しているか
AWS環境では、
Amazon Inspectorの検出結果を確認できる。
ECRにイメージを保存しているなら、
対象イメージのスキャン結果も確認する。
ローカルのイメージを調べたい場合は、
Trivyなどのツールも選択肢になる。
trivy image my-app:1.0.0
検出された項目をすべて同じ優先度で扱うのではなく、
今回の依頼に関係する問題と、その影響を整理したい。
バックアップと切り戻し方法を決める
更新前に、
「失敗したらどう戻すか」を具体的に決める。
確認したいものは次のとおり。
- EC2を戻すためのAMIやEBSスナップショット
- Docker Volumeなど、EC2内に保存されたデータのバックアップ
- 更新前に使用していたコンテナイメージのタグとDigest
- 更新前の
compose.yamlや設定ファイル - 外部DBに変更が入る場合、そのバックアップと復旧方法
AMIを取得しても、
外部のDBまで一緒に戻るわけではない。
保存場所ごとに復旧方法を確認する必要がある。
特にDBのスキーマ変更を伴うアップデートでは、
古いコンテナイメージへ戻すだけでは
復旧できない可能性がある。
検証環境で更新する
更新対象が決まったら、
本番に近い検証環境で試す。
例えば、コンテナイメージを更新する場合は、
次のような流れになる。
Dockerfileや依存関係を更新
↓
新しいイメージをビルド
↓
コンテナを起動
↓
アプリケーションを動作確認
↓
脆弱性やログを再確認
Docker Composeを使用しているなら、
設定を確認してから起動する。
docker compose config -q
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=100
自社アプリのDockerfileを変更した場合、
docker compose pullだけでは新しいイメージは作られない。
ビルドが必要な構成なら、
新しいイメージをビルドして検証する。
ホストOSやDocker Engineの更新は、
コンテナイメージの更新とは分けて検証する。
必要な再起動や、
更新後にコンテナが自動起動するかも
確認しておく。
本番環境へ反映する
検証が終わったら、
本番環境の構成に合わせて反映方法を決める。
複数のEC2がALBのターゲットになっているなら、
例えば次の順番で進められる。
- 更新対象のEC2をALBのターゲットから登録解除する
- 処理中のリクエストが終わり、登録解除が完了するのを待つ
- EC2のOS、Docker、コンテナを必要な範囲で更新する
- アプリケーションの動作を確認する
- EC2をターゲットへ再登録する
- ターゲットが正常になったことを確認する
- 次のEC2へ進む
単一のEC2で動いている場合は、
更新中のサービス停止が避けられない可能性がある。
作業前に停止時間と切り戻し条件を決めておく。
また、既存EC2を直接更新する方法だけでなく、
新しいAMIやイメージを使って
EC2を入れ替える方法も検討できる。
更新後に何を確認するか
コンテナが起動しただけでは、
アップデート成功とは判断できない。
次の項目を確認する。
- コンテナの状態
→docker ps、docker compose ps - コンテナのログ
→docker logs、docker compose logs - HTTP応答
→curl、ALBのヘルスチェック - 主要な操作
→ ログイン、画面表示、データ登録など - エラー
→ アプリケーションログ、CloudWatch Logsなど - リソース使用状況
→ CPU、メモリ、ディスク - 脆弱性
→ InspectorやTrivyの再確認
例えば、HTTP応答だけなら
次のコマンドでも確認できる。
curl -I https://example.com
ただし、HTTPの応答が返るだけでは、
ログインやデータ登録が動くとは限らない。
依頼時に決めた完了条件に沿って確認する。
次回の更新をしやすくする
今回の更新で、
手順が分からない、古いイメージが大量に残っている、
バックアップの場所が不明といった問題が見つかるかもしれない。
その場合は、次回の更新に向けて改善項目を残す。
- OSパッチの適用状況を継続して確認する
- コンテナイメージを定期的にスキャンする
- Dockerfileや依存ライブラリの更新を検知する
- イメージのビルドと配布方法を整理する
- バックアップと復旧手順を文書化する
- 更新後の確認項目を定型化する
例えば、OSパッチにはSystems Manager Patch Manager、
脆弱性の確認にはAmazon InspectorやTrivy、
依存ライブラリの更新検知には
DependabotやRenovateなどを検討できる。
今回の作業範囲を超えるものは、
その場でまとめて変更するのではなく、
改善項目として記録しておきたい。
作業結果を報告する
最後に、何を変更し、
どこまで確認できたかを記録する。
- 作業の目的
→ 依頼の背景、解消したかった問題 - 更新対象
→ EC2、OS、Docker、コンテナイメージなど - 更新内容
→ 更新前後のバージョンやイメージDigest - 動作確認
→ 実施した確認と結果 - 影響
→ 停止時間、発生した問題 - 残課題
→ 今回対応しなかった項目と理由
「アップデート完了」だけでは、
次に担当する人が状況を把握できない。
更新前後の状態と確認結果を残しておく。
まとめ
自分がコンテナサーバーのアップデートを任されたら、
次の順番で進める。
- 依頼の目的と対象範囲を確認する
- AWSコンソールで対象EC2と関連する構成を確認する
- EC2内部でOS、Docker、稼働中のコンテナを確認する
- 更新対象を分けて、対応の優先順位を決める
- バックアップと切り戻し方法を用意する
- 検証環境で更新し、動作を確認する
- 本番環境へ反映する
- 更新結果と残課題を記録する
最初から関連しそうなAWSサービスを
すべて調べる必要はない。
まず対象EC2の構成をAWSコンソールで確認し、
画面から分からない情報をEC2内部で調べる。
そのうえで、今回必要な更新を安全に完了させ、
次回も同じ作業を進められる状態にしておきたい。