一 所需依赖包
<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 {@AutowiredDockerUtils dockerUtils;@Testvoid 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);} }