一 所需依赖包
<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);
}
}
版权声明:本文为SongJingzhou原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。