Writing a Dev Service
前提条件
-
すでに エクステンション構造 が準備されている。
-
外部サービスのコンテナー化されたバージョンがある (すべての Dev Service がコンテナーに依存しているわけではありませんが、ほとんどは依存しています)。
Dev Service の作成
エクステンションが外部サービスに接続するための API を提供する場合は、Dev Service 実装を提供することを推奨します。
Dev Service を作成するには、 DevServicesResultBuildItem を返す新しいビルドステップをエクステンションプロセッサークラスに追加します。
ここでは、 hello-world イメージが使用されていますが、サービスに適切なイメージをセットアップする必要があります。
@BuildStep(onlyIfNot = IsNormal.class, onlyIf = GlobalDevServicesConfig.Enabled.class)
public DevServicesResultBuildItem createContainer() {
DockerImageName dockerImageName = DockerImageName.parse("hello-world");
GenericContainer container = new GenericContainer<>(dockerImageName)
.withExposedPorts(SERVICE_PORT, OTHER_SERVICE_PORT)
.waitingFor(Wait.forLogMessage(".*" + "Started" + ".*", 1))
.withReuse(true);
container.start();
String newUrl = "http://" + container.getHost() + ":" + container.getMappedPort(SERVICE_PORT);
Map<String, String> configOverrides = Map.of("some-service.base-url", newUrl);
return new DevServicesResultBuildItem.RunningDevService(FEATURE, container.getContainerId(),
container::close, configOverrides)
.toBuildItem();
}
このコードを使用すると、エクステンションをテストアプリケーションに追加して quarkus dev を実行すると、コンテナーの起動を確認できるはずです。
ただし、ポートが公開されていないため、アプリケーションは接続できません。ポートを公開するには、コンテナー構造に withExposedPorts を追加します。
以下に例を示します。
GenericContainer container = new GenericContainer<>(dockerImageName)
.withExposedPorts(SERVICE_PORT, OTHER_SERVICE_PORT);
Testcontainers は、これらのポートをホスト上のランダムなポートにマッピングします。これによりポートの競合は回避されますが、アプリケーションはコンテナー内のサービスにどのように接続するのか、という新たな問題が発生します。
アプリケーションが接続できるようにするには、エクステンションはマッピングされたポートを使用してサービスのデフォルト設定をオーバーライドする必要があります。 これはコンテナーを起動した後に実行する必要があります。 以下に例を示します。
container.start();
Map<String, String> configOverrides = Map.of("some-service.base-url",
"http://" + container.getHost() + ":" + container.getMappedPort(SERVICE_PORT));
他の設定のオーバーライドも同じマップに含めることができます。
コンテナーの起動を待機する
コンテナーが起動するまで待つには、コンテナー構築に .waitingFor 呼び出しを追加する必要があります。以下に例を示します。
.waitingFor(Wait.forLogMessage(".*" + "Started" + ".*", 1))
別のオプションとして、ポートが開くのを待つことが挙げられます。待機ストラテジーの詳細は、Testcontainers のドキュメント を参照してください。
Dev Service の設定
Dev Service の起動プロセスを設定するには、ビルドステップのコンストラクターで ConfigPhase.BUILD_TIME 設定クラスを受け入れます。
以下に例を示します。
@BuildStep(onlyIfNot = IsNormal.class, onlyIf = GlobalDevServicesConfig.Enabled.class)
public DevServicesResultBuildItem createContainer(MyConfig config) {
たとえば、この設定を使用して固定ポートを設定したり、イメージ名を設定したりすることができます。
if (config.port.isPresent()) {
container.setPortBindings(List.of(config.port.get() + ":" + SERVICE_PORT));
}
再利用の制御
開発モードでは、ライブリロードにより、Quarkus が頻繁に再起動する場合があります。デフォルトでは、これによりテストコンテナーも再起動されます。 Quarkus の再起動は通常非常に高速ですが、コンテナーの再起動にはさらに長い時間がかかる場合があります。 コードを変更するたびにコンテナーが再起動するのを防ぐには、コンテナーを再利用可能としてマークします。
.withReuse(true)
一部の Dev Service は、プロセッサー自体のコンテナーの状態を追跡する高度な再利用ロジックを実装しています。 サービスに複雑な要件がある場合や、インスタンス間で共有する必要がある場合は、これが必要になることがあります。