Java 测试容器 - 无法连接到暴露的端口
Java Testcontainers - Cannot connect to exposed port
我使用 javax.mail 实现了一个 POP3 服务器和客户端,只是为了尝试使用 Docker 进行集成测试。所以我基于 openjdk:8-jre 图像创建了两个 Docker 图像并将我的罐子复制到它们并启动它。根据我的配置(见下文),它正在工作。他们正在互相交谈。
但是由于想要进行多个集成测试,因此为每个测试构建一个映像并启动它们将会很乏味。我也不知道如何自动化结果。
但后来我偶然发现了 TestContainers,这似乎对实施这些测试有很大帮助。
所以我开始将这些测试移植到 TestContainers,使用我的 POP3 服务器映像作为 GenericContainer,并在 JUnit 测试方法中启动我的 POP3 客户端 类。我公开了我的 POP3 服务器正在侦听的端口 24999。但是当我尝试连接到服务器时,出现以下错误:
com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 32782; timeout -1;
nested exception is:
java.net.ConnectException: Connection refused
...
我可能在 TestContainers 中缺少某些设置。你能帮帮我吗
这是我使用的代码:
public class DockerPop3AutocryptKeyProvidingAndReceivingTest {
@Test
public void test() throws InterruptedException {
GenericContainer container = new GenericContainer<>("immerfroehlich/emailfilter:latest")
.withExposedPorts(24999);
container.start();
String host = container.getContainerIpAddress();
String port = container.getFirstMappedPort().toString();
//The following is simplified, but copied from the working jar used in the Docker Client image/container
MyPOP3Client client = new MyPOP3Client(host, port);
client.connect();
container.stop();
}
}
这就是我创建 Docker 图片的方式:
FROM openjdk:8-jre
ADD build/distributions/MyPOP3Server.tar . #This is where I have packed all the needed files to. It gets unpacked by Docker.
#EXPOSE 24999 #I tried both with and without this expose
WORKDIR /MyPOP3Server/bin
ENTRYPOINT ["sh","MyPOP3Server"] #Executes the shell script which runs java with my jar
这是服务器 Jar 中 运行 代码的简化版本:
MyPOP3Server server = new MyPOP3Server();
server.listenToPort(24999);
请告诉我我错过了什么。这里有什么问题?
谢谢和亲切的问候。
由于您的邮件服务器和客户端在容器中运行,我认为您应该连接到端口 24999 而不是映射端口
尝试 container.getMappedPort(24999)
而不是 getFirstMappedPort
。可能您的 docker 图像暴露了几个端口。
尝试添加一个 http 检查。
new GenericContainer<>("immerfroehlich/emailfilter:latest")
.withExposedPorts(24999)
.waitingFor(new HttpWaitStrategy().forPort(24999)
.withStartupTimeout(Duration.ofMinutes(5)));
有可能您的容器已启动,但您在服务器初始化之前尝试连接。
此外,注册一个日志附加程序以查看容器内的服务器发生了什么。
.withLogConsumer(new Slf4jLogConsumer(LoggerFactory.getLogger(
DockerPop3AutocryptKeyProvidingAndReceivingTest.class)))
其他答案中有一些很好的建议;我将用其他一些技巧来补充这些:
如前所述:
绝对要添加 LogConsumer
以便您可以看到容器的日志输出 - 也许有用的东西会出现在那里,现在或将来。拥有总是好的。
在容器启动后设置一个断点,就在您启动客户端之前。
此外,我希望以下内容有所作为。在断点处暂停时:
- 运行
docker ps -a
在终端
- 首先,检查您的容器是否 运行ning 并且没有退出。如果它已经退出,请从终端查看容器的日志。
- 其次,检查
docker ps
输出中的端口映射。您应该会看到类似 0.0.0.0:32768->24999/tcp
的内容(不过第一个端口号是随机的)。
- 在您的 IDE 中评估
container.getFirstMappedPort()
并检查您返回的端口号是否与随机公开的端口号相同。除非您在本地计算机上安装了非常不寻常的 Docker,否则应该可以通过 localhost:
+ 此端口访问此容器。
- 如果你已经走到这一步,那么很可能是容器或客户端代码出了问题。您可以尝试将不同的客户端连接到 运行ning 容器 - 如果您手边没有另一个 POP3 客户端,甚至
nc
之类的东西也会有所帮助。
另一件事是手动 运行 容器,只是为了减少发生的间接访问量。您提供的 Testcontainers 代码片段相当于:
docker run -p 24999 immerfroehlich/emailfilter:latest
您可能会发现这可以帮助您将问题 space 分成更小的部分。
感谢您的帮助。这使我找到了解决方案。它是缺少 WaitStrategy 和端口映射问题的结合。
这是我所做的:
1) 在 MyPop3Server.listenToPort(String port) 方法中我添加了一个 System.out.println:
public class MyPop3Server {
public void listenToPort(String port) {
//simplified: do initialization and listenToPort
System.out.println("Awaiting Connection...");
}
}
在我的测试中,我添加了一个监听 "Awaiting Connection"
的 LogMessageWaitStrategy
GenericContainer container = new GenericContainer<>("immerfroehlich/emailfilter:latest")
.waitingFor(Wait.forLogMessage("Awaiting Connection.*", 1))
.withExposedPorts(24999);
2) 我从 container.getFirstMappedPort() 切换到
container.getMappedPort(24999);
这里是整个更改后的工作测试代码:
public class DockerPop3AutocryptKeyProvidingAndReceivingTest {
@Test
public void test() throws InterruptedException {
GenericContainer container = new GenericContainer<>("immerfroehlich/emailfilter:latest")
.waitingFor(Wait.forLogMessage("Awaiting Connection.*", 1))
.withExposedPorts(24999);
container.start();
String host = container.getContainerIpAddress();
String port = container.getMappedPort(24999).toString();
//The following is simplified, but copied from the working jar used in the Docker Client image/container
MyPOP3Client client = new MyPOP3Client(host, port);
client.connect();
container.stop();
}
}
谢谢大家
我使用 javax.mail 实现了一个 POP3 服务器和客户端,只是为了尝试使用 Docker 进行集成测试。所以我基于 openjdk:8-jre 图像创建了两个 Docker 图像并将我的罐子复制到它们并启动它。根据我的配置(见下文),它正在工作。他们正在互相交谈。
但是由于想要进行多个集成测试,因此为每个测试构建一个映像并启动它们将会很乏味。我也不知道如何自动化结果。 但后来我偶然发现了 TestContainers,这似乎对实施这些测试有很大帮助。
所以我开始将这些测试移植到 TestContainers,使用我的 POP3 服务器映像作为 GenericContainer,并在 JUnit 测试方法中启动我的 POP3 客户端 类。我公开了我的 POP3 服务器正在侦听的端口 24999。但是当我尝试连接到服务器时,出现以下错误:
com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 32782; timeout -1;
nested exception is:
java.net.ConnectException: Connection refused
...
我可能在 TestContainers 中缺少某些设置。你能帮帮我吗
这是我使用的代码:
public class DockerPop3AutocryptKeyProvidingAndReceivingTest {
@Test
public void test() throws InterruptedException {
GenericContainer container = new GenericContainer<>("immerfroehlich/emailfilter:latest")
.withExposedPorts(24999);
container.start();
String host = container.getContainerIpAddress();
String port = container.getFirstMappedPort().toString();
//The following is simplified, but copied from the working jar used in the Docker Client image/container
MyPOP3Client client = new MyPOP3Client(host, port);
client.connect();
container.stop();
}
}
这就是我创建 Docker 图片的方式:
FROM openjdk:8-jre
ADD build/distributions/MyPOP3Server.tar . #This is where I have packed all the needed files to. It gets unpacked by Docker.
#EXPOSE 24999 #I tried both with and without this expose
WORKDIR /MyPOP3Server/bin
ENTRYPOINT ["sh","MyPOP3Server"] #Executes the shell script which runs java with my jar
这是服务器 Jar 中 运行 代码的简化版本:
MyPOP3Server server = new MyPOP3Server();
server.listenToPort(24999);
请告诉我我错过了什么。这里有什么问题?
谢谢和亲切的问候。
由于您的邮件服务器和客户端在容器中运行,我认为您应该连接到端口 24999 而不是映射端口
尝试 container.getMappedPort(24999)
而不是 getFirstMappedPort
。可能您的 docker 图像暴露了几个端口。
尝试添加一个 http 检查。
new GenericContainer<>("immerfroehlich/emailfilter:latest")
.withExposedPorts(24999)
.waitingFor(new HttpWaitStrategy().forPort(24999)
.withStartupTimeout(Duration.ofMinutes(5)));
有可能您的容器已启动,但您在服务器初始化之前尝试连接。
此外,注册一个日志附加程序以查看容器内的服务器发生了什么。
.withLogConsumer(new Slf4jLogConsumer(LoggerFactory.getLogger(
DockerPop3AutocryptKeyProvidingAndReceivingTest.class)))
其他答案中有一些很好的建议;我将用其他一些技巧来补充这些:
如前所述:
绝对要添加
LogConsumer
以便您可以看到容器的日志输出 - 也许有用的东西会出现在那里,现在或将来。拥有总是好的。在容器启动后设置一个断点,就在您启动客户端之前。
此外,我希望以下内容有所作为。在断点处暂停时:
- 运行
docker ps -a
在终端 - 首先,检查您的容器是否 运行ning 并且没有退出。如果它已经退出,请从终端查看容器的日志。
- 其次,检查
docker ps
输出中的端口映射。您应该会看到类似0.0.0.0:32768->24999/tcp
的内容(不过第一个端口号是随机的)。 - 在您的 IDE 中评估
container.getFirstMappedPort()
并检查您返回的端口号是否与随机公开的端口号相同。除非您在本地计算机上安装了非常不寻常的 Docker,否则应该可以通过localhost:
+ 此端口访问此容器。 - 如果你已经走到这一步,那么很可能是容器或客户端代码出了问题。您可以尝试将不同的客户端连接到 运行ning 容器 - 如果您手边没有另一个 POP3 客户端,甚至
nc
之类的东西也会有所帮助。
另一件事是手动 运行 容器,只是为了减少发生的间接访问量。您提供的 Testcontainers 代码片段相当于:
docker run -p 24999 immerfroehlich/emailfilter:latest
您可能会发现这可以帮助您将问题 space 分成更小的部分。
感谢您的帮助。这使我找到了解决方案。它是缺少 WaitStrategy 和端口映射问题的结合。
这是我所做的: 1) 在 MyPop3Server.listenToPort(String port) 方法中我添加了一个 System.out.println:
public class MyPop3Server {
public void listenToPort(String port) {
//simplified: do initialization and listenToPort
System.out.println("Awaiting Connection...");
}
}
在我的测试中,我添加了一个监听 "Awaiting Connection"
的 LogMessageWaitStrategyGenericContainer container = new GenericContainer<>("immerfroehlich/emailfilter:latest")
.waitingFor(Wait.forLogMessage("Awaiting Connection.*", 1))
.withExposedPorts(24999);
2) 我从 container.getFirstMappedPort() 切换到
container.getMappedPort(24999);
这里是整个更改后的工作测试代码:
public class DockerPop3AutocryptKeyProvidingAndReceivingTest {
@Test
public void test() throws InterruptedException {
GenericContainer container = new GenericContainer<>("immerfroehlich/emailfilter:latest")
.waitingFor(Wait.forLogMessage("Awaiting Connection.*", 1))
.withExposedPorts(24999);
container.start();
String host = container.getContainerIpAddress();
String port = container.getMappedPort(24999).toString();
//The following is simplified, but copied from the working jar used in the Docker Client image/container
MyPOP3Client client = new MyPOP3Client(host, port);
client.connect();
container.stop();
}
}
谢谢大家