はじめに:なぜこんなことを…

ふと、昔の思い出に浸っていました。

社会人新人時代、メインフレーム開発をやってたな…あの複雑怪奇な JCL、COBOL、PL/1・・・あの独特の世界観。あの時代は、今のような情報も少なくて、ひたすら試行錯誤の日々だった。

「それって、ブログのネタになるんじゃ…?」

ふと、そんなことを考えました。

「もし、現代の技術(Docker、Apple Silicon など)を使って、あの時代のシステムを動かせたら、その過程での試行錯誤や工夫は、技術ブログとしていい記事になるかもしれない。」

調べてみると、TK4-Hercules というプロジェクトがあるではないですか。IBM MVS 3.8j を Docker で実行できる。

「これだ。やってみよう。」

結果?

丸一日、Google先生なしに試行錯誤をすることになりました。

本記事は、そのドタバタの記録です。もし同じ轍を踏む人がいたら、少しでも参考になれば幸いです。


TK4-Herculesとは(そして、なぜ自分はハマったのか)

TK4-Herculesは、Hercules System/370 emulator上でIBM MVS 3.8j(Service Level 8505, from 1981)を動作させるDockerコンテナです。

1981年…43年前のメインフレーム環境を、2025年のMacで動かせる。
(まあ、自分は1997年〜5年間ほどやっていただけですが・・・)

不思議なことに、このプロジェクトを発見した瞬間、思い出がいっぱい蘇ってきました。あのモノクロのターミナル画面、c3270コマンド、JCLスクリプト…あの独特の体験が、Dockerコンテナで再現されているなんて。

「試しにやってみるか」

その一言で、自分の地獄の試行錯誤は始まりました。

情報の砂漠

最初、自分が直面した大きな問題は情報の不足です。

  • Apple Silicon Mac上でのクロスプラットフォームビルド? → ほぼ情報がない
  • Herculesの起動トラブル? → Stack Overflowにも答えがない
  • c3270のポート指定? → ドキュメントをよく読め、と言われるだけ

Google で検索しても、大抵は古い情報か、まったく関係のない話ばかり。そうなると、自分の手で試して、エラーメッセージとにらめっこするしかありません。

それが、実は一番の学習になったのですが。


環境

  • Host: Apple Silicon Mac(M1/M2/M3/M4)- 自分の場合はM4
  • OS: macOS 26.0+
  • Container Runtime: Docker Desktop for Mac
  • Guest OS: IBM MVS 3.8j-tk4(1981年のメインフレーム)
  • Emulator: Hercules 4.4.1
  • Architecture Nightmare: x86_64のバイナリをARM64のMacで動かす → Rosetta 2に祈る

セットアップ:簡単に見える5ステップ(でも実際は…)

ステップ1: Rosetta 2のインストール(5分)

まずはこれ。Apple Silicon では x86_64 バイナリを実行するために Rosetta 2 が必須です。

softwareupdate --install-rosetta

これで完了。簡単です。

完了メッセージ:

Install of Rosetta 2 finished successfully

当時の心情: 「よし、簡単だ。この調子ならすぐできるな」← 後に後悔することになる

ステップ2: Docker Desktopの設定(3分)

Docker Desktop のメモリとCPUを確保します。

  1. Docker Desktop を開く → Settings
  2. Resources タブで以下を設定:
    • Memory: 2GB以上(推奨: 4GB。けちるな)
    • CPUs: 2以上
    • Swap: 1GB以上

当時の心情: 「まだ簡単。もしかして、ネットの情報は古いのか?」

ステップ3: プロジェクトのクローン(1分)

git clone https://github.com/skunklabz/tk4-hercules.git
cd tk4-hercules

README を読むと、セットアップ手順が書いてあります。

当時の心情: 「いけるいける。」

ステップ4: Docker イメージのビルド(2分…だと思ってた)

README に従って実行:

make build

…30秒待つ…

…1分待つ…

…1分30秒…

ついに完了。TK4- ZIP ファイル(238MB)のダウンロードと展開が含まれていました。

当時の心情: 「あ、思ったより時間かかったな。でも、これで起動するはず…」

実際には、ここまでは非常にスムーズでした。本番はここからです。

ステップ5: コンテナの起動(ここから地獄)

docker compose up -d

起動確認:

docker compose ps

出力:

NAME                COMMAND                  SERVICE             STATUS
tk4-hercules-1      "/bin/bash /tk4-/..."   tk4-hercules        Up 2 minutes

ステータスが Up になった!

ログを確認しようとします:

docker compose logs -f

そこで見た光景:

=== TK4- MVS Startup ===
=== TK4- MVS Startup ===
=== TK4- MVS Startup ===
=== TK4- MVS Startup ===
=== TK4- MVS Startup ===

無限ループ。

当時の心情: 「あ、これ、やばい。」


試行錯誤の記録:5時間の格闘

こここからが、本当の戦いです。以下、実際に経験した4つの課題と、その解決までの苦労の道を記します。

課題1: 無限ループ地獄

最初の症状:

=== TK4- MVS Startup ===
=== TK4- MVS Startup ===
=== TK4- MVS Startup ===

当時の思考プロセス: 1. 「これは何だ?」 2. ネットで検索 → 情報がない 3. ログをもっと読む → 何も出ていない 4. Dockerfile を眺める → 何も問題が見当たらない 5. 「もしかして、設定ファイルの問題?」 6. 昔の知識を思い出す → 「あ、スクリプトが…」

犯人を見つけるまで:

config/mvs.fixed というファイルを発見。中身を見ると:

#!/bin/bash
# ...いろいろ...
exec ./mvs  # ← これだ!

「あああああああ」

このスクリプトが自身を呼び出すたびに無限ループが発生していました。

解決策:

  1. config/mvs.fixed を削除するか、オーバーライドをやめる
  2. Dockerfile を修正して、直接 Hercules バイナリを実行

修正後のDockerfile:

export LD_LIBRARY_PATH=/tk4-/hercules/linux/64/lib:$LD_LIBRARY_PATH
exec /tk4-/hercules/linux/64/bin/hercules -f /tk4-/conf/tk4-.cnf

当時の心情: 「あああ…もう二度と嫌や…」


課題2: アーキテクチャの地獄(本当の地獄はここから)

無限ループを修正して、再度 make build を実行。

するとエラーが出ます:

qemu-i386: Could not open '/lib/ld-linux.so.2': No such file or directory

「え、なにこれ?」

何が起きていたのか

  • Dockerfile の FROM ubuntu:22.04 は、実行環境のアーキテクチャ(ARM64)を指定していた
  • でも、ビルド内で x86_64 バイナリを使おうとしている
  • そのため、32ビット・64ビットの x86_64 ライブラリが見つからない

試してみたこと(その1):ライブラリをインストール

# Dockerfile に追加してみた
RUN apt-get update && apt-get install -y libc6-i386 libstdc++6:i386

結果:

E: Unable to locate package libc6-i386

当時の思考: 「え、なんで?」

その時点では、ARM64 Ubuntu にはそもそも x86_64 用の 32/64 ビットライブラリが存在しないことに気づいていませんでした。

試してみたこと(その2):GHCR のイメージを使う

公式リポジトリの pre-built image を使ってみようと思いました。

# docker-compose.yml
image: ghcr.io/skunklabz/tk4-hercules:latest

docker compose up -d を実行…

同じエラーが出ました。

この瞬間気づきました。

「これ、ベースイメージのアーキテクチャを指定する問題だ。」

真犯人

Dockerfile を見直します:

FROM ubuntu:22.04  # ← これがARM64指定になっていた!

Docker は、実行環境のアーキテクチャを自動選択します。Mac(ARM64)上では、自動的に ARM64 Ubuntu イメージを選ぶのです。

解決策:明示的にアーキテクチャを指定

FROM --platform=linux/amd64 ubuntu:22.04 AS builder
...
FROM --platform=linux/amd64 ubuntu:22.04

さらに、ビルド時も明示的に指定:

docker buildx build --platform linux/amd64 -t tk4-hercules:latest .

「docker build ではなく docker buildx か…」

その時点では、docker buildx の存在すら知りませんでした。調べて実行。

ビルド時間: 約2分。

結果:成功。

当時の心情: 「…終わった。やっと…」


課題3: c3270 ターミナルの謎のエラー

ようやく Hercules が起動しました。

次は、3270 ターミナルでログインを試みます。

c3270 localhost

エラー:

localhost, port 23: Connection refused

「え?ポート 23?」

その時点では、何が起きているのかわかりませんでした。

試してみたこと(その1):ポートが本当にリッスンしているか確認

netstat -an | grep 3270

出力:

tcp46      0      0  *.3270                 *.*                    LISTEN

ポート 3270 は確かにリッスンしている。では、なぜ connection refused?

試してみたこと(その2):Web コンソールにアクセス

curl http://localhost:8038

結果:成功。HTML が返ってきた。

「あ、Web は動くんだ。だったら c3270 の問題?」

真犯人(その1)

c3270 のマニュアルをよく読んでみると…

c3270 [options] [host[:port]]

ポート指定がないと、デフォルトでポート 23(Telnet)に接続する。

「あ…」

TK4-Hercules は、ポート 3270 でリッスンしています。それなのに、c3270 は勝手にポート 23 を選んでいた。

真犯人(その2)

なぜ Telnet(ポート 23)をデフォルトにしたのか?

歴史的には、System/370 エミュレータは本来、Telnet プロトコル を使うものだったからです。1980年代、3270 ターミナルはネットワーク経由で Telnet で接続していました。

でも、TK4-Hercules は Telnet じゃなくて、raw TCP の 3270 プロトコルでリッスンしているわけです。

解決策:ポート番号を明示的に指定

c3270 localhost:3270

これだけ。

当時の心情: 「…いや、これ、ドキュメントに書いてあったんじゃ…」(怒り)


課題4: Docker Daemon が起動していない(初期段階の問題)

実は、一番最初に遭遇した問題がこれでした:

Cannot connect to the Docker daemon at unix:///Users/username/.docker/run/docker.sock

解決策:

open /Applications/Docker.app

Docker Desktop が完全に起動するまで待つ。

これだけです。

当時の心情: 「あ、普通に Docker 起動してなかった…」


ようやく成功

課題1: コンテナの無限ループ

症状: コンテナが起動すると、ログが無限に繰り返されます:

=== TK4- MVS Startup ===
=== TK4- MVS Startup ===
=== TK4- MVS Startup ===
...(永遠に続く)

原因: プロジェクトの config/mvs.fixed スクリプトが、自身を再帰的に呼び出していました:

# config/mvs.fixed(問題のあるコード)
exec ./mvs  # 自身を呼び出す → 無限ループ!

解決方法: 1. config/mvs.fixed を削除またはオーバーライドをやめる 2. TK4-の元々の mvs スクリプトを使用 3. 最終的には、Dockerfileで直接Herculesバイナリを実行するように修正

修正後のDockerfile抜粋:

export LD_LIBRARY_PATH=/tk4-/hercules/linux/64/lib:$LD_LIBRARY_PATH
exec /tk4-/hercules/linux/64/bin/hercules -f /tk4-/conf/tk4-.cnf

Learning Point: スタートアップスクリプトは必ずテストしましょう。特に再帰呼び出しには注意。


課題2: アーキテクチャの不一致エラー

症状: 以下のようなエラーが表示されます:

qemu-i386: Could not open '/lib/ld-linux.so.2': No such file or directory

または:

rosetta error: failed to open elf at /lib64/ld-linux-x86-64.so.2

根本原因: – ARM64ベースのUbuntuイメージ上で、x86_64バイナリを実行しようとした – ARM64環境では、x86_64用の32ビット/64ビットライブラリが利用できない

失敗した試み:

ARM64イメージ上で依存ライブラリをインストールしようとしました:

# ❌ 失敗
apt-get install libc6-i386 libstdc++6:i386
# エラー: パッケージが ARM64 Ubuntu にない

この失敗から学んだこと:環境が異なると、パッケージの利用可能性も異なるということです。

解決方法 ✅:

Dockerfileの FROM ステートメントで明示的にプラットフォームを指定します:

# ✅ 正しい方法
FROM --platform=linux/amd64 ubuntu:22.04 AS builder
...
FROM --platform=linux/amd64 ubuntu:22.04

そして、ビルド時にも明示的にプラットフォームを指定:

docker buildx build --platform linux/amd64 -t tk4-hercules:latest .

Why docker buildx? – docker build: ホストのアーキテクチャ用のイメージのみ構築 – docker buildx build: クロスプラットフォーム対応のビルダーを使用

Learning Point: クロスプラットフォーム開発では、コンテナベースイメージのアーキテクチャ と ビルダーのプラットフォーム指定 の両方が重要です。


課題3: c3270 ターミナルエミュレータの接続エラー

症状: c3270でTK4-Herculesに接続しようとすると、接続拒否エラーが出ます:

$ c3270 localhost
localhost, port 23: Connection refused

なぜこんなことが起こるのか?

c3270はポート指定なしの場合、デフォルトでポート23(Telnetプロトコル) に接続しようとします。しかし、TK4-Herculesはポート3270 でリッスンしています。

イメージ:

ユーザー入力: c3270 localhost
          ↓
c3270の動作: localhost:23 に接続しようとする ← ❌ ここが間違っている
TK4-Hercules: ポート 3270 でリッスン中
          ↓
接続拒否エラー

検証:

ポートが本当にリッスンしているか確認:

netstat -an | grep 3270

出力:

tcp46      0      0  *.3270                 *.*                    LISTEN

✅ ポート3270は確かにリッスン中です。

解決方法 ✅:

ポート番号を明示的に指定:

# ✅ 成功
c3270 localhost:3270

これだけです!

Learning Point: デフォルト値が常に正しいとは限りません。特にネットワーク通信では、明示的にポート番号を指定することが重要です。


課題4: Docker Daemon の接続エラー(初期段階)

症状:

Cannot connect to the Docker daemon at unix:///Users/username/.docker/run/docker.sock

原因: Docker Desktop が起動していない

解決方法:

open /Applications/Docker.app

Docker Desktop が完全に起動するまで待ちます(メニューバーにDockerアイコンが表示される)

c3270 localhost:3270

実行するとターミナルが表示されます。

Enter キーを 2 回押す…

ログイン画面が表示されます。

HHCPF003I LOGON REQUIRED

HERC01 USERID ========> [        ]
                        [PASSWORD]
                        [        ]

LOGON COMPLETE

ここに入力:

ユーザー名: HERC01
パスワード: CUL8TR

当時の心情: 「…あああ、やった。やっと動いた。」


何を学んだのか

丸一日をかけた試行錯誤から得た教訓:

1. ドキュメントをちゃんと読め

c3270 --help を見れば、ポート指定方法は書いてあった。docker buildx --help を見れば、クロスプラットフォーム対応について書いてある。

でも、実際には、エラーが出てからドキュメントを読みました。

2. デフォルト値は信頼するな

  • c3270 はデフォルトでポート 23 を選ぶ
  • Docker は実行環境のアーキテクチャを自動選択する
  • スクリプトは silent に失敗することがある

デフォルトの背後にある歴史と意図を理解することが重要です。

3. エラーメッセージはあなたの友

「Connection refused」というシンプルなエラーメッセージから、ポート番号の問題を特定できました。エラーメッセージは、問題への手がかりです。

4. 試行錯誤は無駄ではない

正解を教えてもらうのと、自分で試行錯誤するのでは、頭に残るレベルが全く違います。

昔メインフレームを使っていた自分でも、Apple Silicon と Docker の組み合わせは新しい領域。知識がない中での試行錯誤が、一番の学習になりました。

5. 懐かしさって、すごい

この作業中、何度も昔の記憶が蘇りました。

JCL のあの独特の文法、3270 ターミナルのあの画面、COBOL のあの冗長性…

43年前のシステムが、今も動いているし、今も学ぶ価値がある。そして、当時のエンジニアたちが設計した思想や制約が、今なお影響を与えているんだなと。


最後に:なぜこんなことを…

結局、何時間も費やして得たものは何か?

  • Apple Silicon Mac での Docker クロスプラットフォーム構築の知見
  • 3270 ターミナルエミュレータの使い方
  • 1981年のメインフレームが動く環境

そして、何より:

昔触ってた世界が、まだ息づいてるんだな。という実感。

クラウドネイティブ、マイクロサービス、Kubernetes…確かに新しい技術は素晴らしい。でも、世界の金融システムの多くが、いまだに 1981 年のメインフレーム上で動いている。

その事実と、その世界を学ぶ価値を、改めて認識させてくれたプロジェクトでした。


参考:最終的なコマンド集

すべてがうまくいったときのコマンド:

# 1. Rosetta 2 インストール
softwareupdate --install-rosetta

# 2. クローン
git clone https://github.com/skunklabz/tk4-hercules.git
cd tk4-hercules

# 3. ビルド(ここで --platform を指定)
docker buildx build --platform linux/amd64 -t tk4-hercules:latest .

# 4. 起動
docker compose up -d

# 5. ログ確認
docker compose logs -f

# 6. 接続
c3270 localhost:3270

# 7. または Web コンソール
open http://localhost:8038

謝辞

このプロジェクトと資料を提供してくださった TK4-Hercules のメンテナーの皆様に感謝申し上げます。そして、Google なしに試行錯誤をさせてくれた環境に感謝。


続編に向けて

本記事では、TK4-Hercules を Apple Silicon Mac にセットアップするまでのプロセスを記録しました。

しかし、ここからが本番です。

次の記事では:

  • 実際にメインフレームにログインして、何ができるのか
  • JCL(Job Control Language)の基礎と実践
  • TSO(Time Sharing Option)の使い方
  • 簡単なバッチジョブを実行してみる
  • 昔と今のメインフレーム開発の違い

などをお届けする予定です。

43 年前のシステムが今も動いている。その上で、自分たちは何を学べるのか。

続きは、乞うご期待。



ギャップロを運営しているアップフロンティア株式会社では、一緒に働いてくれる仲間を随時、募集しています。 興味がある!一緒に働いてみたい!という方は下記よりご応募お待ちしております。
採用情報をみる