Java获取docker容器状态

最近接到一个小需求,就是通过java应用程序获取服务器上docker容器的运行状态,所以就再网上搜了搜,发现实现此方式大体有2种思路。 1、通过连入系统(ssh),执行docker ps 等命令,然后根据命令返回的字符串结果,解析出其中的状态信息。此方法的特点就是:非常暴力,如果连接其他主机,需要知晓用户名和密码。 附上相关代码DockerPsService类:

package com.collection.dockerdemo.service;

import com.collection.dockerdemo.bean.ContainerInfo;

import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 通过本地执行cmd命令获取docker的一些状态参数
 */
public class DockerPsService {

    private DockerPsService() {}

    /**
     * 此处设置只显示容器名称和运行状态,可以自定义扩展
     */
    private static final String FORMAT = "\"table {{.Names}}\\t{{.Status}}\"";

    /**
     * 获取容器信息
     */
    public static List getContainerInfoList() throws Exception {
        List containerInfoList = new ArrayList();

        //执行shell命令获取容器信息
        Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "docker ps -a --format " + FORMAT}, null, null);
        InputStreamReader ir = new InputStreamReader(process.getInputStream());
        LineNumberReader input = new LineNumberReader(ir);
        String line;
        process.waitFor();

        System.out.println("********************linux 收集docker容器启动状态 开始*****************************");
        int rowIndex = 0;
        while ((line = input.readLine()) != null) {
            System.out.println(line);
            //表格头部信息不需要获取
            if (rowIndex != 0) {
                //把连续的空格转成1个空格
                line = line.replaceAll(" + ", " ");
                String arr[] = line.split(" ");
                containerInfoList.add(new ContainerInfo(arr[0], arr[1]));
            }
            rowIndex++;
        }

        System.out.println("********************linux 收集docker容器启动状态 结束*****************************");
        System.out.println("*************************打印容器名称和状态***************************************");
        containerInfoList.forEach(item -> System.out.println(item.toString()));

        return containerInfoList;
    }

    /**
     * 检测容器是否启动
     * 如果未启动,执行重启命令
     */
    public static void checkContainerIsRuning(String containerName) throws Exception {
        List containerInfoList = getContainerInfoList();
        //非空检测
        if (containerInfoList.size() == 0 || containerName == null || containerName.trim().length() == 0) {
            return;
        }
        //从Java 8 引入的一个很有趣的特性是 Optional 类,Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException)
        Optional containerInfoOptiona = containerInfoList.stream().filter(containerInfo -> containerName.equals(containerInfo.getName())).findFirst();

        //如果容器存在
        if (containerInfoOptiona.isPresent()) {
            ContainerInfo containerInfo = containerInfoOptiona.get();
            //Up 状态标识运行中
            if ("Up".equals(containerInfo.getStatus())) {
                System.out.printf("容器:{%s} 心跳检测正常......", containerName);
                return;
            }
            System.err.printf("容器:{%s} 运行状态为:{%s},正在准备重启....\n", containerName, containerInfo.getStatus());

            //docker命令去掉-a 只看运行中的容器
            Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "docker restart " + containerName}, null, null);
            InputStreamReader ir = new InputStreamReader(process.getInputStream());
            LineNumberReader input = new LineNumberReader(ir);
            process.waitFor();

            String line;
            //输出执行docker restart命令的返回结果
            while ((line = input.readLine()) != null) {
                System.out.println(line);
            }
        } else {
            System.err.printf("容器:{%s}不存在!", containerName);
        }
    }

}

2、通过docker-java api调取docker提供的统一接口获取容器相关状态。此方法的特点就是:需要开启docker对应端口,测试前务必测试下docker 2375端口时候开启,接口是否能够打开,一般都需要手动开启(踩坑了的地方)。 附上相关代码DockerJavaService :

package com.collection.dockerdemo.service;

import com.collection.dockerdemo.bean.ContainerStatisticsInfo;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.command.InspectContainerResponse;
import com.github.dockerjava.api.model.HostConfig;
import com.github.dockerjava.api.model.Statistics;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.InvocationBuilder;
import org.apache.commons.lang3.SystemUtils;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@Service
public class DockerJavaService {

    //注意,务必开启docker的2375监听,否则无法连接
    private  final String localDockerHost = SystemUtils.IS_OS_WINDOWS ? "tcp://203.86.235.53:2375" : "unix:///var/run/docker.sock";


    private DockerClient dockerClient = null;

    @PostConstruct
    public  void connectDocker() {
        dockerClient = DockerClientBuilder.getInstance(localDockerHost).build();
        System.out.println("dockerClient:>>>>>>>>>>>>>"+dockerClient);
    }



    // docker run ...
    public String createContainer(String imageName, String containerName, HostConfig hostConfig, List cmd){
        CreateContainerResponse container = dockerClient.createContainerCmd(imageName)
                .withName(containerName)
                .withHostConfig(hostConfig)
                .withCmd(cmd)
                .exec();
        return container.getId();
    }


    public void startContainer(String containerId) {
        dockerClient.startContainerCmd(containerId).exec();
    }

    // docker stop containerId
    public void stopContainer(String containerId) {
        dockerClient.stopContainerCmd(containerId).exec();
    }


    //docker rm containerId
    public void removeContainer(String containerId) {
        dockerClient.removeContainerCmd(containerId).exec();
    }


    //docker inspect containerId
    public InspectContainerResponse.ContainerState inspectContainerStatus(String containerId) {
        InspectContainerResponse response = dockerClient.inspectContainerCmd(containerId).exec();
        return response.getState();
    }


    // docker stats --no-stream containerId
    //ContainerStatisticsInfo.java 中只有两个属性Statistics statistics 和 boolean ok
    public ContainerStatisticsInfo containerState(String containerId) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        ContainerStatisticsInfo statistics = new ContainerStatisticsInfo();
        InvocationBuilder.AsyncResultCallback callback = new InvocationBuilder.AsyncResultCallback(){
            @Override
            public void onNext(Statistics object) {
                try {
                    statistics.setStatistics(object);
                    statistics.setOk(true);
                } finally {
                    countDownLatch.countDown();
                }
            }
        };
        dockerClient.statsCmd(containerId).withNoStream(true).exec(callback);
        countDownLatch.await(5000, TimeUnit.MILLISECONDS);
        return statistics;
    }
}

以上代码均经过实际测试,可以当作工具类或者service直接调用或改造,希望可能帮助到有需要的朋友!
1.本站所有资源收集于互联网,仅用于学习和研究,若用于违法,与本站无关,仅限学习交流请勿用于商业用途。 2.会员在本站下载的VIP素材后,只拥有使用权,著作权归原作者及49资源网所有。 3.VIP素材,未经合法授权,会员不得以任何形式发布、传播、复制、转售该素材,否则一律封号处理。 4.如果素材损害你的权益,请联系客服删除。
49资源网 » Java获取docker容器状态

发表评论