大数据

docker-java工具类实现

ContainerInfoDTO.java

import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ContainerInfoDTO {
    private String id;        // 容器ID
    private String name;      // 容器名称
    private Boolean status;   // 运行状态(true:运行中, false:已停止)
    private String image;     // 镜像名称
    private String desc;      // 描述信息
    private ServiceTypeEnum type; // 服务类型
}

DockerInfoDTO.java

import lombok.Data;

@Data
public class DockerInfoDTO {
    private Integer runningContainer; // 运行中的容器数量
    private Integer stopContainer;    // 已停止的容器数量
    private Integer allContainer;     // 全部容器数量
}

ImageInfoDTO.java

import lombok.Data;

@Data
public class ImageInfoDTO {
    private String id;
    private String name;
    private long created;
    private long size;
}

ServiceTypeEnum.java

public enum ServiceTypeEnum {
    MIDDLEWARE_SERVER,  // 中间件服务
    BUSINESS_SERVICE;   // 业务服务
}

DockerClientUtils.java

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CreateContainerCmd;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.command.PullImageResultCallback;
import com.github.dockerjava.api.model.*;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.command.LogContainerResultCallback;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class DockerClientUtils {

    private final DockerClient client;

    /**
     * 构造函数,初始化Docker连接
     */
    public DockerClientUtils(String dockerHost) {
        this.client = DockerClientBuilder.getInstance(dockerHost).build();
    }

    /**
     * 获取Docker系统信息
     */
    public DockerInfoDTO getDockerInfo() {
        Info info = client.infoCmd().exec();
        DockerInfoDTO dto = new DockerInfoDTO();
        dto.setAllContainer(info.getContainers());
        dto.setStopContainer(info.getContainersStopped());
        dto.setRunningContainer(info.getContainersRunning());
        return dto;
    }

    /**
     * 启动容器
     */
    public void startContainer(String containerId) {
        if (!isContainerRunning(containerId)) {
            client.startContainerCmd(containerId).exec();
        }
    }

    /**
     * 停止容器
     */
    public void stopContainer(String containerId) {
        if (isContainerRunning(containerId)) {
            client.stopContainerCmd(containerId).exec();
        }
    }

    /**
     * 删除容器
     *
     * @param containerId 容器ID
     * @param force       是否强制删除运行中的容器
     */
    public void removeContainer(String containerId, boolean force) {
        if (isContainerRunning(containerId)) {
            if (force) {
                // 如果容器正在运行且强制删除,先停止容器
                stopContainer(containerId);
            } else {
                throw new RuntimeException("容器正在运行,请先停止容器或设置force=true");
            }
        }
        client.removeContainerCmd(containerId).exec();
    }

    /**
     * 删除容器(不强制删除运行中的容器)
     *
     * @param containerId 容器ID
     */
    public void removeContainer(String containerId) {
        removeContainer(containerId, false);
    }

    /**
     * 获取所有容器(运行中和已停止)
     */
    public List<ContainerInfoDTO> getAllContainer() {
        List<ContainerInfoDTO> result = new ArrayList<>();
        result.addAll(getRunningContainer());
        result.addAll(getStopContainer());
        return result;
    }

    /**
     * 获取运行中的容器
     */
    public List<ContainerInfoDTO> getRunningContainer() {
        return convertContainers(client.listContainersCmd().exec(), true);
    }

    /**
     * 获取已停止的容器
     */
    public List<ContainerInfoDTO> getStopContainer() {
        return convertContainers(
                client.listContainersCmd()
                        .withShowAll(true)
                        .withStatusFilter(Collections.singleton("exited"))
                        .exec(),
                false
        );
    }

    /**
     * 获取容器日志
     */
    public List<String> getContainerLogs(String containerId, int lineCount)
            throws InterruptedException {

        List<String> logs = new ArrayList<>();

        client.logContainerCmd(containerId)
                .withStdOut(true)
                .withStdErr(true)
                .withTail(lineCount)
                .exec(new LogContainerResultCallback() {
                    @Override
                    public void onNext(Frame item) {
                        logs.add(item.toString());
                    }
                }).awaitCompletion();

        return logs;
    }

    /**
     * 根据条件筛选容器
     */
    public List<ContainerInfoDTO> filterContainers(String name, Boolean status) {
        return getAllContainer().stream()
                .filter(c -> name == null || c.getName().contains(name))
                .filter(c -> status == null || c.getStatus().equals(status))
                .collect(Collectors.toList());
    }

    // 辅助方法:转换Container对象为ContainerInfoDTO
    private List<ContainerInfoDTO> convertContainers(List<Container> containers, boolean status) {
        List<ContainerInfoDTO> result = new ArrayList<>();

        containers.forEach(container -> {
            ContainerInfoDTO dto = new ContainerInfoDTO();
            dto.setId(StringUtils.substring(container.getId(), 0, 12));
            dto.setName(container.getNames()[0].substring(1));
            dto.setImage(container.getImage());
            dto.setStatus(status);

            if (container.getLabels() != null) {
                dto.setDesc(container.getLabels().get("DESC"));
                String type = container.getLabels().get("TYPE");
                if (type != null) {
                    dto.setType(ServiceTypeEnum.valueOf(type));
                }
            }

            result.add(dto);
        });

        return result;
    }

    // 辅助方法:检查容器是否在运行
    private boolean isContainerRunning(String containerId) {
        return getRunningContainer().stream()
                .anyMatch(c -> c.getId().equals(containerId));
    }

    /**
     * 拉取镜像
     *
     * @param imageName 镜像名称(格式: repository:tag)
     * @throws InterruptedException 如果拉取过程被中断
     */
    public void pullImage(String imageName) throws InterruptedException {
        String[] parts = imageName.split(":");
        String repository = parts[0];
        String tag = parts.length > 1 ? parts[1] : "latest";

        client.pullImageCmd(repository)
                .withTag(tag)
                .exec(new PullImageResultCallback())
                .awaitCompletion();
    }

    /**
     * 列出所有镜像
     */
    public List<ImageInfoDTO> listImages() {
        return client.listImagesCmd()
                .exec()
                .stream()
                .map(image -> {
                    ImageInfoDTO dto = new ImageInfoDTO();
                    dto.setId(image.getId());
                    dto.setCreated(image.getCreated());
                    dto.setSize(image.getSize());

                    if (image.getRepoTags() != null && image.getRepoTags().length > 0) {
                        dto.setName(image.getRepoTags()[0]);
                    }

                    return dto;
                })
                .collect(Collectors.toList());
    }

    /**
     * 删除镜像
     *
     * @param imageId 镜像ID
     * @param force   是否强制删除
     */
    public void removeImage(String imageId, boolean force) {
        client.removeImageCmd(imageId)
                .withForce(force)
                .exec();
    }

    /**
     * 运行容器(带参数)
     *
     * @param imageName     镜像名称
     * @param containerName 容器名称(可选)
     * @param ports         端口映射(格式: "主机端口:容器端口")
     * @param envs          环境变量(格式: "KEY=VALUE")
     * @param volumes       卷映射(格式: "主机路径:容器路径")
     * @param command       容器启动命令(可选)
     * @return 容器ID
     */
    public String runContainer(String imageName,
                               String containerName,
                               List<String> ports,
                               List<String> envs,
                               List<String> volumes,
                               List<String> command) {

        // 创建容器
        CreateContainerCmd containerCmd = client.createContainerCmd(imageName).withName(containerName);

        // 端口绑定
        if (ports != null) {
            List<PortBinding> portBindings = new ArrayList<>();
            ExposedPort[] exposedPorts = new ExposedPort[ports.size()];

            for (int i = 0; i < ports.size(); i++) {
                String[] parts = ports.get(i).split(":");
                int hostPort = Integer.parseInt(parts[0]);
                int containerPort = Integer.parseInt(parts[1]);

                exposedPorts[i] = ExposedPort.tcp(containerPort);
                portBindings.add(PortBinding.parse(hostPort + ":" + containerPort));
            }

            containerCmd = containerCmd
                    .withExposedPorts(exposedPorts)
                    .withPortBindings(portBindings);
        }

        if (envs != null) {
            containerCmd = containerCmd.withEnv(envs);
        }
        if (volumes != null) {
            containerCmd = containerCmd.withVolumes(volumes.stream()
                            .map(v -> new Volume(v.split(":")[1]))
                            .toArray(Volume[]::new))
                    .withHostConfig(HostConfig.newHostConfig()
                            .withBinds(volumes.stream()
                                    .map(Bind::parse)
                                    .toArray(Bind[]::new)));
        }
        if (command != null) {
            containerCmd = containerCmd.withCmd(command);
        }

        CreateContainerResponse response = containerCmd
                .exec();

        // 启动容器
        client.startContainerCmd(response.getId()).exec();

        return response.getId();
    }
}

test.java

import java.util.Arrays;
import java.util.List;

public class Test {
    public static void test01() {
        // 初始化Docker客户端
        DockerClientUtils docker = new DockerClientUtils("tcp://xxx.xxx.xxx.xxx:2375");

        // 获取Docker系统信息
        DockerInfoDTO info = docker.getDockerInfo();
        System.out.println("Docker信息:");
        System.out.println("运行中容器: " + info.getRunningContainer());
        System.out.println("已停止容器: " + info.getStopContainer());
        System.out.println("全部容器: " + info.getAllContainer());
        List<ContainerInfoDTO> allContainer = docker.getAllContainer();
        for (ContainerInfoDTO containerInfoDTO : allContainer) {
            System.out.println(containerInfoDTO);
            String id = containerInfoDTO.getId();
            String containerName = containerInfoDTO.getName();
            if ("my-nginx".equals(containerName)) {
                docker.removeContainer(id, true);
            }
        }
        info = docker.getDockerInfo();
        System.out.println("Docker信息:");
        System.out.println("运行中容器: " + info.getRunningContainer());
        System.out.println("已停止容器: " + info.getStopContainer());
        System.out.println("全部容器: " + info.getAllContainer());
    }

    public static void test02() {
        // 初始化Docker客户端
        DockerClientUtils docker = new DockerClientUtils("tcp://192.168.20.242:2375");

//        docker.pullImage("nginx:latest");

        // 运行带参数的容器
        List<String> ports = Arrays.asList("8080:80", "8443:443");
        List<String> envs = Arrays.asList("ENV=production", "DEBUG=false");
//        List<String> volumes = Arrays.asList("/host/path:/container/path");

        docker.runContainer(
                "nginx:latest",
                "my-nginx",
                ports,
                envs,
                null,
                null
        );

        DockerInfoDTO info = docker.getDockerInfo();
        System.out.println("Docker信息:");
        System.out.println("运行中容器: " + info.getRunningContainer());
        System.out.println("已停止容器: " + info.getStopContainer());
        System.out.println("全部容器: " + info.getAllContainer());
    }
    public static void main(String[] args) throws InterruptedException {
//        test01();
        test02();
    }
}

windows docker desktop 启用远程API访问:

打开Docker Desktop设置

进入"General" → 勾选"Expose daemon on tcp://localhost:2375 without TLS"

防火墙配置:允许2375端口(TCP)的入站连接或者在高级防火墙规则中限制只允许特定IP访问

执行端口映射命令管理员权限开启cmd,执行以下命令:

netsh interface portproxy add v4tov4 listenport=2375 listenaddress=%EXPOSE_IP% connectaddress=127.0.0.1 connectport=2375

将上述命令中的%EXPOSE_IP% 替换成你需要暴露的ip 也就是安装docker desktop的主机ip