docker 将测试容器中的Spring-Boot应用程序连接到Postgres DB

5t7ly7z5  于 2023-03-01  发布在  Docker
关注(0)|答案(1)|浏览(124)

目前我正在测试MyService,它与AccountService有依赖关系,因此我使用@Testcontainers

我面临的问题是AccountService无法连接到我的mac上的数据库,我不知道为什么,因为数据库是可用的,我可以手动连接到它。我试图连接MyService(不是在一个容器中,从IntelliJ)到数据库,它工作正常。
我假设AccountService的Docker容器上的配置问题是由于以下错误造成的:(参见下面的堆栈跟踪)
Connection refused: localhost/127.0.0.1:52801
希望你能帮我解决这个问题。

我的测试代码

@Testcontainers
    @SpringBootTest
    @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
    @AutoConfigureWebTestClient
    @EnableAutoConfiguration
    class MyServiceIntegrationTest {
    
        private static final String ACCOUNT_SERVICE = "account-service:0.0.1";
        private static final int ACCOUNT_SERVICE_INTERNAL_PORT = 8099;
        private static final String ACCOUNT_SERVICE_DATABASE_NAME = "account-db";
        private static final String DATABASE_USERNAME = "admin";
        private static final String DATABASE_PASSWORD = "password";
    
        @Container
        public static PostgreSQLContainer<?> accountServiceDb = new PostgreSQLContainer<>("postgres:latest")
                .withDatabaseName(ACCOUNT_SERVICE_DATABASE_NAME)
                .withUsername(DATABASE_USERNAME)
                .withPassword(DATABASE_PASSWORD);
        static GenericContainer<?> accountServiceContainer;
  
        @BeforeAll
        static void setup() {
        try (final Network network = Network.newNetwork()) {
            final var accountServiceEnv = Map.of(
                    "R2DBC_URL", "r2dbc:postgresql://"
                            + accountServiceDb.getHost() + ":"
                            + accountServiceDb.getFirstMappedPort()
                            + "/"
                            + accountServiceDb.getDatabaseName(),
                    "DB_USERNAME", DATABASE_USERNAME,
                    "DB_PASSWORD", DATABASE_PASSWORD
            );
    
            accountServiceContainer = new GenericContainer<>(DockerImageName.parse(ACCOUNT_SERVICE))
                    .withNetwork(network)
                    .withNetworkAliases(ACCOUNT_SERVICE)
                    .withEnv(accountServiceEnv)
                    .withExposedPorts(ACCOUNT_SERVICE_INTERNAL_PORT);
               
            accountServiceDb.withNetwork(network);
            accountServiceContainer.start();
        }
    }
        
        @Test
        void intTest(){
            // todo
        }
    }

来自帐户服务的堆栈跟踪

2023-02-22 09:16:27 2023-02-22 09:16:27.503  INFO 1 --- [           main] c.c.b.Account.AccountServiceApplication  : Starting AccountServiceApplication using Java 17.0.5 on 358da35fc9e0 with PID 1 (/service.jar started by root in /)
2023-02-22 09:16:27 2023-02-22 09:16:27.517  INFO 1 --- [           main] c.c.b.Account.AccountServiceApplication  : No active profile set, falling back to 1 default profile: "default"
2023-02-22 09:16:30 2023-02-22 09:16:30.833  INFO 1 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data R2DBC repositories in DEFAULT mode.
2023-02-22 09:16:30 2023-02-22 09:16:30.885  INFO 1 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 33 ms. Found 0 R2DBC repository interfaces.
2023-02-22 09:16:31 2023-02-22 09:16:31.567  INFO 1 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data R2DBC repositories in DEFAULT mode.
2023-02-22 09:16:32 2023-02-22 09:16:32.436  INFO 1 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 868 ms. Found 2 R2DBC repository interfaces.
2023-02-22 09:16:38 2023-02-22 09:16:38.398 ERROR 1 --- [tor-tcp-epoll-1] c.c.b.s.services.AccountBackendService   : Error by DB creation
2023-02-22 09:16:38 
2023-02-22 09:16:38 io.r2dbc.postgresql.PostgresqlConnectionFactory$PostgresConnectionException: Cannot connect to localhost/<unresolved>:52801
2023-02-22 09:16:38     at io.r2dbc.postgresql.PostgresqlConnectionFactory.cannotConnect(PostgresqlConnectionFactory.java:218) ~[r2dbc-postgresql-0.8.13.RELEASE.jar!/:0.8.13.RELEASE]
2023-02-22 09:16:38     at reactor.core.publisher.Mono.lambda$onErrorMap$31(Mono.java:3811) ~[reactor-core-3.4.26.jar!/:3.4.26]
2023-02-22 09:16:38     at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:94) ~[reactor-core-3.4.26.jar!/:3.4.26]
2023-02-22 09:16:38     at 
SHORTENED
io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.87.Final.jar!/:4.1.87.Final]
2023-02-22 09:16:38     at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
2023-02-22 09:16:38 Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException: finishConnect(..) failed: Connection refused: localhost/127.0.0.1:52801
2023-02-22 09:16:38 Caused by: java.net.ConnectException: finishConnect(..) failed: Connection refused
2023-02-22 09:16:38     at io.netty.channel.unix.Errors.newConnectException0(Errors.java:155) ~[netty-transport-native-unix-common-4.1.87.Final.jar!/:4.1.87.Final]
2023-02-22 09:16:38     at io.netty.channel.unix.Errors.handleConnectErrno(Errors.java:128) ~[netty-transport-native-unix-common-4.1.87.Final.jar!/:4.1.87.Final]
2023-02-22 09:16:38     at io.netty.channel.unix.Socket.finishConnect(Socket.java:359) ~[netty-transport-native-unix-common-4.1.87.Final.jar!/:4.1.87.Final]
2023-02-22 09:16:38     at io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.doFinishConnect(AbstractEpollChannel.java:710) ~[netty-transport-classes-epoll-4.1.87.Final.jar!/:4.1.87.Final]
2023-02-22 09:16:38     at io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.finishConnect(AbstractEpollChannel.java:687) ~[netty-transport-classes-epoll-4.1.87.Final.jar!/:4.1.87.Final]
2023-02-22 09:16:38     at io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.epollOutReady(AbstractEpollChannel.java:567) ~[netty-transport-classes-epoll-4.1.87.Final.jar!/:4.1.87.Final]
2023-02-22 09:16:38     at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:489) ~[netty-transport-classes-epoll-4.1.87.Final.jar!/:4.1.87.Final]
2023-02-22 09:16:38     at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:397) ~[netty-transport-classes-epoll-4.1.87.Final.jar!/:4.1.87.Final]
2023-02-22 09:16:38     at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.87.Final.jar!/:4.1.87.Final]
2023-02-22 09:16:38     at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.87.Final.jar!/:4.1.87.Final]
2023-02-22 09:16:38     at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.87.Final.jar!/:4.1.87.Final]
2023-02-22 09:16:38     at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
2023-02-22 09:16:38 
2023-02-22 09:16:38 2023-02-22 09:16:38.416 ERROR 1 --- [tor-tcp-epoll-1] reactor.core.publisher.Operators         : Operator called default onErrorDropped

帐户服务的停靠文件

FROM secret/copenjdk17:17

EXPOSE 8080
EXPOSE 9090
# JMX port:
EXPOSE 9998
# Java Debug port:
EXPOSE 5004

COPY /build/libs/account-service-0.0.1.jar service.jar

STOPSIGNAL SIGINT

提前感谢!

lf5gs5x2

lf5gs5x21#

您的代码中存在以下几个问题:

  • 您需要将两个容器都连接到网络
  • 容器可以通过网络别名(此网络上的DNS名称)通过此网络进行访问,因此在从服务连接到此数据库时,应使用postgres容器别名作为主机
  • 您应该通过5432端口而不是主机上的Map端口访问postgres数据库,因为它们通过网络进行通信。

如果你想从localhost连接,你会使用Map端口检查下面的代码和注解,应该会给你指出正确的方向:

@Testcontainers
@SpringBootTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@AutoConfigureWebTestClient
@EnableAutoConfiguration
class MyServiceIntegrationTest {

    private static final String ACCOUNT_SERVICE = "account-service:0.0.1";
    private static final int ACCOUNT_SERVICE_INTERNAL_PORT = 8099;
    private static final String ACCOUNT_SERVICE_DATABASE_NAME = "account-db";
    private static final String DATABASE_USERNAME = "admin";
    private static final String DATABASE_PASSWORD = "password";
    //create network
    private static final Network network = Network.newNetwork();

    private static final String ACCOUNT_SERVICE_DB = "account-service-db";
    
    @Container
    public static PostgreSQLContainer<?> accountServiceDb = new PostgreSQLContainer<>("postgres:latest")
            .withDatabaseName(ACCOUNT_SERVICE_DATABASE_NAME)
            .withUsername(DATABASE_USERNAME)
            .withPassword(DATABASE_PASSWORD)
            //connect postgres db to network
            .withNetwork(network)
            //give the postgres DNS name
            .withNetworkAliases(ACCOUNT_SERVICE_DB);
    static GenericContainer<?> accountServiceContainer;

    @BeforeAll
    static void setup() {
        final Network network = Network.newNetwork();
        final var accountServiceEnv = Map.of(
                "R2DBC_URL", "r2dbc:postgresql://"
                        //use db container DNS alias as host over common network
                        + ACCOUNT_SERVICE_DB + ":"
                        //here we use default postgres exposed port and not host port
                        + "5432"
                        + "/"
                        + accountServiceDb.getDatabaseName(),
                "DB_USERNAME", DATABASE_USERNAME,
                "DB_PASSWORD", DATABASE_PASSWORD
        );

        accountServiceContainer = new GenericContainer<>(DockerImageName.parse(ACCOUNT_SERVICE))
                .withNetwork(network)
                .withNetworkAliases(ACCOUNT_SERVICE)
                .withEnv(accountServiceEnv)
                .withExposedPorts(ACCOUNT_SERVICE_INTERNAL_PORT);

        accountServiceDb.withNetwork(network);
        accountServiceContainer.start();
    }

    @Test
    void intTest() {
        // todo
    }

相关问题