Docker Hubの見方、わかってますか?
皆さまはDocker Hubの見方はわかってますか?
私は正直全然わかってませんでした。
先日投稿させていただいたこちらの記事では、AWSのRDS for PostgreSQLに、EC2内にあるSpring Bootアプリケーションからアクセスするという構成をCDKを使ってデプロイしようという内容でした。
そこで、今回はこのアプリケーションをローカルでも起動させたいと思い、ローカルのDocker Desktop上にDBコンテナを立ち上げて、それで接続したらええやん!と思ったので、いざDocker Hubを見てみたのですが、たくさんある情報の中からどこの何を見ればいいのかが全然わからず、結局いつものごとくチャッピーに聞いて解決となりそうだったので、この際ちゃんと自分で理解できるようにせねば!!と思い、これを記事にして自分を戒めようと思います。
この記事では、ChatGPTと対話をしながらDocker Hubの見方について学んでいこうという内容です。(結局チャッピー使うんかい!)
「この使い方が必ず正しい!!」というものではないので、実務でどう扱うべきかわからない場合は、公式ガイドを参照したり、有識者の方々に意見を仰ぎましょう。
まずはDocker Hubにアクセスする
検索窓に「PostgreSQL」と入力して検索します。
すると一番左上に「RECOMMENDED: HARDENED IMAGE」とキラキラ輝いてるものがあります。
いかにもこれを選べば良さそうかと思いますが、ここは一旦落ち着いてチャッピーに聞いてみます。
Docker Hardened Images(DHI)とは?
まず、Docker Hubには大きく分けて次のように分類ができます。
Docker Hub
├── Official Images
│ postgres
│ mysql
│ redis
│ nginx
│
├── Docker Hardened Images (DHI)
│ dhi.io/postgres
│ dhi.io/nginx
│ dhi.io/node
│
└── Community Images
bitnami/*
linuxserver/*
...
真ん中に「Docker Hardened Images (以降、DHI)」があります。
英語の「Harden」とは「堅牢化する(セキュリティを強化する)」という意味で、
Docker Hardened Images
↓
セキュリティをより強化したDocker Image
ということです。
一般的なDockerイメージだと、
- shell
- package manager
- 各種ライブラリ
などが入ってます。
一方DHIは、
- 不要なパッケージを極力削除
- 攻撃対象を減らす
- SBOM(Software Bill of Materials:ソフトウェア部品表)を提供
- 継続的な脆弱性対応
- FIPS/STIGなどのコンプライアンス向けバリアントも提供
といった特徴があります。
つまり、普通のDockerイメージなら、そのコンテナ内に「docker exec」で入って「bash」や「apt」などを使って作業をすることはよくあると思いますが、DHIではそもそもshellもパッケージマネージャも入っていないというのもあるらしいです。
そんなのめっちゃ不便じゃん!誰が使うねん?って思うかもしれませんが、このDHIは大規模エンタープライズ向けで、金融・医療・官公庁などの強固で堅牢なセキュリティ対策が必須要件である場合に使用される想定らしいです。
つまりDHIは今回の私のように個人開発で検証したい場合に使うコンテナではないということが理解できました。
迷ったときはDocker Official Imageを使おう
じゃあどのDockerイメージを使えばいいの?ということですが、迷ったときは「Docker Official Image」を使いましょう。
Docker Hub(再掲)
├── Official Images ←これ
│ postgres
│ mysql
│ redis
│ nginx
│
├── Docker Hardened Images (DHI)
│ dhi.io/postgres
│ dhi.io/nginx
│ dhi.io/node
│
└── Community Images
bitnami/*
linuxserver/*
...
「Docker Official Image」とは、その名の通り、Docker社が各OSSコミュニティと協力して管理している公式のイメージです。
「Docker Hardened Images (DHI)」は先述の通り、大規模エンタープライズ向けです。
残る「Community Images」ですが、これは「誰でも公開できるDockerイメージ」なので、安全性などは完全に自己責任となります。
ということで消去法的にも今回は「Docker Official Image」から探していきます。
(他にも「Verified Publisher」というDocker公式ではなく、「企業公式」のDockerイメージもあるらしいですが、今回は触れないので興味がある方はご自身で調べてみてください)
先ほどの検索結果ページにて、左サイドメニューにある「Docker Official Image」にチェックを入れると検索結果が1つに絞られました。
これがDocker公式のPostgreSQLのイメージになります。
それではこのページにいきましょう。
対象のDockerイメージのページで確認すること
さて、無事に公式のPostgreSQLのDocker Hubのページにたどり着きましたが、問題はここからです。
「何を見ればいいのか?」
チャッピーに聞いてみます。
- Supported tags
- Environment Variables
- Initialization scripts
- Volume
- Port
1. Supported tags
まずは「タグ」から確認していきます。
「Overview」タブの中の「Supported tags and respective Dockerfile links」を見てみます。
たくさんのDockerイメージのタグ一覧がずらっと並んでいます。
Dockerイメージの「タグ」とは、そのDockerイメージを一意に識別するためのバージョン番号や変数名であり、多くの場合はだいたいが「バージョン番号」と「ベースOS」も含めた名称になっていることが多いです。
バージョン17系だけでもこれだけあります。
17.10, 17, 17.10-trixie, 17-trixie
17.10-bookworm, 17-bookworm
17.10-alpine3.24, 17-alpine3.24, 17.10-alpine, 17-alpine
17.10-alpine3.23, 17-alpine3.23
全部挙げていったらキリがないのですが、基本的に以下の法則に則って命名されています。
<メジャーバージョン番号>.<パッチバージョン番号>-<ベースOS名(コードネーム)>.<ベースOSバージョン番号>
じゃあどれを選べばいいのか?という話ですが、結論から言うと今回は「17」を採用します。
「17-bookworm」でも「17-alpine」でも「17.10」でもなく「17」です。
理由としまして、本記事冒頭にも書いた通り、前回の記事ではAWS RDS for PostgreSQLを利用したのですが、その際は以下のようにメジャーバージョンのみを指定していました。
// RDSの定義
const database = new rds.DatabaseInstance(this, 'RdsId', {
engine: rds.DatabaseInstanceEngine.postgres({
version: rds.PostgresEngineVersion.VER_17, // ←ここ!
}),
このように、メジャーバージョン番号のみを指定した場合、そのアプリケーションの最新パッチバージョンのものが自動的に反映される仕組みとなっています。
バージョンを指定しない場合、Amazon RDS では、利用可能なバージョン (通常は最新バージョン) がデフォルトで設定されます。マイナーバージョンではなく、メジャーバージョンを指定した場合、Amazon RDS では、指定されたメジャーバージョンの最新リリースにデフォルトで設定されます。
私がAWS CDKで指定したメジャーバージョンの「17」ですが、現在の最新パッチバージョン(マイナーバージョン)は「17.10」でした。
そして話をDocker Hubのほうに戻しますが、この中にある「17」のリンクを開いてみます。
するとGithubのページが開きます。
これはそのDockerイメージを作成するためのDockerfileのページです。
この中を見ていくと、92行目に「ENV PG_VERSION 17.10-1.pgdg13+1」という記述があり、タグ「17」で実際に動いているPostgreSQLは「17.10」であることが無事に判明しました。
ということで、AWSで利用しているものと、Dockerコンテナで利用しようとしているPostgreSQLのバージョンが一致していることが確認できたので、今回はタグ「17」でやろうと思います。
こんなに確認事項が多いなら最初からパッチバージョンまで指定しておけばよかったじゃん!って話ですが、今回は学習の意味も含めてそのままこれで進めます。
実務ではパッチバージョンまで指定して使うべきだと思います。
2. Environment Variables
次に見るべき項目は「Environment Variables」=「環境変数」です。
これはアプリケーションを開発するときにも意識するところで、Spring Bootで開発する際もapplication.yamlなどの設定ファイルにDB接続先情報として「POSTGRES_USER」や「POSTGRES_PASSWORD」など、どういうパラメータ名で何を指定すればいいのか?という情報が載っていて、後ほど作成するcompose.yamlでも必要となります。
3. Initialization scripts
次は「Initialization scripts」=「初期化スクリプト」です。
こちらもcompose.yaml作成時には必要となり、/docker-entrypoint-initdb.dにSQLファイルやshellファイルなどを配置しておくと、初回起動時に自動で読み取って実行してくれるものです。
(※ただし、今回はSpring Boot側の設定で初期SQLを読み込む設定をしているので、今回はこのInitialization scriptsは使用しません)
4. Volume
こちらは先ほど見たGithub上にあるDockerfileを再び確認します。
(再掲↓)
この中の187行目に「VOLUME /var/lib/postgresql/data」という行があります。
これが永続化をするためのボリュームになるので、今回のようにDBコンテナのデータを永続化したい場合はcompose.yamlに記述する必要があります。
5. Port
引き続き、先ほどのDockerfileの中を見ます。
ポート番号は地味に大事です。
Dockerfileの最後のほうの217行目に「EXPOSE 5432」とありますが、これは「このコンテナは5432番ポートをサービス提供に使用します」という宣言になります。
(※QiitaのGithubページのプレビューでは200行までしか表示されていません)
PostgreSQLのデフォルトポート番号が5432であることは有名な話なのでわざわざ確認する必要はないかもしれませんが、もし初めて使うコンテナの場合はここを確認するべきかもしれませんね。
注意点として、このEXPOSEはあくまで「このコンテナはXXX番ポートを使用します」というメタデータに過ぎず、自動的にそのポート番号が外部公開されるわけではありません。
docker composeでports: \ - "127.0.0.1:5432:5432"と記述され、それが実行されたときなどに初めて利用することができるらしいです。
compose.yamlを作成する
ただDocker Hub上にある情報を見るだけでは勿体ないので、これまでに得た情報を使ってcompose.yamlを作成していきましょう。
Overview内にある「How to use this image」にcompose.yamlの作成例が載っているのでこれを参考にします。
例として、Spring Bootアプリケーションでローカル起動時に読み取る設定ファイルとしてapplication-local.yamlを以下の通りに記述します。
spring:
datasource:
url: jdbc:postgresql://localhost:5432/crawl_app
username: app_user
password: local_password
そしてプロジェクトルートに以下の内容でcompose.yamlを記述します。
services:
postgres:
image: postgres:17
environment:
POSTGRES_USER: app_user
POSTGRES_PASSWORD: local_password
POSTGRES_DB: crawl_app
ports:
- "127.0.0.1:5432:5432"
volumes:
- postgres-data:/var/lib/postgresql/data
volumes:
postgres-data:
services
servicesは、docker composeで起動するサービスを定義します。
ここで指定している「postgres」はサービス名です。
今回はSpring BootをComposeに含めないため、この名前をアプリから参照することはありません。
services:
postgres:
image
本記事でも見てきた通り、今回は「17」のタグのDockerイメージを使用するので、「postgres:17」と記述します。
image: postgres:17
environment
本記事でも見てきた通り、ここでどのパラメータ名で環境変数を定義するか確認をします。
値はapplication-local.yamlで指定した内容です。
environment:
POSTGRES_USER: app_user
POSTGRES_PASSWORD: local_password
POSTGRES_DB: crawl_app
ports
記述の意味は、「ホストIP:ホストポート:コンテナポート」です。
「ローカルの5432番ポートにアクセスしたら、コンテナの5432番ポートにアクセスできますよ」というわけですね。
ports:
- "127.0.0.1:5432:5432"
volumes
永続化したいデータを名前付きボリュームへ保存します。
これにより、コンテナを削除・再作成してもデータを残せます。
末尾のほうの「volumes: \postgres-data:」がその名前付きボリューム自体の定義になります。
volumes:
- postgres-data:/var/lib/postgresql/data
volumes:
postgres-data:
compose.yamlからコンテナを起動する
それでは以下のコマンドでコンテナを起動します。
docker compose up -d
状態確認をします。
docker compose ps
# 以下のように出力されていたらOK
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
cdk-crawl-app-postgres-1 postgres:17 "docker-entrypoint.s…" postgres 25 seconds ago Up 24 seconds 127.0.0.1:5432->5432/tcp
ログ確認をしたい場合は以下のコマンドを実行しましょう。
docker compose logs -f postgres
Spring Bootアプリケーションを起動させます。
Eclipseの「実行の構成」から新規でSpring Bootアプリケーションタスクを作成し、プログラム引数に「--spring.profiles.active=local」を指定して実行します。
あとはブラウザから「http://localhost:8080/」にアクセスし、アプリケーションが起動できればOKです。
コンテナの後始末は以下のいずれかでやりましょう。
# コンテナの停止(コンテナもイメージも残る)
docker compose stop
# コンテナの停止および削除(イメージは残り、ボリュームに保存された内容も残る)
docker compose down
# コンテナの停止および削除(イメージは残るが、ボリュームに保存された内容は削除される)
docker compose down -v
# コンテナの停止および削除(イメージは削除されるが、ボリュームに保存された内容は残る)
docker compose down --rmi all
おわりに
今までなんとなく見ていたDocker Hubでしたが、これを機にだいぶ理解できた気がします。
「とりあえずチャッピーにきく」から「とりあえず公式の一次情報を見る」という癖を今後も身に着けていきたいなと思いました。
今回はPostgreSQLに注目した内容でしたが、今後はもっと様々な組み合わせでコンテナを活用していきたいので、Docker Hubには引き続きお世話になりそうです。
この記事が、私のような「なんとなく分かってるつもり」なエンジニアの方々の一助になれば幸いです。










