docker-java

一 所需依赖包

<dependency>
    <groupId>com.github.docker-java</groupId>
    <artifactId>docker-java</artifactId>
    <version>3.3.3</version>
</dependency>

二 前期准备

2.1 docker已安装

2.2 运行程序用户的docker使用权限

默认docker安装后是root权限运行的,比如运行程序的用户是admin用户,则需要将admin用户加加入到docker用户组

gpasswd -a admin docker
systemctl restart docker

2.3 docker.service 的访问方式,需要开启tcp访问默认,不然可能导致非root用户运行程序导致连接异常

vi /usr/lib/systemd/system/docker.service

将 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

改为
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock

然后重启

systemctl daemon-reload

systemctl restart docker

三 配置参数

3.1 配置信息类,可以放在配置文件中,为了演示直接写死
public class Docker {
    /** docker 连接方式
     * 或者 "unix:///var/run/docker.sock"
     */
    private String host = "tcp://DOCKER_HOST_IP:2375";
    private String configDir = "/home/admin/.docker";
    private String apiVersion = "1.30";
    private String registerUrl = "";
    private String registerName = "";
    private String registerPassword = "";
    private String registerEmail = "";
    private Boolean tlsVerify = false;
    private String certPath = ""; // tsl证书地址
}

3.2 创建请求参数

import java.util.Collection;
import java.util.List;
import java.util.Map;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class ContainerCreateParam implements Serializable {

    private String imageName;
    private String containerName;
    /**
     * 端口映射Map,key是hostPort,value是containerPort
     */
    private Map<Integer, Integer> portMap;
    /**
     *  卷绑定 /host:/container:ro
     */
    private Collection<String> volumeBindSpecs;
    private Long memory;
    private List<String> envs;
}

四 工具类

import cn.hutool.core.collection.CollectionUtil;
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.model.Bind;
import com.github.dockerjava.api.model.ExposedPort;
import com.github.dockerjava.api.model.HostConfig;
import com.github.dockerjava.api.model.PortBinding;
import com.github.dockerjava.api.model.SearchItem;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.xz.cp.core.exception.BusinessException;
import com.xz.cp.core.utils.JsonUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.apache.commons.lang3.BooleanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class DockerUtils {

    private static final String CONTAINER_NAME_PATTERN = "^/?[a-zA-Z0-9][a-zA-Z0-9_.-]+$";
    private static final Logger LOG = LoggerFactory.getLogger(DockerUtils.class);

    private static DockerClient dockerClient;

    public DockerUtils() {
        Docker dockerProperties = new Docker(); // 取配置信息,视情况放在配置中心读取
        DefaultDockerClientConfig.Builder builder = DefaultDockerClientConfig
            .createDefaultConfigBuilder()
            .withDockerHost(dockerProperties.getHost())
            .withDockerConfig(dockerProperties.getConfigDir())
            .withApiVersion(dockerProperties.getApiVersion()) // optional
            .withRegistryUrl(dockerProperties.getRegisterUrl())
            .withRegistryUsername(dockerProperties.getRegisterName())
            .withRegistryPassword(dockerProperties.getRegisterPassword())
            .withRegistryEmail(dockerProperties.getRegisterEmail());

        if (BooleanUtils.isTrue(dockerProperties.getTlsVerify())) {
            builder.withDockerTlsVerify(true)
                .withDockerCertPath(dockerProperties.getCertPath());
        }

        dockerClient = DockerClientBuilder.getInstance(builder.build()).build();

        LOG.info("dockerClient init success");
    }

    private void _checkContainerName(String containerName) {
        if (!Pattern.matches(CONTAINER_NAME_PATTERN, containerName)) {
            throw new BusinessException("", "非法容器名!");
        }
    }

    /**
     * 创建容器
     *
     * @param containerCreateParam containerCreateParam
     * @return 创建完的容器
     */
    public CreateContainerResponse createContainer(ContainerCreateParam containerCreateParam) {
        _checkContainerName(containerCreateParam.getContainerName());

        // 创建容器需要使用的命令
        CreateContainerCmd containerCmd = dockerClient
            .createContainerCmd(containerCreateParam.getImageName())
            .withName(containerCreateParam.getContainerName());
        // 封装端口映射
        List<PortBinding> list = new ArrayList<>();
        Map<Integer, Integer> portMap = containerCreateParam.getPortMap();
        for (Integer hostPort : portMap.keySet()) {
            // 暴露端口
            containerCmd = containerCmd
                .withExposedPorts(ExposedPort.parse(portMap.get(hostPort) + "/tcp"));
            // 绑定主机端⼝ -> docker容器端⼝
            list.add(PortBinding.parse(hostPort + ":" + portMap.get(hostPort)));
        }

        HostConfig hostConfig = HostConfig.newHostConfig()
            .withMemory(containerCreateParam.getMemory() == null ? 1024L * 1024 * 1024
                : containerCreateParam.getMemory())
            .withPortBindings(list);
        if (CollectionUtil.isNotEmpty(containerCreateParam.getVolumeBindSpecs())) {
            List<Bind> volumeBinds = containerCreateParam.getVolumeBindSpecs().stream()
                .map(Bind::parse)
                .collect(Collectors.toList());

            hostConfig.withBinds(volumeBinds);
        }

        if (CollectionUtil.isNotEmpty(containerCreateParam.getEnvs())) {
            containerCmd = containerCmd.withEnv(containerCreateParam.getEnvs());
        }

        // 执行创建命令
        CreateContainerResponse container = containerCmd
            .withHostConfig(hostConfig)
            .exec();

        LOG.info("create container res = {}", JsonUtils.toString(container));
        return container;
    }

    public List<SearchItem> searchItems(String image) {
        return dockerClient.searchImagesCmd(image).exec();
    }

    /**
     * 关闭容器
     *
     * @param id 容器ID
     */
    public void stopContainer(String id) {
        dockerClient.stopContainerCmd(id).exec();
    }

    /**
     * 暂停容器
     *
     * @param id 容器ID
     */
    public void pauseContainer(String id) {
        dockerClient.pauseContainerCmd(id).exec();
    }

    /**
     * 重启容器
     *
     * @param id 容器ID
     */
    public void restartContainer(String id) {
        dockerClient.restartContainerCmd(id).exec();
    }

    /**
     * 删除容器
     *
     * @param id 容器ID
     */
    public void startContainer(String id) {
        dockerClient.startContainerCmd(id).exec();
    }

    /**
     * docker容器commit为镜像
     *
     * @param containerID 容器id
     * @param rep         镜像的仓库,就相当于【ubuntu:latest】中的【ubuntu】
     * @param tag         镜像的标签,就相当于【ubuntu:latest】中的【latest】
     */
    public void createImageByContainer(String containerID, String rep, String tag) {
        dockerClient.commitCmd(containerID).withRepository(rep).withTag(tag).exec();
    }
}

五 测试类

@SpringBootTest
class DockerUtilsTest {

    @Autowired
    DockerUtils dockerUtils;

    @Test
    void createContainer() {
        ContainerCreateParam param = new ContainerCreateParam();

        String containerName = "customizeName-" + UUID.fastUUID();
        param.setContainerName(containerName);
        param.setEnvs(List.of("MYSQL_ROOT_PASSWORD=123456"));
        param.setImageName("mysql:5.7");
        param.setVolumeBindSpecs(List.of("/root/docker_data/" + containerName + ":/var/lib/mysql"));
        param.setPortMap(Map.of(3318, 3306));
        param.setMemory(1024L * 1024 * 1024 * 2);
        dockerUtils.createContainer(param);
    }
}
### 将Docker集成到Java项目中 为了实现Java应用程序的自动化部署以及简化环境配置,可以考虑通过编写脚本或者利用CI/CD工具来调用Docker CLI命令完成镜像构建与推送操作。然而,在Java代码内部直接控制Docker行为通常不是最佳实践;更推荐的方式是在开发流程之外处理这些任务。 如果确实有需求要在Java应用里管理容器生命周期,则可借助于一些开源库比如[Docker Java](https://github.com/docker-java/docker-java),它提供了访问Docker REST API的能力,允许开发者以编程方式执行诸如创建、启动、停止和删除容器等动作[^1]。 下面是一个简单的例子展示如何使用`docker-java`库在Java程序中交互式地管理和监控Docker服务: #### 添加依赖项至Maven POM文件 ```xml <dependency> <groupId>com.github.docker-java</groupId> <artifactId>docker-java-core</artifactId> <version>3.2.12</version> </dependency> <dependency> <groupId>com.github.docker-java</groupId> <artifactId>docker-java-transport-httpclient5</artifactId> <version>3.2.12</version> </dependency> ``` #### 初始化客户端连接实例 ```java import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.core.DefaultDockerClientConfig; import com.github.dockerjava.httpclient5.ApacheDockerHttpClient; import com.github.dockerjava.core.DockerClientImpl; public class DockerManager { private static final String DOCKER_HOST = "tcp://localhost:2376"; private static final int CONNECTION_TIMEOUT_MILLIS = 30 * 1000; private static final Version DEFAULT_API_VERSION = Version.V1_41; public DockerClient createDockerClient() { DefaultDockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder() .withDockerHost(DOCKER_HOST) .build(); ApacheDockerHttpClient httpClient = new ApacheDockerHttpClient.Builder() .dockerHost(config.getDockerHost()) .maxConnections(100) .connectionTimeout(CONNECTION_TIMEOUT_MILLIS) .build(); return DockerClientImpl.getInstance(config, httpClient); } } ``` 此段代码展示了怎样建立一个能够远程操控本地或其他服务器上运行着的Docker守护进程的对象。请注意替换URL地址以便匹配实际使用的Docker主机位置。 对于具体的Java应用打包成Docker镜像的过程,建议遵循标准做法——即先准备好包含必要指令集在内的Dockerfile描述文档,再运用官方提供的JDK基础映像作为起点逐步定制专属的应用环境。最后按照常规步骤实施镜像编译(`docker build`)及分发(`docker push`)作业即可[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值