Docker-Java操作Windows Docker踩坑记录
最近正在学习OJ判题系统,需要用到Docker来对用户提交的代码进行环境隔离,鱼皮哥推荐使用的是虚拟机的方式,我这里由于已经使用WSL2 按照了Docker,所有就记录一下,踩到的坑
坑点1:JDK版本问题导致日志无法输出
我jdk用的17,导致引入运行Docker-Java快速入门案例时,没有日志打印的问题
就是出现了SLF4J的提示,这个解决办法很简单,引入一个依赖就好
▼xml复制代码<dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.4.11</version> </dependency>
引入后,启动日志就显示正常了
引入依赖后,可以通过这段代码对输入日志进行控制
▼java复制代码import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import org.slf4j.LoggerFactory; Logger dockerLogger = (Logger) LoggerFactory.getLogger("com.github.dockerjava"); Logger clientLogger = (Logger) LoggerFactory.getLogger("org.apache.hc.client5.http"); dockerLogger.setLevel(Level.INFO); clientLogger.setLevel(Level.INFO);
坑点2:使用默认的快速入门代码,无法连接Win Docker
默认的快速入门方式
▼java复制代码DockerClient client = DockerClientBuilder.getInstance().build(); client.pingCmd().exec(); client.close();
运行提示
Exception in thread "main" java.lang.IllegalArgumentException: Unsupported protocol scheme: npipe:////./pipe/dockerDesktopLinuxEngine 这个错误表示默认连接的是Linux的Docker,可是我要连接Windows的上的,哪该怎么办?
AI 大法,直接问Deespeek或者通义千问,通义给出,我们需要修改windows的一个配置,然后再修改对应的DockerClient 配置
ok 按照他的配置修改了,我们再修改DockerClient的连接配置
▼java复制代码public static void main(String[] args) { // 配置 Docker 客户端 DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder() .withDockerHost("tcp://localhost:2375") // 指定 Docker 主机地址 .withDockerTlsVerify(false) // 禁用 TLS 验证(测试环境) .build(); // 创建 Docker 客户端实例 DockerClient dockerClient = DockerClientBuilder.getInstance(config).build(); dockerClient.pingCmd().exec(); dockerClient.close(); }
运行可以发现,控制台已经正确打印响应信息了
但是我觉得还不行,开启TSL 存在风险,不能使用默认的npipe吗?
继续问AI,
AI 提示我们可以使用 npipe:////./pipe/docker_engine 来进行连接,于是修改代码
▼java复制代码public static void main(String[] args) throws IOException { // 配置 Docker 客户端 DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder() .withDockerHost("npipe:////./pipe/docker_engine") // 指定 Docker 主机地址 .withDockerTlsVerify(false) // 禁用 TLS 验证(测试环境) .build(); DockerClient client = DockerClientBuilder.getInstance(config).build(); client.pingCmd().exec(); client.close(); }
我非常高兴的运行,以为这次成功了,没想到继续包了一个跟上面一样的错误 Exception in thread "main" java.lang.IllegalArgumentException: Unsupported protocol scheme: npipe:////./pipe/docker_engine 翻译一下,发现是客户端不认真npipe这个命令
随后查看官网的 Available transports 文档 ,发现默认的客户端(Jersey)不支持npipe命令
我原以为引入docker-java-transport-httpclient5 这个依赖后,会自动使用,但有想想,又不是spring管理的,它凭什么自动使用。因此还需要我自己配置HttpClient,修改后的代码
▼java复制代码public static void main(String[] args) throws IOException { ApacheDockerHttpClient httpClient = new ApacheDockerHttpClient.Builder() .dockerHost(URI.create("npipe:////./pipe/docker_engine")).build(); DockerClient client = DockerClientBuilder.getInstance() .withDockerHttpClient(httpClient).build(); client.pingCmd().exec(); client.close(); }
由于鱼皮哥给的pom.xml 依赖中已经引入了
docker-java-transport-httpclient5这里就不写了
运行
哈哈哈哈哈 成功
总结
虽然由于环境给鱼皮哥的不同,踩了点坑,解决坑点时间,但是在解决坑点的过程中,提高了自身解决问题的能力。
