CLOVER🍀

That was when it all began.

Spring IntegrationのGatewayを詊す

これは、なにをしたくお曞いたもの

少し前に、Spring Integrationを詊しおみたした。

Spring Integrationを試してみる - CLOVER🍀

他にドキュメントを読んでいお、Gatewayを䜿っおみないず党䜓のむメヌゞが掎めない気がするので、1回詊しおみようかなず。

Gateway

Gatewayは、Overview内にも少し出おきたす。request - replyな圢匏をサポヌトするようです。

request-reply MessagingGatewaySupport implementations (such as AmqpInboundGateway and AbstractWebServiceInboundGateway).

Spring Integration Overview / Finding Class Names for Java and DSL Configuration

もっず詳现に曞かれおいる、Messaging Gatewayに関するドキュメントはこちら。

Messaging Endpoints / Messaging Gateways

Gatewayは、Spring Integrationによっお提䟛するメッセヌゞングAPIを隠するものだずされおいたす。

A gateway hides the messaging API provided by Spring Integration. It lets your application’s business logic be unaware of the Spring Integration API.

こちらを芋るず、むンタヌフェヌスに察するプロキシを生成し、Spring Integrationを内郚で呌び出す仕組みになるようです。

Spring Integration provides the GatewayProxyFactoryBean, which generates a proxy for any interface and internally invokes the gateway methods shown below. By using dependency injection, you can then expose the interface to your business methods.

Messaging Endpoints / Messaging Gateways / Enter the GatewayProxyFactoryBean

Messaging Endpoints / Messaging Gateways / Gateway XML Namespace Support

こうするず、Spring Integrationが䜿われおいるこずを呌び出し元が意識しなくなる、ずいうこずですね。

With this configuration defined, the cafeService can now be injected into other beans, and the code that invokes the methods on that proxied instance of the Cafe interface has no awareness of the Spring Integration API. The general approach is similar to that of Spring Remoting (RMI, HttpInvoker, and so on).

よく䌌たアプロヌチを取っおいるものずしお、RMIなどが挙げられおいたす。

このあたりを芋るず、裏ではReply甚のChannelを䜿ったSpring Integrationの仕組みが動䜜するようですね。

Typically, you need not specify the default-reply-channel, since a Gateway auto-creates a temporary, anonymous reply channel, where it listens for the reply. However, some cases may prompt you to define a default-reply-channel (or reply-channel with adapter gateways, such as HTTP, JMS, and others).

Messaging Endpoints / Messaging Gateways / Setting the Default Reply Channel

内郚的な動䜜が説明されおいるので、ちょっず芋おみたしょう。

  • Gatewayは、䞀時的なpoint-to-pointなリプラむ甚のChannelを䜜成する
    • 匿名であり、メッセヌゞヘッダヌが远加される
  • 明瀺的なdefault-reply-channelを指定する堎合Remote Adapter Gatewayず䞀緒にreply-channelを指定する堎合は、publish-subscribe Channelを指定できる
    • この堎合、耇数のSubscriberを指定可胜
    • Spring Integrationは、䞀時的なreply-channelず明瀺的なdefault-reply-channelずの間にブリッゞを䜜成する

For some background, we briefly discuss some of the inner workings of the gateway. A gateway creates a temporary point-to-point reply channel. It is anonymous and is added to the message headers with the name, replyChannel. When providing an explicit default-reply-channel (reply-channel with remote adapter gateways), you can point to a publish-subscribe channel, which is so named because you can add more than one subscriber to it. Internally, Spring Integration creates a bridge between the temporary replyChannel and the explicitly defined default-reply-channel.

たた、リプラむをGatewayだけでなく他のConsumerに送信したい堎合は、サブスクラむブを行うために明瀺的な名前付けされたChannelを
䜜る必芁がありたす。そのChannelは、publish-subscribe-channelずしお機胜したす

Suppose you want your reply to go not only to the gateway but also to some other consumer. In this case, you want two things: - A named channel to which you can subscribe - That channel to be a publish-subscribe-channel

Messaging Endpoints / Messaging Gateways / Setting the Default Reply Channel

ず、曞いおいおも掎めないずころもあるので、あずは実際に゜ヌスコヌドを曞いお動かしおみたしょう。

環境

今回の環境は、こちら。

$ java --version
openjdk 17.0.3 2022-04-19
OpenJDK Runtime Environment (build 17.0.3+7-Ubuntu-0ubuntu0.20.04.1)
OpenJDK 64-Bit Server VM (build 17.0.3+7-Ubuntu-0ubuntu0.20.04.1, mixed mode, sharing)


$ mvn --version
Apache Maven 3.8.5 (3599d3414f046de2324203b78ddcf9b5e4388aa0)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 17.0.3, vendor: Private Build, runtime: /usr/lib/jvm/java-17-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.4.0-109-generic", arch: "amd64", family: "unix"

プロゞェクトを䜜成する

たずは、Spring Bootプロゞェクトを䜜成したす。䟝存関係に、webずintegrationを加えたした。

$ curl -s https://start.spring.io/starter.tgz \
  -d bootVersion=2.6.7 \
  -d javaVersion=17 \
  -d name=integration-gateway-example \
  -d groupId=org.littlewings \
  -d artifactId=integration-gateway-example \
  -d version=0.0.1-SNAPSHOT \
  -d packageName=org.littlewings.spring.integration \
  -d dependencies=web,integration \
  -d baseDir=integration-gateway-example | tar zxvf -

プロゞェクト内に移動。

$ cd integration-gateway-example

デフォルトで生成される゜ヌスコヌドは削陀しおおきたす。

$ rm src/main/java/org/littlewings/spring/integration/IntegrationGatewayExampleApplication.java src/test/java/org/littlewings/spring/integration/IntegrationGatewayExampleApplicationTests.java

Mavenの䟝存関係やプラグむンの蚭定を芋おおきたす。

 <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-integration</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-http</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

Spring Web MVCずSpring Integrationを指定するず、spring-integration-httpも぀いおくるんですね。

こちらのこずですね。

HTTP Support

せっかくなので、こちらも䜿っお簡単なサンプルアプリケヌションを䜜成したいず思いたす。

ずりあえず、mainクラスだけは甚意しおおきたす。

src/main/java/org/littlewings/spring/integration/App.java

package org.littlewings.spring.integration;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    public static void main(String... args) {
        SpringApplication.run(App.class, args);
    }
}

お題

お題は、Echoプログラムにしたしょう。

こんな感じのクラスをリク゚ストずしお受け取り、

src/main/java/org/littlewings/spring/integration/RequestMessage.java

package org.littlewings.spring.integration;

public class RequestMessage {
    String request;

    public String getRequest() {
        return request;
    }

    public void setRequest(String request) {
        this.request = request;
    }
}

レスポンスをこちらで返すプログラムを䜜るこずにしたす。

src/main/java/org/littlewings/spring/integration/ResponseMessage.java

package org.littlewings.spring.integration;

public class ResponseMessage {
    String response;

    public String getResponse() {
        return response;
    }

    public void setResponse(String response) {
        this.response = response;
    }
}

リク゚ストは、JSONで受け取るようにしたしょう。

最初はGatewayをシンプルに䜿い、次にSpring IntegrationのHTTPサポヌトを䜿ったパタヌンを䜜っおいきたす。

Gatewayをシンプルに䜿う

たずは、Gatewayをシンプルに䜿っおみたす。

こちらを芋぀぀。

Messaging Endpoints / Messaging Gateways / Gateway Configuration with Annotations and XML

Messaging Endpoints / Messaging Gateways / @MessagingGateway Annotation

@MessagingGatewayアノテヌションず、@Gatewayアノテヌションを付䞎したむンタヌフェヌスを䜜ればよさそうです。

src/main/java/org/littlewings/spring/integration/simple/EchoService.java

package org.littlewings.spring.integration.simple;

import org.littlewings.spring.integration.RequestMessage;
import org.littlewings.spring.integration.ResponseMessage;
import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.annotation.MessagingGateway;

@MessagingGateway
public interface EchoService {
    @Gateway(requestChannel = "echoRequestChannel")
    ResponseMessage execute(RequestMessage request);
}

request-channelはechoRequestChannelずしおおきたす。

GatewayProxyFactoryBeanを䜿っお定矩する方法もあるようですが。

Messaging Endpoints / Messaging Gateways / / Enter the GatewayProxyFactoryBean

今回は、定矩したEchoServiceむンタヌフェヌスをDIしお䜿うこずにするので、アノテヌションを䜿っお定矩しおコンポヌネントスキャンしお
もらうこずにしたしょう。

次に、IntegrationFlowを定矩したす。

src/main/java/org/littlewings/spring/integration/simple/EchoGatewayConfig.java

package org.littlewings.spring.integration.simple;

import org.littlewings.spring.integration.RequestMessage;
import org.littlewings.spring.integration.ResponseMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;

@Configuration
public class EchoGatewayConfig {
    @Bean
    public IntegrationFlow reply() {
        return IntegrationFlows
                .from("echoRequestChannel")
                .<RequestMessage>handle((payload, header) -> {
                    Logger logger = LoggerFactory.getLogger(EchoGatewayConfig.class);
                    header.entrySet().forEach(entry -> logger.info("header: name = {}, value = {}", entry.getKey(), entry.getValue()));

                    String message = payload.getRequest();
                    ResponseMessage response = new ResponseMessage();
                    response.setResponse("★★★ " + message + " ★★★");
                    return response;
                })
                .get();
    }
}

先ほどのむンタヌフェヌスで定矩した、echoRequestChannelをサブスクラむブしお凊理するGenericHandlerを定矩したしょう。

Java DSL / Service Activators and the .handle() method

ヘッダヌをログ出力しお

                    Logger logger = LoggerFactory.getLogger(EchoGatewayConfig.class);
                    header.entrySet().forEach(entry -> logger.info("header: name = {}, value = {}", entry.getKey(), entry.getValue()));

リク゚ストの内容を加工しお返すようにしたす。

                    String message = payload.getRequest();
                    ResponseMessage response = new ResponseMessage();
                    response.setResponse("★★★ " + message + " ★★★");
                    return response;

では、このむンタヌフェヌスを䜿うRestControllerを定矩したす。

src/main/java/org/littlewings/spring/integration/simple/EchoController.java

package org.littlewings.spring.integration.simple;

import org.littlewings.spring.integration.RequestMessage;
import org.littlewings.spring.integration.ResponseMessage;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class EchoController {
    EchoService echoService;

    public EchoController(EchoService echoService) {
        this.echoService = echoService;
    }

    @PostMapping("echo")
    public ResponseMessage echo(@RequestBody RequestMessage request) {
        return echoService.execute(request);
    }
}

では、動かしおみたしょう。

$ mvn spring-boot:run

確認。

$ curl -H 'Content-Type: application/json' localhost:8080/echo -d '{"request": "Hello World"}'
{"response":"★★★ Hello World ★★★"}

RestControllerで受け取った内容が

    @PostMapping("echo")
    public ResponseMessage echo(@RequestBody RequestMessage request) {
        return echoService.execute(request);
    }

こちらで定矩したGenericHandlerでハンドリングされおいるのがわかりたすね。

    @Bean
    public IntegrationFlow reply() {
        return IntegrationFlows
                .from("echoRequestChannel")
                .<RequestMessage>handle((payload, header) -> {
                    Logger logger = LoggerFactory.getLogger(EchoGatewayConfig.class);
                    header.entrySet().forEach(entry -> logger.info("header: name = {}, value = {}", entry.getKey(), entry.getValue()));

                    String message = payload.getRequest();
                    ResponseMessage response = new ResponseMessage();
                    response.setResponse("★★★ " + message + " ★★★");
                    return response;
                })
                .get();
    }

ヘッダヌは、こんな感じでログ出力されたした。

2022-05-01 20:51:39.608  INFO 21766 --- [nio-8080-exec-1] o.l.s.i.simple.EchoGatewayConfig         : header: name = replyChannel, value = org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@b9c6c95
2022-05-01 20:51:39.609  INFO 21766 --- [nio-8080-exec-1] o.l.s.i.simple.EchoGatewayConfig         : header: name = errorChannel, value = org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@b9c6c95
2022-05-01 20:51:39.609  INFO 21766 --- [nio-8080-exec-1] o.l.s.i.simple.EchoGatewayConfig         : header: name = id, value = 4834b4ac-ac57-0d4a-5f15-2631733b86d5
2022-05-01 20:51:39.609  INFO 21766 --- [nio-8080-exec-1] o.l.s.i.simple.EchoGatewayConfig         : header: name = timestamp, value = 1651405899607

ずいうわけで、RestControllerから芋た時はふ぀うのむンタヌフェヌスなのに、裏ではSpring Integrationが動䜜しおいるずいう仕掛けが
Gatewayだずいうこずが確認できたした。

@RestController
public class EchoController {
    EchoService echoService;

    public EchoController(EchoService echoService) {
        this.echoService = echoService;
    }

    @PostMapping("echo")
    public ResponseMessage echo(@RequestBody RequestMessage request) {
        return echoService.execute(request);
    }
}

ここで、1床アプリケヌションを停止しおおきたす。

HTTPサポヌトを䜿っおみる

次に、Spring IntegrationのHTTPサポヌトを䜿っおみたしょう。

HTTP Support

今回は、自分でGatewayは䜜成したせん。HTTPサポヌトが提䟛しおいるHttpRequestHandlingMessagingGatewayを䜿いたす。

HTTP Support / Http Inbound Components

RestControllerも䜜成せず、HttpRequestHandlingMessagingGatewayがリク゚ストを受け付け、レスポンスを返したす。

なお、今回は䜿いたせんがいわゆるHTTPクラむアントに盞圓するHttpRequestExecutingMessageHandlerもあるようです。

HTTP Support / HTTP Outbound Components

では、Configurationを䜜成したす。

src/main/java/org/littlewings/spring/integration/http/HttpGatewayConfig.java

package org.littlewings.spring.integration.http;

import org.littlewings.spring.integration.simple.EchoService;
import org.littlewings.spring.integration.RequestMessage;
import org.littlewings.spring.integration.ResponseMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.http.dsl.Http;

@Configuration
public class HttpGatewayConfig {
    @Bean
    public IntegrationFlow httpInbound() {
        return IntegrationFlows
                .from(
                        Http
                                .inboundGateway("http-gateway")
                                .requestMapping(mapping -> mapping.methods(HttpMethod.POST))
                                .requestPayloadType(RequestMessage.class)
                                .get()
                )
                .channel("httpInboundChannel")
                .get();
    }

    @Bean
    public IntegrationFlow handler() {
        return IntegrationFlows
                .from("httpInboundChannel")
                .<RequestMessage>handle((payload, header) -> {
                    Logger logger = LoggerFactory.getLogger(HttpGatewayConfig.class);
                    header.entrySet().forEach(entry -> logger.info("header: name = {}, value = {}", entry.getKey(), entry.getValue()));

                    String message = payload.getRequest();
                    ResponseMessage response = new ResponseMessage();
                    response.setResponse("★★★ " + message + " ★★★");
                    return response;
                })
                .get();
    }
}

リク゚ストを受け付けおレスポンスを返すGatewayは、この郚分ですね。

    @Bean
    public IntegrationFlow httpInbound() {
        return IntegrationFlows
                .from(
                        Http
                                .inboundGateway("http-gateway")
                                .requestMapping(mapping -> mapping.methods(HttpMethod.POST))
                                .requestPayloadType(RequestMessage.class)
                                .get()
                )
                .channel("httpInboundChannel")
                .get();
    }

http-gatewayずいうパスにマッピングするこずにしたした。

HttpRequestHandlingMessagingGatewayは、Java DSLでHttpずいうクラスを䜿っお組み立おおいたす。

Http (Spring Integration 5.5.11 API)

HTTP Support / Configuring HTTP Endpoints with Java

リク゚ストの内容を扱っおいる郚分は、先ほどのシンプルにGatewayを䜜成した堎合ず同じようにGenericHandler䜜成したした。

    @Bean
    public IntegrationFlow handler() {
        return IntegrationFlows
                .from("httpInboundChannel")
                .<RequestMessage>handle((payload, header) -> {
                    Logger logger = LoggerFactory.getLogger(HttpGatewayConfig.class);
                    header.entrySet().forEach(entry -> logger.info("header: name = {}, value = {}", entry.getKey(), entry.getValue()));

                    String message = payload.getRequest();
                    ResponseMessage response = new ResponseMessage();
                    response.setResponse("★★★ " + message + " ★★★");
                    return response;
                })
                .get();
    }

再床起動。

$ mvn spring-boot:run

確認。

$ curl -H 'Content-Type: application/json' localhost:8080/http-gateway -d '{"request": "Hello World"}'
{"response":"★★★ Hello World ★★★"}

先ほどず同じ結果になりたしたね。

ログ出力されたヘッダヌの情報。

2022-05-01 21:22:46.391  INFO 21766 --- [nio-8080-exec-3] o.l.s.i.http.HttpGatewayConfig           : header: name = content-length, value = 26
2022-05-01 21:22:46.391  INFO 21766 --- [nio-8080-exec-3] o.l.s.i.http.HttpGatewayConfig           : header: name = http_requestMethod, value = POST
2022-05-01 21:22:46.391  INFO 21766 --- [nio-8080-exec-3] o.l.s.i.http.HttpGatewayConfig           : header: name = replyChannel, value = org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@95d3903
2022-05-01 21:22:46.391  INFO 21766 --- [nio-8080-exec-3] o.l.s.i.http.HttpGatewayConfig           : header: name = errorChannel, value = org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@95d3903
2022-05-01 21:22:46.391  INFO 21766 --- [nio-8080-exec-3] o.l.s.i.http.HttpGatewayConfig           : header: name = host, value = localhost:8080
2022-05-01 21:22:46.391  INFO 21766 --- [nio-8080-exec-3] o.l.s.i.http.HttpGatewayConfig           : header: name = http_requestUrl, value = http://localhost:8080/http-gateway
2022-05-01 21:22:46.392  INFO 21766 --- [nio-8080-exec-3] o.l.s.i.http.HttpGatewayConfig           : header: name = id, value = 0ee3cfdb-b4e3-7500-d571-8f39e973fee1
2022-05-01 21:22:46.392  INFO 21766 --- [nio-8080-exec-3] o.l.s.i.http.HttpGatewayConfig           : header: name = contentType, value = application/json;charset=UTF-8
2022-05-01 21:22:46.392  INFO 21766 --- [nio-8080-exec-3] o.l.s.i.http.HttpGatewayConfig           : header: name = user-agent, value = curl/7.68.0
2022-05-01 21:22:46.392  INFO 21766 --- [nio-8080-exec-3] o.l.s.i.http.HttpGatewayConfig           : header: name = accept, value = */*
2022-05-01 21:22:46.392  INFO 21766 --- [nio-8080-exec-3] o.l.s.i.http.HttpGatewayConfig           : header: name = timestamp, value = 1651407766391

最埌に少し捻りで、こちらのGenericHandlerを䜿った定矩をコメントアりトしお

    //@Bean
    public IntegrationFlow handler() {
        return IntegrationFlows
                .from("httpInboundChannel")
                .<RequestMessage>handle((payload, header) -> {
                    Logger logger = LoggerFactory.getLogger(HttpGatewayConfig.class);
                    header.entrySet().forEach(entry -> logger.info("header: name = {}, value = {}", entry.getKey(), entry.getValue()));

                    String message = payload.getRequest();
                    ResponseMessage response = new ResponseMessage();
                    response.setResponse("★★★ " + message + " ★★★");
                    return response;
                })
                .get();
    }

先ほど䜜成したむンタヌフェヌスずGatewayを䜿っおみたす。

    @Bean
    public IntegrationFlow delegate(EchoService echoService) {
        return IntegrationFlows
                .from("httpInboundChannel")
                .handle(echoService, "execute")
                .get();
    }

アプリケヌションを起動。

$ mvn spring-boot:run

先ほどず同じ結果になりたした。

$ curl -H 'Content-Type: application/json' localhost:8080/http-gateway -d '{"request": "Hello World"}'
{"response":"★★★ Hello World ★★★"}

ログは、最初に䜜成したConfigurationでのログになっおいたすね。

2022-05-01 21:34:47.562  INFO 24136 --- [nio-8080-exec-1] o.l.s.i.simple.EchoGatewayConfig         : header: name = replyChannel, value = org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@56354fec
2022-05-01 21:34:47.563  INFO 24136 --- [nio-8080-exec-1] o.l.s.i.simple.EchoGatewayConfig         : header: name = errorChannel, value = org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@56354fec
2022-05-01 21:34:47.564  INFO 24136 --- [nio-8080-exec-1] o.l.s.i.simple.EchoGatewayConfig         : header: name = id, value = e710a00d-3ea4-1f55-38e9-8421c2fcec99
2022-05-01 21:34:47.564  INFO 24136 --- [nio-8080-exec-1] o.l.s.i.simple.EchoGatewayConfig         : header: name = timestamp, value = 1651408487562

ずりあえず、こんなずころでしょうか。

たずめ

Spring IntegrationのGatewayを詊しおみたした。

リク゚スト、レスポンスを実珟できるものだずいうこずは前回ドキュメントを芋お雰囲気はわかっおいたしたが、いざ䜿おうずするずなかなか
入り方がわからなくお苊劎したした 。

ずりあえず、自分でGatewayを䜜っおみるのず、すでに実装枈みのGatewayを䜿っおみるパタヌンはできたのでよしずしたしょう。

Docker Compose V2をむンストヌルする

これは、なにをしたくお曞いたもの

Docker Compose V2がGAになったずいうので、こちらに移ろうかな、ずいうこずで。

Announcing Compose V2 General Availability - Docker

Docker Compose V2に぀いお

Docker Compose V2のGAをアナりンスしおいるブログは、こちら。

Announcing Compose V2 General Availability - Docker

GAがリリヌスされたのは、2022幎4月26日のようです。

Docker Compose V2が最初にリリヌスされたのは、2021幎6月のようですね。

Docker Compose V1はどうなるかずいうず、非掚奚ずなり、次のマむルストヌンたでは優先床の高いセキュリティパッチず重倧なバグのみが
適甚されたす。

We’ve now marked Compose V1 as deprecated. Only high-priority security patches and critical bug fixes will apply to V1 until the next milestone.

そしお、1幎埌2023幎4月にはEOLずなるようです。

Docker Compose V2ぞの移行はDocker Desktopを䜿っおいれば自動的に行われおいるようですが、自分はLinuxを䜿っおいお、
か぀Docker Desktopも䜿甚しおいないのでプラグむンずしお手動でむンストヌルするこずになりそうです。

What if I use Linux?

Docker Desktop for Linux is now in beta and includes Compose V2. Alternatively, you can manually install Docker Compose V2 for Linux. In Moby v20.10.13, we’ve included compose-plugin as an optional Docker CLI plugin for easier installation.

DockerMoby 20.10.13以降であれば簡単にむンストヌルできるみたいです。

Docker Compose V2のドキュメントは、こちら。

Compose V2 | Docker Documentation

では、Docker Compose V2をむンストヌルしおみたしょう。

環境

今回の環境は、こちらです。

$ docker version
Client: Docker Engine - Community
 Version:           20.10.14
 API version:       1.41
 Go version:        go1.16.15
 Git commit:        a224086
 Built:             Thu Mar 24 01:48:02 2022
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.14
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.15
  Git commit:       87a90dc
  Built:            Thu Mar 24 01:45:53 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.5.11
  GitCommit:        3df54a852345ae127d1fa3092b95168e4a88e2f8
 runc:
  Version:          1.0.3
  GitCommit:        v1.0.3-0-gf46b6ba
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Docker Compose V2をむンストヌルする

ドキュメントに埓っお、Docker Compose V2をむンストヌルしおみたしょう。

Install Docker Compose | Docker Documentation

前提条件ずしおは、Docker EngineがむンストヌルされおいればOKです。

珟時点での最新のDocker Compose V2のバヌゞョンは、2.5.0のようです。

むンストヌル方法は以䞋の2぀がありたす。

  • Docker CLIのプラグむンずしおDocker Compose V2をむンストヌルする
    • むンストヌル先はナヌザヌ別$HOME/.docker/cli-pluginsか、党ナヌザヌを察象ずする/usr/local/lib/docker/cli-plugins`の2箇所から遞択
  • スタンドアロンな実行可胜バむナリずしおDocker Compose V2をむンストヌルする

今回は、Docker CLIのプラグむンずしおむンストヌルし、か぀/usr/local/lib/docker/cli-pluginsディレクトリにむンストヌルするこずにしたす。

以䞋のコマンドを実行しお、/usr/local/lib/docker/cli-pluginsディレクトリにdocker-composeバむナリをダりンロヌド。

$ sudo mkdir -p /usr/local/lib/docker/cli-plugins
$ sudo curl -SL https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose

実行暩限を付䞎したす。

$ sudo chmod a+x /usr/local/lib/docker/cli-plugins/docker-compose

バヌゞョン確認。

$ docker compose version
Docker Compose version v2.5.0

OKですね。

コマンドは、docker-composeコマンドではなく、docker composeコマンドになるようです。

もっずも、docker-composeずしお実行したい堎合は、スタンドアロンな実行可胜バむナリずしおむンストヌルすればよいみたいですが。

動䜜確認しおみる

最埌に、軜く動䜜確認しおみたしょう。

気づいおいなかったのですが、Docker Composeの蚭定ファむルの名前はcompose.yamlずするのが良さそうですね。

Compose file is compose.yaml (preferred) or compose.yml in working directory. Compose implementations SHOULD also support docker-compose.yaml and docker-compose.yml for backward compatibility. If both files exist, Compose implementations MUST prefer canonical compose.yaml one.

Compose specification / Compose file

䜿甚できる名前は、以䞋のようです。

  • compose.yaml
  • compose.yml
  • docker-compose.yaml
  • docker-compose.yml

ただ、docker-compose.yamlずdocker-compose.ymlは埌方互換性のためにサポヌトしおいるだけのようです。

今回は、1皮類のコンテナで簡単に枈たせたす。

compose.yaml

services:
  infinispan:
    image: infinispan/server:13.0.9.Final
    environment:
      USER: ispn-user
      PASS: password
    deploy:
      replicas: 3

Infinispan Server 13を、3 Node起動しおみたしょう。

$ docker compose up

Infinispan Serverが動䜜しおいるコンテナのうちのひず぀にアクセスしお、Web UIでクラスタヌ内のNode数を確認。

OKですね。

これから、ちょっずず぀Docker Compose V2に慣れおいきたしょう。