docker run docker/whalesayがエラーになる
こちらのDocker ドキュメントのwhalesay イメージの検索と実行を学習しようとして、下記コマンドを入力するとエラーになりました。
docker run docker/whalesay cowsay boo
下記は、エラー内容です。
Unable to find image 'docker/whalesay:latest' locally
docker: Error response from daemon: [DEPRECATION NOTICE] Docker Image Format v1 and Docker Image manifest version 2, schema 1 support is disabled by default and will be removed in an upcoming release. Suggest the author of docker.io/docker/whalesay:latest to upgrade the image to the OCI Format or Docker Image manifest v2, schema 2. More information at https://docs.docker.com/go/deprecated-image-specs/.
See 'docker run --help'.
最新のDocker ドキュメントでは、whalesayに関する記述はなくなっています。
エラーの原因は、公式イメージ「docker/whalesay」が古い形式のままであるため、使用できないことにあります。そこで今回は、新しく「whalesay」を作成して対応することにしました。
docker run docker/whalesayのエラー原因
Dockerイメージ形式が古いdocker/whalesayイメージは、Docker Image Format v1 または Docker Image Manifest v2, Schema 1 形式で作成されていて、形式が古く、新しいDockerバージョンではデフォルトで無効化されているためのようです。
Dockerの仕様変更
Dockerは、イメージ形式の互換性を維持するために長らくサポートしていましたが、非推奨となり新しい形式(OCI FormatやDocker Image Manifest v2, Schema 2)への移行を進めています。
OCI Format、Docker Image Manifest v2, Schema 2って何?
OCI Format
概要
- OCI(Open Container Initiative)は、コンテナランタイムとイメージの標準仕様を定める業界団体です。
- Docker社が提供していた独自仕様をオープンスタンダード化したもの。
- コンテナイメージの互換性と移植性を向上させる目的で開発。
特徴
- 標準化: OCIイメージ仕様は、DockerやPodman、Kubernetesなど、主要なツールでサポート。
- 移植性: 異なるコンテナランタイム間でのイメージの移植が簡単。
- シンプルな構造: イメージのレイヤーやメタデータが扱いやすい構造に改善。
OCIイメージの構造
- Manifest: イメージのメタデータ(レイヤー構成やエントリポイントなど)。
- Config: イメージの設定情報(環境変数、コマンド、作業ディレクトリなど)。
- Layers: コンテナのファイルシステムを表す圧縮されたレイヤー。
Docker Image Manifest v2
概要
- Dockerが提供するコンテナイメージの仕様。
- イメージのメタデータを管理するManifestのバージョン2。
- Schema 1の非効率な部分を改良し、OCI Formatと互換性を持たせています。
特徴
- 効率化: レイヤー管理が効率化され、イメージのプッシュ/プル速度が向上。
- セキュリティ: デジタル署名やハッシュによる改ざん検知をサポート。
- マルチプラットフォーム対応: 異なるアーキテクチャ(例:
amd64,arm64)のイメージを単一のマニフェストで管理可能。
Schema 1 と Schema 2 の違い
| 特徴 | Schema 1 | Schema 2 |
|---|---|---|
| 導入時期 | 初期のDockerイメージフォーマット | 2015年以降 |
| レイヤー管理 | 非効率なリンクリスト形式 | フラットなリスト形式で効率的 |
| セキュリティ | ハッシュによる検証なし | 各レイヤーのSHA256ハッシュで検証 |
| マルチプラットフォーム | 非対応 | 対応 |
| OCIとの互換性 | 非互換 | 互換 |
whalesayを作成
whalesayをPythonで新規作成し、ソースからイメージをビルドすることにしました。
作成するwhalesayの仕様は、下記の通りです。
docker run whalesay -t text -c character
<オプションについて>
textは、表示させたい文字を指定。
-tの指定がない場合は、fortune プログラムの結果を出力する。
-cは、表示させたいキャラクターを指定。
下記のキャラクターが指定可能。
cow cat duck horse dolphin whale
指定がない場合は、whaleを使用
whalesayソースコード(Python)の作成
import argparse
import subprocess
# CHARACTERS辞書(既存の定義)
CHARACTERS = {
"cow": r"""
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
""",
"cat": r"""
\ /\_/\
\ ( o.o )
> ^ <
""",
"duck": r"""
\ __
\<(o )___
( ._> /
`---'
""",
"horse": r"""
\ // \\
\ ((o o))
\\ - //
\===/
""",
"dolphin": r"""
\ __
\ ('v`)
>---\=\
^^
""",
"whale": r"""
\
\## .
## ## ## ==
## ## ## ## ## ===
________________________/ ===
/ /
\ / ===-
\______ O __/
\ \ __/
\____\_______/
""",
"dog": r"""
\ /o\_/o\
\ ( ^.^ )
(")_(")
"""
}
def create_bubble(text):
"""吹き出しを生成する関数"""
text_width = len(text) + 2
bubble_top = " " + "_" * text_width
bubble_middle = f"< {text} >"
bubble_bottom = " " + "-" * text_width
return f"{bubble_top}\n{bubble_middle}\n{bubble_bottom}"
def get_fortune():
"""fortuneコマンドの出力を取得する関数"""
try:
result = subprocess.check_output(["fortune"], text=True).strip()
except FileNotFoundError:
result = "fortune command not found."
return result
def cowsay(text, character="cow"):
"""cowsayを実行する関数"""
bubble = create_bubble(text)
character_art = CHARACTERS.get(character, CHARACTERS["cow"])
print(f"{bubble}\n{character_art}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Python cowsay clone")
parser.add_argument(
"-t", "--text", type=str, help="吹き出しのテキスト (指定がない場合は fortune の結果を使用)"
)
parser.add_argument(
"-c", "--character", type=str, default="whale",
help="キャラクター選択 (デフォルト: whale)"
)
args = parser.parse_args()
# -tオプションが指定されていない場合、fortuneの結果を使用
text = args.text if args.text else get_fortune()
# cowsayを実行
cowsay(text, args.character)
Dockerfileの作成
# ベースイメージ
FROM python:3.9-slim
# 必要なパッケージをインストール
RUN apt-get update && apt-get install -y \
fortune-mod \
busybox \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# システムPATHに/usr/gamesを追加
ENV PATH="/usr/games:${PATH}"
# 作業ディレクトリを設定
WORKDIR /app
# cowsay.pyをコピー
COPY cowsay.py /app/
# BusyBoxをデフォルトのシェルに設定
RUN ln -sf /bin/busybox /bin/sh
# 実行コマンドを設定
ENTRYPOINT ["python", "/app/cowsay.py"]
- FROM python:3.9-slim
ベースとなるイメージとしてpython:3.9-slimを使用 - RUN
イメージにコマンドを実行し、その結果を保存します。
ここではapt-getを使用して追加パッケージをインストールしています。 - apt-get install -y
以下の2つのパッケージをインストールします。
fortune-mod:ランダムなメッセージ(名言やジョーク)を表示するコマンド。
busybox:シンプルで軽量なLinuxツール集。シェルやファイル操作コマンドが含まれる。 - apt-get clean
キャッシュをクリアし、イメージサイズを削減します。 - rm -rf /var/lib/apt/lists/*
apt-getで使用したパッケージリストを削除し、イメージをさらに軽量化。 - ENV PATH=”/usr/games:${PATH}”
環境変数PATHに/usr/gamesディレクトリを追加。fortune-modは通常/usr/gamesにインストールされますが、PATHに含まれていない場合、コマンドが見つからなくなります。 - WORKDIR /app
コンテナ内での作業ディレクトリ(カレントディレクトリ)を設定。
以降のコマンド(例:COPYやRUN)は/appディレクトリ内で実行されます。 - COPY cowsay.py /app/
ホストのcowsay.pyをコンテナ内の/app/ディレクトリにコピー。 - RUN ln -sf /bin/busybox /bin/sh
コンテナ内のデフォルトシェル/bin/shをBusyBoxのシェルに置き換え。 - ENTRYPOINT [“python”, “/app/cowsay.py”]
コンテナ起動時に実行するデフォルトのコマンドを設定。
Dockerイメージの作成
作業ディレクトリを作成し、whalesayソースコファイルをcowsay.pyとして保存する。
上記の内容で、Dockerfilを作成し保存する。
作業ディレクトリ内で、下記のコマンドを実行しイメージ構築する。
docker build -t docker-whale .
Dockerイメージの確認と実行
下記のコマンドでDockerイメージを確認する。
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker-whale latest 87cc9933c880 52 minutes ago 193MB
下記はDockerイメージの実行例です。
docker run docker-whale
___________________________
< Condense soup, not books! >
---------------------------
\
\## .
## ## ## ==
## ## ## ## ## ===
________________________/ ===
/ /
\ / ===-
\______ O __/
\ \ __/
\____\_______/
docker run docker-whale -t Hello,world! -c dog
______________
< Hello,world! >
--------------
\ /o\_/o\
\ ( ^.^ )
(")_(")
docker run docker-whale -t boo -c cow
_____
< boo >
-----
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
以上で、Docker ドキュメントの自分でイメージを構築までが完了しました。
次は、Docker ドキュメントのDocker Hub アカウントとリポジトリの作成から進むことができます。

