まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

毎年恒例のマンホールマップ年間アクセスランキングを発表します。 2025 年にマンホールマップでもっとも人気のあったマンホール蓋をベスト10形式で紹介します。 また今年新たに投稿された蓋の中で最も人気があった「新人賞」と、 今年最も多くの蓋画像を投稿いただいた方「最多投稿賞」を紹介します。

集計のルールとしては 2024/12/21 から 2025/12/20 までの集計期間における、 PC およびスマホのブラウザから単独ページとしてのアクセス数を集計しています。 ページビューとしての集計なので、例えば同じページの画面をリロードした場合は1回とだけカウントされます。

なお、過去11回の結果はこちらを参照ください:
2014 マンホールマップ年間アクセス数ランキング
2015 マンホールマップ年間アクセス数ランキング
2016 マンホールマップ年間アクセス数ランキング
2017 マンホールマップ年間アクセス数ランキング
2018 マンホールマップ年間アクセス数ランキング
2019 マンホールマップ年間アクセス数ランキング
2020 マンホールマップ年間アクセス数ランキング
2021 マンホールマップ年間アクセス数ランキング
2022 マンホールマップ年間アクセス数ランキング
2023 マンホールマップ年間アクセス数ランキング
2024 マンホールマップ年間アクセス数ランキング


では今年の各賞を発表します。


2025 最多投稿賞

2025 年は集計期間中に 408 枚ものマンホール画像が投稿されました。今年も多くの皆様からの投稿によってマンホールマップは支えていただきました。改めて投稿に協力いただいた皆様、ありがとうございました。

そして今年マンホールマップに最も多くの画像を投稿いただいたユーザーに与えられる賞、それが最多投稿賞です。 今年もコンスタントに投稿いただいた 42ER03 様が最多投稿でした(5年連続8回目)。 今年も感謝の限りでございます。 m(__)m

なお2位は carz82902686 様(3年連続)、 3位は私 dotnsf でした(3年連続)。上位投稿者が固定化されつつある状況は改善の余地というか、新しい施策の必要性がありそうに感じています。


2025 新人賞&総合ランキングベスト10

いよいよ 2025 年マンホールマップ年間アクセス数ランキングを発表する時がやってまいりました。 総合ランキング1位となる MVM(Most Variable Manhole) の座はどの蓋に!?


まずは新人賞です。今年投稿された中で最もアクセス数の多かった蓋を紹介します。こちらです:

市区町村投稿者画像
群馬県草津町 dotnsf


「♪草津よいとこ、一度はおいで」、で有名な群馬県草津町の湯畑周辺に設置された『ゆもみちゃん』デザインのマンホールが今年投稿された蓋の中では最も多いアクセスを記録していました。カタカナの「サ」が九つ描かれた草津町の町章も有名ですね。 

この蓋の投稿者は私(dotnsf)でした。実は2年連続新人賞でした。



では改めて 2025 年のランキングを発表します。まずは 10 ~ 4 位です。

順位昨年順位市区町村投稿者画像
10 - 東京都中央区 dotnsf


この年間アクセス数ランキングではたまに「なんでこの蓋の人気があったのか?」という理由がよくわからない蓋がランキング入りすることがあるのですが、いきなり解説の難しい蓋がなぜか10位でした。築地市場近く、浜離宮踏切跡のすぐ近くに設置された JIS マンホール蓋です。この真ん中のマークは旧東京市章と思われます。人気の秘密はそこ、、かな? 投稿者は私、dotnsf です。


第9位!

順位昨年順位市区町村投稿者画像
9 - 北海道泊村 minamu4545


北海道で唯一の原子力発電所を持つ泊(とまり)村、そのカブト岬が描かれたデザインマンホールです。漁業が盛んな地域らしく、漁船やカモメも描かれていますね。 投稿者はこのアクセスランキングでは常連となった minamu4545 様です。


第7位は同点でした。というわけで1つ目の第7位!

順位昨年順位市区町村投稿者画像
7 - 東京都葛飾区 42ER03


東京都葛飾区の地味な蓋が第7位でした。毎年のことではありますし、この後も続くのでこういってはアレですが、なぜこの地味な蓋に人気が・・・ 投稿者は最多投稿賞でもある 42ER03 様です。


もう一つの第7位!

順位昨年順位市区町村投稿者画像
7 - 静岡県静岡市 meaculpax3


静岡県静岡市のマンホール蓋ですが、より正確には「旧清水市」のマンホール蓋が第7位でした。この蓋のように市区町村合併によって現存しない自治体の足跡となる蓋には人気が集まりやすい傾向を感じます。投稿者は meaculpax3 様です。


第6位!

順位昨年順位市区町村投稿者画像
6 - 宮崎県宮崎市 my_pace_man


宮崎県宮崎市に設置された、市の花でもあるハナショウブがデザインされた蓋が第6位でした。"WELCOME TO MIYAZAKI" というメッセージは観光客向けですかね?投稿者は my_page_man 様です。ランキング入りは初じゃないかな?


第5位!

順位昨年順位市区町村投稿者画像
5 1 東京都台東区 minamu450


昨年第1位だった、東京都台東区の助六夢通り蓋が今年は第5位でした。一昨年は3位だったので、3年連続トップ10入りを果たしたことになります。浅草に設置されたこの蓋は外国人観光客にも人気ありそうだと思います。投稿者は minamu450 様です。


第4位!

順位昨年順位市区町村投稿者画像
4 - 東京都墨田区 42ER03


東京都墨田区に設置された東京都23区マンホールが第4位でした。 投稿者は 42ER03 様です。42ER03 様は第7位の蓋と併せて、地味なマンホールで2つのトップ10入りを果たしたことになりますね。





ここからはトップ3の発表です。第3位!!

順位昨年順位市区町村投稿者画像
3 - 東京都西東京市 minamu4545



東京都ですが23区や伊豆諸島以外としては珍しく、西東京市の蓋が 2025 年の第3位でした。ケヤキ、ハナミズキ、ヒマワリ、コスモス、スイセン、そしてツツジが描かれた美しいカラーマンホールです。 投稿者はminamu4545様(第9位で紹介した minamu450 様と同一人物)です。2年連続の3位獲得でした。


第2位!!!

順位昨年順位市区町村投稿者画像
2 - 岐阜県岐阜市 SatoMachiya




岐阜県岐阜市(旧柳津町)の旧町章がデザインされたハニカム柄の地味な蓋が今年の第2位となりました。上述しましたが、このような現存しない自治体の足跡がマンホールとして残っているのは地元の人にとっては嬉しいものですよね。なおこの画像はマンホールマップが生まれた 2011 年に投稿されたものでした。14年目にして初のランキング入りでした。投稿はこの年間ランキングでは常連の SatoMachiya 様です。

さて 2025 年の MVM はどの蓋に?  注目の第1位!!!!
























順位昨年順位市区町村投稿者画像
1 - 大阪府泉南郡田尻町 minamu4545


大阪府泉南郡田尻町のマスコットキャラクター『たじりっち』が描かれたデザインマンホールが 2025 年の MVM となりました。蓋の真ん中に大きく描かれているので他が目立たなくなっているのですが、よく見るとたじりっちの頭には田尻の特産品でもあるタコやコスモスが描かれており、また背景にはスカイブリッジ、ヨット、航空機といった田尻でよく見かける風景が描かれています(ちなみにたじりっち自身も泉州タマネギをモチーフにしています)。実は今年はミャクミャクマンホールの人気が高いのではと想像していたのですが、情報量の多いこのデザインマンホールが同じ大阪のライバルをぶっちぎっての MVM となりました。

投稿者である minamu4545 さんはこれで4年連続 MVM タイトルホルダーとなりました。人気蓋をかぎ分ける鋭い嗅覚をお持ちなのだと思います。 あらためておめでとうございます!!


ちなみに以前はアクセスランキングを席巻していた「ポケふた」、今年もランキングに入ることはありませんでした。 もうね、こういうのがマンホールマップのよく分からないところで、データサイエンス泣かせではあります。。


さて来年のマンホールマップランキングはどうなるのでしょう?
午年となる 2026 年も引き続きマンホールマップをよろしくおねがいします。




IBM Cloud から提供されている生成 AI の自動化ソリューションである watsonx Orchestrate の agent builder を使ってみました。システムプロンプトや RAG 、 MCP 、外部エージェントといった生成 AI の補助機能を簡単に使って独自エージェントを定義したり、定義したエージェントを外部公開したり、といったことが簡単に実現できる IBM の生成 AI ソリューションです(IBM Cloud アカウントがあると1か月間無料トライアルで使えます):
2025121801


ここで作成した自分のエージェントを REST API として公開することもできますが、より簡単な外部連携の方法として、小さなスクリプト(JavaScript)を HTML に貼り付けて、その HTML ページ内にチャット機能を埋め込む形でエージェントを使う、といったこともできます(embedded agent 機能と呼びます):
2025121802
(agent builder を使って作ったエージェントを・・)


2025121803
(外部ウェブページに貼り付けてチャットボットとして活用する)


この embedded agent を使うことで HTML 内を編集可能なウェブページであれば(WordPress のような CMS も含めて)作成したエージェントを使ったチャットボット機能を任意のページに埋め込むことができるようになります。比較的簡単な外部連携方法の1つです。


しかし、この embedded agent 機能を私が使おうとしたところうまく動きませんでした。そこで色々調べた所、IBM Cloud 版の watsonx Orchestrate では現状(2025年12月) embedded agent はデフォルト設定のままでは正しく動作しない、ということがわかりました。2026 年初頭のアップデートによって IBM Cloud 画面内からの設定変更が可能になるような予定もあるらしいのですが、現時点では REST API を呼び出す形で watsonx Orchestrate の設定内容を変更(Security を Disabled に変更)しないと embedded agent が使えない、ということが分かりました。

そのためのセキュリティ変更を curl と jq が導入された Linux/macOS 環境で実施するためのシェルスクリプトを独自に作って用意しました。以下の内容を set_watson_embed_security.sh として保存し、実行権限を付けてください:

#!/usr/bin/env bash
# set_watson_embed_security.sh
# IBM Cloud IAM トークンを取得し、Watson Orchestrate Embed Secure Config を更新する。
# Usage:
#   bash set_watson_embed_security.sh --api-key "(API キー)" --instance-id "(インスタンスID)" [--insecure]

set -euo pipefail

IAM_URL="https://iam.cloud.ibm.com/identity/token"
WATSON_BASE_URL="https://api.jp-tok.watson-orchestrate.cloud.ibm.com"
INSECURE_FLAG=""
API_KEY=""

INSTANCE_ID=""

log() { printf '[INFO] %s\n' "$*" >&2; }
err() { printf '[ERROR] %s\n' "$*" >&2; }

# 引数パース
while (( $# )); do
  case "$1" in
    --api-key)
      API_KEY="${2:-}"; shift 2 ;;
    --instance-id)
      INSTANCE_ID="${2:-}"; shift 2 ;;
    --insecure)
      INSECURE_FLAG="--insecure"; shift ;;
    -*)
      err "不明なオプション: $1"; exit 1 ;;
    *)
      err "不明な引数: $1"; exit 1 ;;
  esac
done

# 必須チェック
[[ -n "${API_KEY}" ]] || { err "API KEY が指定されていません。--api-key を指定してください。"; exit 1; }
[[ -n "${INSTANCE_ID}" ]] || { err "INSTANCE ID が指定されていません。--instance-id を指定してください。"; exit 1; }

# jq があるか確認(任意)
JQ_AVAILABLE=0
if command -v jq >/dev/null 2>&1; then
  JQ_AVAILABLE=1
fi

log "IBM Cloud IAM アクセストークンを取得中..."


# IAM トークン取得
# 参考のコマンド例:
# curl --fail -sS --insecure --request POST \
#   --url "https://iam.cloud.ibm.com/identity/token" \
#   --header "Content-Type: application/x-www-form-urlencoded" \
#   --data "grant_type=urn:ibm:params:oauth:grant-type:apikey&apikey=(API KEY)"

IAM_RESP="$(curl --fail -sS ${INSECURE_FLAG} \
  --request POST \
  --url "${IAM_URL}" \
  --header "Content-Type: application/x-www-form-urlencoded" \
  --data "grant_type=urn:ibm:params:oauth:grant-type:apikey&apikey=${API_KEY}" \
  || { err 'IAM トークン取得に失敗しました。API KEY が正しいか、ネットワーク/プロキシ/証明書を確認してください。'; exit 1; })"

# アクセストークン抽出
ACCESS_TOKEN=""
if [[ "${JQ_AVAILABLE}" -eq 1 ]]; then
  ACCESS_TOKEN="$(printf '%s' "${IAM_RESP}" | jq -r '.access_token // empty')"
else
  # jq が無い場合の簡易抽出(最低限の JSON 形式想定)
  ACCESS_TOKEN="$(printf '%s' "${IAM_RESP}" | sed -n 's/.*"access_token"[[:space:]]*:[[:space:]]*"\([^"]\+\)".*/\1/p')"
fi


if [[ -z "${ACCESS_TOKEN}" ]]; then
  err "アクセストークン抽出に失敗しました。応答: ${IAM_RESP}"
  exit 1
fi

log "アクセストークンの取得に成功しました。"

# Watson Orchestrate Embed Secure Config 更新
CONFIG_URL="${WATSON_BASE_URL}/instances/${INSTANCE_ID}/v1/embed/secure/config"
BODY='{"is_security_enabled": false}'

log "Watson Orchestrate の Embed Secure Config を更新します: is_security_enabled=false"
# ステータスコードを取得して判定

HTTP_CODE="$(curl -sS ${INSECURE_FLAG} \
  -X POST "${CONFIG_URL}" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -d "${BODY}" \
  -w '%{http_code}' -o /tmp/watson_embed_resp.$$ || true)"

if [[ "${HTTP_CODE}" =~ ^2[0-9][0-9]$ ]]; then
  log "設定更新に成功しました。(HTTP ${HTTP_CODE})"
  printf '\n=== API 応答 ===\n'
  cat /tmp/watson_embed_resp.$$

  printf '\n===============\n'
  rm -f /tmp/watson_embed_resp.$$
else
  err "設定更新に失敗しました。(HTTP ${HTTP_CODE})応答ボディ:"
  printf '\n=== API 応答 ===\n'
  cat /tmp/watson_embed_resp.$$
  printf '\n===============\n'
  rm -f /tmp/watson_embed_resp.$$
  exit 1
fi

log "一連の処理が完了しました。"
exit 0

実行時は以下のように API キー(※1)と watsonx Orchestrate のインスタンス ID (※2)を指定します:
$ ./set_watson_embed_security.sh --api-key "(API キー)" --instance-id "(インスタンスID)"

※1※2いずれも IBM Cloud で watsonx Orchestrate インスタンスを選択した画面の Manage メニュー内 "Credentials" 部に記載されています。なおインスタンス ID は URL と書かれた文字列内の最後、"/instances/" に続くランダムに見える文字列部分がインスタンス ID です:
2025121901


これらの情報をコマンドラインで指定して実行すると、API キーからアクセストークンを取得して、セキュリティを無効化するための API が実行されます。

処理が成功すると「設定更新に成功しました。」「一連の処理が完了しました。」というメッセージが表示されます。また API 応答結果のJSON 文字が表示され、その最後に "is_security_enabled": false と表示されていればセキュリティの無効化に成功しています:
2025121902


現時点では、このセキュリティ無効化に成功できている状況下で watsonx Orchestrate の embedded agent が動きます:
2025121803


なお watsonx Orchestrate における「セキュリティの有効化/無効化」についてはこちらを参照ください:
https://developer.watson-orchestrate.ibm.com/manage/channels#enabling-security




最近、VM を扱う機会が多くなりました。何度も色んなパーティショニング要件で Linux をインストールしている中で、これまでちゃんと理解してなかった VG(Volume Group) と LV(Logical Volume) についても理解が深まりました。そのアウトプットの1つとして、ルートディレクトリの容量を無限に増やすことができるような形で Linux VM(VM でなくても OK)を作るための手順等を紹介しようと思い、まずはその前提知識となる VG / LV についてまとめてみます。


【「ルートディレクトリ容量を増やせるようにする」とは?】
Linux に慣れる前に使っていると、最初のうちはあまり深く考えずに VM 等で Linux 環境を用意して使い続けることになり、どこかのタイミングで特定のディレクトリにデータが集まりすぎてディスクが足りなくなってしまう、という経験はないでしょうか?

例えば MySQL データベースとして使っていると、(デフォルト設定だと)そのデータは /var/lib/mysql/ 以下に溜まっていきます。データを多く扱ううちにこのフォルダ以下に大量のファイルが溜まっていくことになります。 また(WordPress のような形も含めて)httpd サーバーとして多くのデータを扱っていると、/var/www/html/ 以下に多くのファイルが溜まっていくことになります。このようにあらかじめ容量に注意すべきディレクトリが分かっている場合は、そのディレクトリに大容量ディスクをマウントして使うとか、その上で LV 化(後述)しておいて後から容量追加できるようにしておく、といった準備が可能です。

問題はそのような大容量が必要なディレクトリ(上述の例だと /var/lib/mysql や /var/www/html )が事前にわからない場合です。最初はそもそも多くのデータを使うつもりもなく作った環境を、後から当初想定していなかった用途でも利用するようになって、あらかじめ容量を拡張できるような準備をせずに使い始めることもあると思っています。しかもこの場合だと利用開始時点では「どのディレクトリに多くのデータが集まるのかもわからない」ので、事前に準備できることがあるとすれば「/(ルートディレクトリ)の容量を後から動的に追加」できるようにしておく必要があります。

特定のサブディレクトリ以下ではなく、ルートディレクトリ自体が拡張可能になっていれば「後からディスクが足りなくなる」ことへの不安はかなり解消されると思っています。


【PV と VG と LV の関係】
以下、"PV", "VG", "LV" という用語を使います。まずはこれらの意味を簡単に紹介します:

PV(Physical Volume): 物理ボリューム
後述する「論理的なボリューム」に対比する意味での「物理的なボリューム」です。論理的なボリュームでは複数のディスクをまとめて1つのディスクであるかのように扱うのに対し、物理的なボリュームでは複数のディスクを(パーティショニングすることはあっても)1つにまとめて扱うのではなく、あくまで1つのディスクは1つとして取り扱う考え方です。厳密には1つの物理ディスクをパーティショニングして1つまたは複数の空間(=ボリューム)として扱います。「論理ボリューム」という考え方をしないのであれば「1つの物理ディスク内の1パーティション=1つの物理ボリューム」です。

VG(Volume Group): ボリュームグループ
PV とは逆に、複数のディスクであっても論理的に1つのディスクとしてみなす、という考え方です。この論理的なディスクをボリュームグループ (Volume Group) と呼びます。

複数の物理的なディスクをまとめて1つの VG を定義します。VG には後からディスクを動的に追加することもでき、そのサイズは追加したぶんだけ増えます。

LV(Logical Volume): 論理ボリューム
Linux のファイルシステムはマウントと呼ばれる仕組みで複数のディスクを1つの空間にマッピングすることができます。この考え方は物理ディスクだけでなく、論理ディスクにも適用できます。

物理ディスク同様に、複数のディスクからなる論理的な1台のディスクをパーティショニングしてマウントすることになります。この論理的なパーティションが論理ボリューム(LV) となり、LV を管理する方法を LVM (Logical Volume Manager) と呼びます。


【2つの物理ディスクを使った場合の比較】
2つの物理ディスク(/dev/sda 容量は 100GB と /dev/sdb 容量は 200GB)を使って Linux マシンを構築するケースを想定し、PV で作る場合と LV で作る場合を比較します。

PV で(というか、LV を使わずに)ルートディスクを作る場合、/dev/sda に1つのパーティション /dev/sda1 を作ってルート(/)にマウントすると仮定すると、100GB のディスク容量を持つファイルシステムが作れます:
2025090501


一方、LV(論理ボリューム)では物理的なサイズやとは関係なく、論理的に定義した空間の容量として考えます。例えば /dev/sda1 を1つの VG とみなし、この VG 全体を1つの LV とみなしてパーティションを作り、このパーティションをルート(/)にマウントすることで 100GB の容量を持つファイルシステムとなります:
2025090502


ここまでだと結局どちらも 100GB の空間を持つファイルシステムが作られることになり、同じことのように見えてしまって、PV と LV の違いが分かりにくいと思います。違いを分かりやすくするためにもう1つ、別に「容量 200GB のディスク /dev/sdb」が手元にあると仮定します。

PV で考えると、この 200GB のディスク /dev/sdb は先ほどの 100GB のディスク /dev/sda とは完全に別のディスクという扱いになります。「容量が 100GB のディスクA」と「容量が 200GB のディスクB」という2つのディスクです。Linux の機能を使って、ディスクAをルートディスク(/)として、ディスクBを /home にマウントすることはできますし、その場合「両方合わせて 300GB」にはなります。しかしディスクAに余裕があったとしてもディスクBに余裕がなければ /home にデータを追加できなくなってしまいます:
2025090503


一方 LV で考えるとこの辺りを柔軟に考えることができるようになります。もともとディスクAをまるごと使って VG を作成していましたが、更にディスクBも同じ VG に追加することができます。この場合、この VG のサイズ(つまり LV のサイズ)は 300GB になります。ディスクBに(物理的な)余裕がなかったとしても、ディスクAに余裕があれば LV にデータを追加可能です。仮にディスクA、B両方の余裕がなくなってしまった場合も、更に別の物理ディスクCを VG に追加することで、動的に VG/LV を拡張することが可能です:
2025090504


1点注意が必要なのは、この論理的な LV の空間が linux のどのディレクトリにマウントされているかです。例えばルートディスクは別に存在していて、 この LV が /mnt にマウントされていた場合、/mnt 以下には最大 300GB のデータを格納することができますが、それ以外のディレクトリ(/usr など)はルートディスクの空きを意識する必要がある、という点です。

なお、1つの VG を1つの LV にする必要はありません。物理ディスクをパーティショニングする時のように、1つの VG から複数の LV に分けて使うことも可能です。



Linux では複数ディスクを論理的に扱う VG/LV という概念があることを説明しました。次回はこの考え方を使って、ルートディレクトリを LV で作り、後からルートディレクトリを拡張する具体的な手順を紹介予定です。




このページのトップヘ