この記事でわかること
- Ubuntu 22.04 のパッケージを安全にアップデートする手順
- Docker Compose(スタンドアロン版)を最新にする方法
- Docker イメージ(OWASP ModSecurity CRS、WordPress)を更新し、Digest 値で正しく適用されたか確認する方法
普段は VS Code のリモート接続でサーバーを操作しているが、久しぶりに PowerShell で直接 SSH 接続したところ、次のメッセージが表示された。
58 updates can be applied immediately.
To see these additional updates run: apt list --upgradable
これをきっかけに、OS パッケージだけでなく Docker 周りもまとめてアップデートすることにした。その記録をまとめる。
注意: 基本的に AI(Gemini、Claude 等)に聞きながら作業しているが、AI の回答は誤りを含む場合がある。筆者自身の勘違いもあり得るため、内容は自己責任で判断・実行してほしい。
前提環境
- VPS: お名前ドットコム VPS(KVM)
- OS: Ubuntu 22.04(デフォルトの 20.04 から 2025 年に自分でアップグレード済み)
- Docker: Docker CE + Docker Compose(スタンドアロン版)
- 構成: Nginx(OWASP ModSecurity CRS)+ WordPress(php8.3-fpm-alpine)
私のサーバーの詳細は、以下↓。この記事は、この構成での話ですので、ご確認ください。

2024/4お名前.comのレンタルサーバーからVPSへ移行したときの記録になります。
お名前ドットコムVPS(KVM)はデフォルトではUbuntu 20.04サーバーだが、Ubuntu 22.04へアップグレードを去年2025に自分で実施した。以下は、その状況です。

Ubuntu パッケージのアップデート
apt upgrade で何が更新されるのか
sudo apt upgrade は、Ubuntu 22.04 という枠組みの中でインストール済みパッケージを最新にするコマンドだ。具体的には次のようなものが対象になる。
| 対象 | 例 |
|---|---|
| OS のコアコンポーネント | Linux カーネル、システムライブラリ(libc など) |
| 標準ツール | ls、grep、bash などの基本コマンド |
| インストール済みアプリ | Python、Git、Apache/Nginx など |
| セキュリティパッチ | 脆弱性を修正する重要なアップデート |
Docker は apt upgrade の対象に含まれるか?
Docker 公式の手順でインストールした場合は対象に含まれる。 公式手順ではリポジトリ(download.docker.com)をソースリストに追加するため、apt upgrade で Docker Engine も一緒に更新される。
apt upgrade で OS バージョンが勝手に上がることはない
Ubuntu には「パッケージの更新」と「OS バージョンの更新」に明確な区別がある。
sudo apt upgrade→ 22.04 の枠内でセキュリティパッチやバグ修正を適用するsudo do-release-upgrade→ 22.04 → 24.04 のように OS バージョンを上げる(明示的に実行しない限り発動しない)
サーバー環境では互換性や設定変更のリスクがあるため、この2つは厳格に分けられている。
apt upgrade と apt dist-upgrade の違い
| コマンド | 何をするか | 特徴 |
|---|---|---|
sudo apt upgrade -y | 既存パッケージを安全に更新 | 依存関係が変わる更新はスキップ |
sudo apt dist-upgrade -y | 依存関係の変更を含む更新も適用 | パッケージの追加・削除が発生することがある |
今回の判断:OS バージョンは 22.04 のまま
アップデート中に New release '24.04.4 LTS' available. と表示されたが、22.04 のままにした。メジャーアップデートは Docker のネットワーク設定やストレージ周りでトラブルが起きることがあり、22.04 のサポートは 2027 年まで続くため、急ぐ必要はない。
準備(うまくいかないときに備える)
何かあってもいいように準備をする必要がありますが、私の場合、以下のメジャーアップ時に準備したので、その点は大丈夫です。以下、参考にしてください。

スナップショットの取得
万が一に備え、お名前.com のサーバーコントロールパネルでスナップショットを取得する。
- サーバーをシャットダウン
- 回転アイコンが止まり「停止中」になるまで待つ
- 「スナップショット」をクリック → スナップショットを取得
- サーバーを起動
- シリアルコンソールで接続(コピペは
Ctrl+Shift+V) - ログイン名・パスワードを入力
以前のメジャーアップグレード時にバックアップ体制は整備済みだったので、今回はスナップショットのみ。 詳しくは過去記事を参照してほしい。
ディスク容量の確認
メモリ使いすぎてたらsudo du -h -d 1 / | sort -hで減らせる。(もっと適切なコマンドがあるかもしれないが、私は、これが効く)
sudo docker psでコンテナ動いてるか確認
・waf-nginx(Nginxのコンテナ)は docker-compose.ymlでrestart: alwaysにしてるのに再スタートしない、他のコンテナはrestart: alwaysで立ち上がってる。
reboot 後に Apache と Nginx が衝突した場合の対処
自分の環境では Apache2 が自動起動する設定になっているため、再起動後に Nginx コンテナとポート 80 が競合することがある。
# Apache を停止
sudo systemctl stop apache2.service
# Nginx コンテナを起動
sudo docker start waf-nginx
Apache を止めずに
sudo docker start waf-nginxを実行すると、ポート 80 の競合で以下のエラーになる。Error response from daemon: Cannot restart container waf-nginx: failed to bind host port for 0.0.0.0:80:172.21.0.7:80/tcp: address already in use
実際のアップデート作業
カーネルバージョンの確認(更新前)
uname -r
# 5.15.0-138-generic
パッケージリストの更新
sudo apt update
更新対象を事前に確認したい場合は以下を実行する(任意)。
sudo apt list --upgradable
補足:
apt updateはパッケージの「名簿」を更新するだけで、実際のインストールは行わない。apt upgradeが実際の更新を行う。
パッケージのアップグレード
sudo apt upgrade -y
途中で needrestart の画面が表示された。

これは「古いライブラリを使っているサービスがあるので、再起動してよいか?」と確認する画面だ。packagekit.service にチェックが入った状態で Enter を押せばよい。
なぜ再起動が必要か: アップデートをダウンロードしても、動作中のプログラムが古いライブラリをメモリ上に読み込んだままでは修正が反映されない。サービスを再起動することで、最新のライブラリを読み込ませる。
依存関係を含む更新の適用
sudo apt dist-upgrade -y
サーバーの再起動
お名前.com サーバーコントロールパネルのシリアルコンソールで実行。
sudo reboot
途中で画面が止まったように見えたが、Enter を押すとログインプロンプトが表示された。
私の場合、reboot後は必ずreboot 後に Apache と Nginx が衝突した場合の対処が必要。
カーネルバージョンの確認(更新後)
uname -r
# 5.15.0-177-generic
不要ファイルの掃除
sudo apt autoremove -y
カーネルバージョンの詳細を調べる方法
更新後のカーネル 5.15.0-177-generic の詳細は、UbuntuUpdates.org で確認できる。
- 右上の検索窓に
linux-image-5.15.0-177-genericと入力 - 検索結果に
5.15.0-177.187と表示される
バージョン番号の読み方
5.15.0— Linux カーネル本家のバージョン177— ABI 番号(カーネルの内部構造に変更があると更新される)187— アップロード番号(同じ ABI 番号内でのパッチ適用・再ビルド回数)つまり
5.15.0-177.187は「バージョン 5.15.0-177 に対して 187 回目の修正を加えたビルド」を意味する。
検索結果に「updates」と「security」の 2 行が表示されるのは、同じバージョンがバグ修正とセキュリティ対策の両方の窓口で配布されているためだ。5.15.0-177.187 をクリックすると Changelog が確認でき、修正された脆弱性(CVE 番号など)の詳細がわかる。
カーネル以外のパッケージの更新履歴を確認する
grep "upgrade " /var/log/dpkg.log
実行例:
2026-05-07 06:06:55 upgrade libnghttp2-14:amd64 1.43.0-1ubuntu0.2 1.43.0-1ubuntu0.3
2026-05-07 06:06:55 upgrade apache2:amd64 2.4.52-1ubuntu4.19 2.4.52-1ubuntu4.20
2026-05-07 06:06:56 upgrade apache2-bin:amd64 2.4.52-1ubuntu4.19 2.4.52-1ubuntu4.20
2026-05-07 06:06:56 upgrade apache2-data:all 2.4.52-1ubuntu4.19 2.4.52-1ubuntu4.20
2026-05-07 06:06:56 upgrade apache2-utils:amd64 2.4.52-1ubuntu4.19 2.4.52-1ubuntu4.20
2026-05-07 06:06:56 upgrade distro-info-data:all 0.52ubuntu0.11 0.52ubuntu0.12
各パッケージの変更内容は UbuntuUpdates.org の Updates タブ → jammy で確認できる。たとえば apache2 なら Package name が apache2 の項目を見ればよい。
Docker Compose のアップデート
Docker Compose のアップデート方法は、インストール方式によって異なる。自分の場合は Docker Compose 公式ドキュメントの「Linux スタンドアロン」方式でインストールしていた。
更新前のバージョン確認
docker-compose --version
# Docker Compose version v2.4.1
アップデート手順
# 1. 最新バージョン番号を取得
COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest \
| grep '"tag_name"' | cut -d'"' -f4)
echo $COMPOSE_VERSION # 確認用
# 2. バイナリを上書きダウンロード
sudo curl -SL "https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-linux-x86_64" \
-o /usr/local/bin/docker-compose
# 3. 実行権限を付与
sudo chmod +x /usr/local/bin/docker-compose
# 4. バージョン確認
docker-compose version
# Docker Compose version v5.1.3
Docker イメージのアップデート
3-1. OWASP ModSecurity CRS(nginx-alpine)
更新前のイメージ確認
sudo docker images --digests | grep modsecurity-crs
# owasp/modsecurity-crs nginx-alpine sha256:c8d794704a... 42b87f614319 2 years ago 94.9MB
Docker イメージの識別子
識別子 例 説明 Image ID 42b87f614319ローカルでの短縮 ID(12桁) Digest sha256:c8d794...(64桁)レジストリ上のコンテンツハッシュ。pull 元と完全一致を検証できる Tag nginx-alpine人間が読める名前。同じタグでも中身が変わることがある
使っているimageが分かっても3系なのか4系なのか分からない。私は以下の方法で調べてます。

バージョンアップの流れ
- Docker Hub で最新バージョンを確認
- GitHub の CHANGELOG で破壊的変更がないか確認
docker compose pull→docker compose up -dで更新
Step 1:Docker Hub で最新タグを確認
👉 https://hub.docker.com/r/owasp/modsecurity-crs/tags
Tags ページで Sort を「Newest」にし、Filter に nginx-alpine と入力する。1番上に表示されているものを入れればいいかというと注意しなければならない。それは、同じLast pushed about ○○ hoursにいくつもあるからだ。
以下は、すべて同じ更新時間(202606261106 = 2026年6月26日 11時06分)にビルドされています。
「Newest」でSortすると3.3.9-nginx-alpine-202606261106が1番上に表示される。
タグの読み方
| タグ | 意味 | 用途 |
|---|---|---|
| 4.27.0-nginx-alpine-202606261106 | メジャーバージョンが「4」の最新版(マイナー 27) | 最もバグ修正や機能追加が進んでいます。 |
| 4.25.0-nginx-alpine-202606261106 | メジャーバージョンが「4」の最新版(マイナー 25) | 既存のシステムがすでに 4.25 系で動いており、互換性を保ちながらセキュリティアップデート(2026年6月26日版)だけを適用したい場合に選びます。 |
| 3.3.9-nginx-alpine-202606261106 | メジャーバージョンが「3」の最新版(マイナー 3.9) | メジャーバージョンが「3」のため、4系に上げると動かなくなる古いシステム向けのメンテナンス用です。 |
tagとdigest値の関係
Dockerなどのコンテナイメージにおいて、tagとdigestは以下のような役割の違いがあります。
- tag(付箋・ラベル)
- 人間が理解しやすいように付けられた「名前」です。
- 同じイメージに対して、複数のtag(別名)を同時に貼り付けることができます。
- 後から別のイメージに貼り替えることができるため、可変(Mutable)です。
- digest値(指紋・ハッシュ値)
- イメージの構成要素(レイヤー)の内容から計算された「固有の識別子」です。
- 中身のデータ(1バイト単位)に基づいて生成されるため、内容が少しでも違えば全く異なる値になります。
- 改ざん不可能で不変(Immutable)です。
なぜtagが違うのにdigest値が同じになるのか?
今回のように、バージョン表記が異なる複数のtagでdigest値が同じになる理由は、「まったく同じ中身のイメージに対して、複数の用途(名前)でtagが打たれたから」です。
どのtagを使うかの目安と注意
2026/6/27現在のDocker hubでFilter に nginx-alpineを設定した場合について
4.27-nginx-alpine(最新の脆弱性への即時対応や新機能を重視するユーザー向け。)4.25-nginx-alpine(安定した防御・不具合の少なさを重視するユーザー向け。)4-nginx-alpine(4.25-nginx-alpineと同じもの)nginx-alpine(このタグは、新しいバージョンが出るたびに中身(紐づく digest 値)が書き換わる仕組みになっています。私が確認した時点では3系の最新になってました。)
3系か4系か、最新か安定板か、tagだけではなくdigest値を見て決める必要があります。
さらに特異なケースにおける注意点
以下の3つのtagについて、もしこれらすべてのdigest値が同じだった場合、少し特殊な状況が考えられます。
4.27.0-...4.25.0-...3.3.9-...
通常、メジャーバージョン(4系と3系)が違えば中身が異なるため、digest値も変わるのが普通です。もしこれらすべてのdigest値が「完全に一致」している場合、以下のいずれかの可能性が高いです。
- 古いバージョンのサポートが終了し、すべてのtagが「最新版」を指すように設定(エイリアス化)された
- 提供元のビルドスクリプトのミスで、すべてのtagに同じイメージが誤って紐付けられた
いずれにせよ、「digest値が同じ=中身は完全に同一」というルールは絶対です。
Step 2:GitHub Releases で変更内容を確認
👉 https://github.com/coreruleset/modsecurity-crs-docker/releases
各リリースの変更内容を確認し、破壊的変更がないかチェックする。Docker Hub のタグと GitHub の Release は、CRS のバージョン番号と日付で結びつけられる。
1. バージョン番号で結びつける
GitHubのReleaseページ(coreruleset/modsecurity-crs-docker)に
Dependency updates
chore(deps): update dependency coreruleset/coreruleset to v4.25.0 といった表記は、CRS(ルールセット)自体のバージョンを指します。
- GitHub:
v4.25.0というリリースがある - Docker Hub: タグ名に
4.25.0-nginx-alpine...と含まれている
これが一致していれば、そのリリースのコードを元に作られたイメージである証拠です。
2. 日付(タイムスタンプ)で結びつける
Docker Hubのタグの末尾にある 202604040104 のような数字は、「いつビルドされたか(YYYYMMDDHHMM)」 を表しています。
- GitHubのRelease: 各リリースのタイトルにreleae/20260404といった記載がある。
- Docker Hub: リリース直後にビルドされたイメージには、その日付が刻印されます。
Step 3:更新前のチェックと準備
Claude にyml ファイルと現在運用中のイメージ情報を添付してアドバイスをもらった結果、以下の確認ポイントが見つかった。
| 確認項目 | 結果 |
|---|---|
環境変数 MODSEC_RULE_ENGINE=on が有効か | ✅ 公式ドキュメントで確認済み |
カスタムルール z-custom-rules.conf の互換性 | ✅ Claude に判断してもらい問題なし |
nginx 設定 jikken1.conf の互換性 | ⚠️ ルール id:777 が重複していた。777 と 778 に修正 |
# カスタムルールのバックアップ
cat ./modsecurity/z-custom-rules.conf
cp ./modsecurity/z-custom-rules.conf ./modsecurity/z-custom-rules.conf.bak
# nginx 設定のバックアップ
cp ./modsecurity/jikken1.conf ./modsecurity/jikken1.conf.bak
# 現在の動作ログを保存(比較用)
sudo docker compose logs waf > waf-before-update.log
Step 4:イメージの更新と起動
今回は docker-compose.yml のタグを :nginx-alpine のまま変更せず、pull で最新になるか確認した。(最初に実験したときは、これで最新になったが、4系を使いたいのに3系が割り振られているのをみたので今は最新のtagを都度、書いてる。)
補足:
・https://hub.docker.com/r/owasp/modsecurity-crs/tagsでtagがnginx-alpineのdigest値を調べ、その値と同じtagがインストールされるので確認が必要です。注意してみないと4系のつもりが3系がインストールされることになるかもしれません。
・docker compose up -dだけでは、ローカルに同名タグのイメージがある場合、リモートの最新版を確認しに行かない。明示的にpullする必要がある。
# pull のみ実行(まだ起動しない)
sudo docker compose pull
# 起動
sudo docker compose up -d
# 起動直後のログを確認(設定エラーはここに出る)
sudo docker compose logs -f <サービス名>
ログで確認すべきポイント
| ログメッセージ | 状態 |
|---|---|
[error] ... unknown directive ... | ❌ 設定ファイルエラー |
nginx: configuration file test failed | ❌ nginx 設定エラー |
ModSecurity: Rules error | ❌ ModSecurity ルールエラー |
libmodsecurity3 version 3.0.14 | ✅ 正常起動(ModSecurity 本体のバージョン表示) |
ModSecurity: status engine is currently enabledは表示されなかったが、libmodsecurity3 version 3.0.14が表示された。Docker Hub の Image Layers にARG MODSEC3_VERSION=3.0.14と記載があり、一致しているので正常に起動している。
Step 5:更新結果の確認
sudo docker images --digests | grep modsecurity-crs
# 新イメージ:
# owasp/modsecurity-crs nginx-alpine sha256:f7ebbff373... 28350bddc8ae 4 weeks ago 108MB
# 旧イメージ:
# owasp/modsecurity-crs <none> sha256:c8d794704a... 42b87f614319 2 years ago 94.9MB
旧イメージのタグが <none> になっているのは正常。新しいイメージが nginx-alpine タグを引き継いだためだ。
Digest 値の照合で更新を確認する方法:
- Docker Hub の nginx-alpine タグページ を開く
linux/amd64の Digest(4b6626ec481f)をクリック- 表示された Index digest
sha256:f7ebbff3739ad03cff3062537543129598f94ab304ed19b895e20ddf14e1e1daが、ローカルの Digest と一致 → 更新は正常に完了 ✅
| 旧イメージ | 新イメージ | |
|---|---|---|
| Tag | nginx-alpine | nginx-alpine |
| Digest | sha256:c8d794... | sha256:f7ebbf... |
| Image ID | 42b87f614319 | 28350bddc8ae |
| 作成日 | 2年前 | 4週間前 |
| サイズ | 94.9MB | 108MB |
問題が起きた場合のロールバック
sudo docker compose down
# docker-compose.yml の image を旧 Digest で指定
# image: owasp/modsecurity-crs@sha256:c8d794704a7774399835a6bcc480181d5d01e47320171cd36679687e39e6e453
sudo docker compose up -d
旧イメージの削除(任意)
動作確認が取れたら削除して構わない。
# Image ID を指定して削除
sudo docker rmi 42b87f614319
# または、タグなしイメージを一括削除
sudo docker image prune -f
今後の運用メモ
ロールバックが必要になった場合に備え、Digest 値を手元に控えておくと安心だ。
# 旧イメージ(2024-02-27)
sha256:c8d794704a7774399835a6bcc480181d5d01e47320171cd36679687e39e6e453
# 現行イメージ(2026年4月頃)
sha256:f7ebbff3739ad03cff3062537543129598f94ab304ed19b895e20ddf14e1e1da
Docker Hub 画面の読み方(補足)
この補足では、Docker Hub の Digest 周りで混乱しやすいポイントを整理する。
Digest が存在する理由
Digest はイメージの中身が改ざんされていないことを証明する「デジタル指紋」 だ。
- Tag(
nginx-alpine): 誰でも後から付け替え可能な「ラベル」。中身が変わっても同じ名前にできる - Digest(
sha256:abcd...): 中身のデータから計算された「ハッシュ値」。1 バイトでも中身が変われば全く別の値になる
Docker Hub の 12 桁 Digest と 64 桁 Index Digest の関係
Docker Hub のタグ一覧に表示される 12 桁の Digest をクリックすると、64 桁の Index Digest が確認できる。マルチアーキテクチャイメージの場合、Index マニフェスト(全アーキテクチャをまとめたもの)のハッシュと個別アーキテクチャのマニフェストのハッシュは別物なので、12 桁を切り出しただけでは一致しないことがある。
Digest クリック時の詳細画面
| 項目 | 内容 |
|---|---|
| Layers | イメージの構築履歴(FROM alpine:3.19 → RUN apk add ... → COPY ... など)。各レイヤーの容量もわかる |
| OS/Arch | 対象 OS・CPU アーキテクチャ(Linux/amd64 など) |
| Environment Variables | デフォルトの環境変数(MODSECURITY_VERSION、CRS_RELEASE など) |
お名前.com VPS で該当するアーキテクチャ
お名前.com VPS は Intel/AMD の x86_64 CPU を使用しているため、amd64 が該当する。
uname -m
# x86_64
x86_64とamd64は呼び方が違うだけで同じもの。Docker の「マルチアーキテクチャ・イメージ」機能により、docker pull時にマシンの CPU を自動判別して適切なイメージをダウンロードするため、手動でアーキテクチャを指定する必要はない。
3-2. WordPress イメージ
WordPress は管理画面での更新とは別に、Docker イメージの更新が必要だ。この 2 つは更新する対象が異なる。
| 項目 | 管理画面での更新(Web UI) | Docker イメージの更新(docker pull) |
|---|---|---|
| 対象 | WordPress 本体、プラグイン、テーマ | OS(Alpine)、PHP、Web サーバ(fpm) |
| 反映先 | Docker のボリューム(永続データ) | Docker の実行環境(レイヤー) |
| メリット | 手軽に最新機能が使える | 脆弱性対策(セキュリティ)と安定性 |
管理画面で最新にしていても、Docker イメージの更新は別途必要。 イメージには PHP エンジンや Alpine Linux のライブラリが含まれており、これらの脆弱性は管理画面からは修正できない。
なぜイメージを更新してもデータが消えないのか
WordPress の Docker 運用では、wp-content(画像・プラグイン・テーマ)やデータベースをボリュームとしてホスト側に保存している。イメージを更新してコンテナを作り直しても、このボリュームを新しいコンテナに繋ぎ直すだけなので、データは維持される。
更新前のイメージ確認
sudo docker images --digests | grep wordpress
# wordpress php8.3-fpm-alpine sha256:d55b8e80... 4f0121924931 3 months ago 291MB
Docker Hub(https://hub.docker.com/_/wordpress/tags )で php8.3-fpm-alpine を検索すると、最新イメージは 18 日前に push されており、Digest 値も異なっていた。つまりセキュリティパッチやベース OS の更新が行われ、新しいビルドが公開されている。
更新手順
# 1. バックアップ(データベースと wp-content)
# 2. 最新イメージを取得
sudo docker compose pull
# 3. 再起動(最新の OS/PHP 環境で WordPress が動き出す)
sudo docker compose up -d
# 4. 自分の環境では Nginx コンテナの再起動も必要
sudo docker restart waf-nginx
更新結果の確認
sudo docker images --digests | grep wordpress
# 新イメージ:
# wordpress php8.3-fpm-alpine sha256:5a72878172... dfea0abdbbdc 2 weeks ago 291MB
# 旧イメージ:
# wordpress <none> sha256:d55b8e8042... 4f0121924931 3 months ago 291MB
Digest 値が Docker Hub の最新と一致していることを確認。
# 古いイメージを一括削除
sudo docker image prune
所感
サーバーで運用している各パーツのバージョンアップ方法をまとめた。まとめて管理できないため、自分で何が更新必要なのか探し出さなければならなかった。バージョンアップはしたほうがいいと思うが、そのせいで動作に不具合が出ないか気を遣うので大変だ。さらに最近は npm などのサプライチェーン攻撃の話もよく耳にするし、Docker Hub から最新のイメージを落としたとして、それがゼロデイ攻撃を受けたものだったらどうしようと不安になる。セキュリティ対策は大変である。
また、個人的に、この辺を AI エージェント丸投げで本当にまともに動くのか疑問である。結局、うまくいかず余計手間がかかりそうな気はする。無料版のチャットで聞きながらやるのが私は好きです。