過去に コンテナー間のデータ通信に named pipe を使って実装 した。機能的には問題なく運用できていたが、環境構築時に named pipe の設定がわかりにくいという課題があった。また docker compose は volumes に設定したパスが存在しないときに歴史的経緯でディレクトリを作成してしまう。初期設定時に named pipe を期待するリソースがディレクトリになってしまっているところの、エラー制御のわかりにくさもあった。またこの運用はオンプレミスの環境でしか利用できず、将来的にクラウド対応 (k8s) で運用することを考慮すると、http 通信できる方がよいと考えを改め、データ通信の仕組みを再実装した。http サーバーと比べて named pipe の方が優れているのはセキュリティとして物理的にその OS 上からしかアクセスできないところ。

go でフレームワークを使わず、シンプルな http サーバーを実装してみた。セキュリティの制約さえなければ、このぐらいの手間を惜しんで named pipe を実装することもなかったかと、いまとなっての学びとなった。

func newMux(cfg config.MyConfig) *http.ServeMux {
	mux := http.NewServeMux()
	mux.HandleFunc("/version", handler.HandleVersion(cfg))
	return mux
}

func main() {
	ctx, stop := signal.NotifyContext(context.Background(),
		syscall.SIGINT,
		syscall.SIGTERM,
	)
	defer stop()

	cfg := config.MyConfig{}
	server := &http.Server{
		Addr:    ":7099",
		Handler: newMux(cfg),
	}
	go func() {
		if err := server.ListenAndServe(); err != http.ErrServerClosed {
			slog.Error("got an error providing http service", "err", err)
		}
		slog.Info("stopped http server normally")
	}()

	<-ctx.Done()
	slog.Info("caught the stop signal")
	ctxTimeout, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	if err := server.Shutdown(ctxTimeout); err != nil {
		slog.Error("failed to shutdown normally", "err", err)
		return
	}
	slog.Info("done graceful shutdown")
}