diff --git a/build.gradle b/build.gradle index 39f5b3f..d526b6c 100644 --- a/build.gradle +++ b/build.gradle @@ -66,3 +66,9 @@ dependencies { tasks.named('test') { useJUnitPlatform() } + +tasks.withType(Javadoc) { + options.encoding = 'UTF-8' + options.docEncoding = 'UTF-8' + options.charSet = 'UTF-8' +} \ No newline at end of file diff --git a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomConfig.java b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomConfig.java index 5d46deb..3713df3 100644 --- a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomConfig.java +++ b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomConfig.java @@ -4,6 +4,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; +/** + * The type Custom config. + * + * @author whitem4rk + * @version 1.0 + * @see ProcessedData + */ @Getter @NoArgsConstructor public class CustomConfig { diff --git a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomContainer.java b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomContainer.java index 8482e25..4b6dbd7 100644 --- a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomContainer.java +++ b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomContainer.java @@ -6,6 +6,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; +/** + * The type Custom container. + * + * @author whitem4rk + * @version 1.0 + * @see ProcessedData + */ @Getter @NoArgsConstructor public class CustomContainer { diff --git a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomHost.java b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomHost.java index 1d96713..9a7a511 100644 --- a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomHost.java +++ b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomHost.java @@ -6,6 +6,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; +/** + * The type Custom host. + * + * @author whitem4rk + * @version 1.0 + * @see ProcessedData + */ @Getter @NoArgsConstructor public class CustomHost { diff --git a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomImage.java b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomImage.java index 7119939..92e76a0 100644 --- a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomImage.java +++ b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomImage.java @@ -4,6 +4,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; +/** + * The type Custom image. + * + * @author whitem4rk + * @version 1.0 + * @see ProcessedData + */ @Getter @NoArgsConstructor public class CustomImage { diff --git a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomIpam.java b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomIpam.java index a2a24a8..6999681 100644 --- a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomIpam.java +++ b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomIpam.java @@ -6,6 +6,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; +/** + * The type Custom ipam. + * + * @author whitem4rk + * @version 1.0 + * @see ProcessedData + */ @Getter @NoArgsConstructor public class CustomIpam { diff --git a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomMount.java b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomMount.java index 1535dce..d740543 100644 --- a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomMount.java +++ b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomMount.java @@ -4,6 +4,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; +/** + * The type Custom mount. + * + * @author whitem4rk + * @version 1.0 + * @see ProcessedData + */ @Getter @NoArgsConstructor public class CustomMount { diff --git a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomNetwork.java b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomNetwork.java index 6f87792..f4e00be 100644 --- a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomNetwork.java +++ b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomNetwork.java @@ -6,6 +6,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; +/** + * The type Custom network. + * + * @author whitem4rk + * @version 1.0 + * @see ProcessedData + */ @Getter @NoArgsConstructor public class CustomNetwork { diff --git a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomNetworkSettings.java b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomNetworkSettings.java index d4fda36..edfeef4 100644 --- a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomNetworkSettings.java +++ b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomNetworkSettings.java @@ -4,6 +4,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; +/** + * The type Custom network settings. + * + * @author whitem4rk + * @version 1.0 + * @see ProcessedData + */ @Getter @NoArgsConstructor public class CustomNetworkSettings { diff --git a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomPort.java b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomPort.java index aec474a..49c530c 100644 --- a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomPort.java +++ b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomPort.java @@ -4,6 +4,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; +/** + * The type Custom port. + * + * @author whitem4rk + * @version 1.0 + * @see ProcessedData + */ @Getter @NoArgsConstructor public class CustomPort { diff --git a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomVolume.java b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomVolume.java index 7ecc5b1..6110828 100644 --- a/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomVolume.java +++ b/src/main/java/api/goraebab/domain/blueprint/dockerObject/CustomVolume.java @@ -4,6 +4,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; +/** + * The type Custom volume. + * + * @author whitem4rk + * @version 1.0 + * @see ProcessedData + */ @Getter @NoArgsConstructor public class CustomVolume { diff --git a/src/main/java/api/goraebab/domain/blueprint/dockerObject/ProcessedData.java b/src/main/java/api/goraebab/domain/blueprint/dockerObject/ProcessedData.java index 985f274..c3b6053 100644 --- a/src/main/java/api/goraebab/domain/blueprint/dockerObject/ProcessedData.java +++ b/src/main/java/api/goraebab/domain/blueprint/dockerObject/ProcessedData.java @@ -6,6 +6,15 @@ import lombok.Getter; import lombok.NoArgsConstructor; +/** + * The data which is used to synchronize Docker with. + * From CustomHost class to leaf, all the fields are following docker daemon API request arguments. + * If you add new features, check API documents and follow JSON key and value format. + * Also, add "custom" prefix and change key format using @JsonProperty + * + * @author whitem4rk + * @version 1.0 + */ @Getter @NoArgsConstructor public class ProcessedData { diff --git a/src/main/java/api/goraebab/domain/blueprint/dto/BlueprintReqDto.java b/src/main/java/api/goraebab/domain/blueprint/dto/BlueprintReqDto.java index 572d20a..0eaff39 100644 --- a/src/main/java/api/goraebab/domain/blueprint/dto/BlueprintReqDto.java +++ b/src/main/java/api/goraebab/domain/blueprint/dto/BlueprintReqDto.java @@ -9,6 +9,12 @@ import lombok.Getter; import lombok.NoArgsConstructor; +/** + * Request DTO which Client sends when synchronize Docker with host. + * + * @author whitem4rk + * @version 1.0 + */ @Getter @NoArgsConstructor public class BlueprintReqDto { diff --git a/src/main/java/api/goraebab/domain/blueprint/dto/BlueprintResDto.java b/src/main/java/api/goraebab/domain/blueprint/dto/BlueprintResDto.java index b0ca522..1b70d2c 100644 --- a/src/main/java/api/goraebab/domain/blueprint/dto/BlueprintResDto.java +++ b/src/main/java/api/goraebab/domain/blueprint/dto/BlueprintResDto.java @@ -8,6 +8,14 @@ import java.time.LocalDateTime; +/** + * Response DTO which client request details of blueprint. + * This DTO contains DBMS settings which should not be revealed. + * + * @author whitem4rk + * @version 1.0 + * @see StorageResDto + */ @Getter @Setter @NoArgsConstructor diff --git a/src/main/java/api/goraebab/domain/blueprint/dto/BlueprintsResDto.java b/src/main/java/api/goraebab/domain/blueprint/dto/BlueprintsResDto.java index af80575..7a5a6ae 100644 --- a/src/main/java/api/goraebab/domain/blueprint/dto/BlueprintsResDto.java +++ b/src/main/java/api/goraebab/domain/blueprint/dto/BlueprintsResDto.java @@ -1,6 +1,5 @@ package api.goraebab.domain.blueprint.dto; -import api.goraebab.domain.blueprint.dockerObject.CustomHost; import api.goraebab.domain.blueprint.dockerObject.ProcessedData; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; @@ -10,6 +9,13 @@ import java.time.LocalDateTime; +/** + * Response DTO which client request list of blueprints. + * This DTO only contains necessary information. + * + * @author whitem4rk + * @version 1.0 + */ @Getter @Setter @AllArgsConstructor diff --git a/src/main/java/api/goraebab/domain/blueprint/dto/SyncResultDto.java b/src/main/java/api/goraebab/domain/blueprint/dto/SyncResultDto.java index 4849c44..21005ce 100644 --- a/src/main/java/api/goraebab/domain/blueprint/dto/SyncResultDto.java +++ b/src/main/java/api/goraebab/domain/blueprint/dto/SyncResultDto.java @@ -6,6 +6,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; +/** + * DTO that includes the success status of the container synchronization request contained in the original request. + * Note that Whether the synchronization request succeed or not, this DTO is returned. + * + * @author whitem4rk + * @version 1.0 + */ @Getter @NoArgsConstructor public class SyncResultDto { diff --git a/src/main/java/api/goraebab/domain/blueprint/entity/Blueprint.java b/src/main/java/api/goraebab/domain/blueprint/entity/Blueprint.java index 51262c7..fb95b59 100644 --- a/src/main/java/api/goraebab/domain/blueprint/entity/Blueprint.java +++ b/src/main/java/api/goraebab/domain/blueprint/entity/Blueprint.java @@ -5,6 +5,12 @@ import jakarta.persistence.*; import lombok.*; +/** + * Represents a blueprint entity with information. + * + * @author whitem4rk + * @version 1.0 + */ @Getter @Entity @Table(name = "blueprint") @@ -36,6 +42,12 @@ public void setAsRemote() { this.isRemote = true; } + /** + * Modify. + * + * @param name the blueprint name + * @param data the blueprint JSON format with escape handling applied. + */ public void modify(String name, String data) { if (name != null) { this.name = name; @@ -45,6 +57,14 @@ public void modify(String name, String data) { } } + /** + * Constructs a new instance + * + * @param name the blueprint name + * @param data the blueprint JSON format with escape handling applied. + * @param isRemote whether the blueprint is copied from remote database + * @param storage the storage to be stored + */ @Builder public Blueprint(String name, String data, Boolean isRemote, Storage storage) { this.name = name; diff --git a/src/main/java/api/goraebab/domain/blueprint/mapper/BlueprintMapper.java b/src/main/java/api/goraebab/domain/blueprint/mapper/BlueprintMapper.java index 7003c65..078ecea 100644 --- a/src/main/java/api/goraebab/domain/blueprint/mapper/BlueprintMapper.java +++ b/src/main/java/api/goraebab/domain/blueprint/mapper/BlueprintMapper.java @@ -16,6 +16,12 @@ import org.mapstruct.Named; import org.mapstruct.factory.Mappers; +/** + * Mapper interface for converting {@link Blueprint} entities to various DTOs and vice versa. + * + * @author whitem4rk + * @version 1.0 + */ @Mapper(uses = {StorageMapper.class}) public interface BlueprintMapper { @@ -33,6 +39,13 @@ public interface BlueprintMapper { @IterableMapping(elementTargetType = BlueprintsResDto.class) List toBlueprintsResDtoList(List blueprints); + /** + * Custom mapping method to convert a JSON string into a {@link ProcessedData} object. + * + * @param data the JSON string to convert + * @return the resulting {@link ProcessedData} object + * @throws CustomException if the JSON string cannot be parsed + */ @Named("stringToHost") default ProcessedData stringToHost(String data) { try { diff --git a/src/main/java/api/goraebab/domain/blueprint/mapper/BlueprintRowMapper.java b/src/main/java/api/goraebab/domain/blueprint/mapper/BlueprintRowMapper.java index 8cb5641..3903f2b 100644 --- a/src/main/java/api/goraebab/domain/blueprint/mapper/BlueprintRowMapper.java +++ b/src/main/java/api/goraebab/domain/blueprint/mapper/BlueprintRowMapper.java @@ -5,6 +5,16 @@ import java.sql.SQLException; import org.springframework.jdbc.core.RowMapper; +/** + * A RowMapper implementation that maps a row from the result set to a {@link Blueprint} object. + * + *

This implementation extracts the "data" column from the + * result set and maps it to the {@code data} field in the {@link Blueprint} object.

+ * + * @author whitem4rk + * @version 1.0 + * @see org.springframework.jdbc.core.RowMapper + */ public class BlueprintRowMapper implements RowMapper { private static final String BLUEPRINT_DATA_COLUMN_NAME = "data"; diff --git a/src/main/java/api/goraebab/domain/blueprint/repository/BlueprintRepository.java b/src/main/java/api/goraebab/domain/blueprint/repository/BlueprintRepository.java index 280b101..80e62ce 100644 --- a/src/main/java/api/goraebab/domain/blueprint/repository/BlueprintRepository.java +++ b/src/main/java/api/goraebab/domain/blueprint/repository/BlueprintRepository.java @@ -5,8 +5,24 @@ import org.springframework.stereotype.Repository; import java.util.List; -import java.util.Optional; +/** + * Repository interface for managing {@link Blueprint} entities. + * + *

Extends the {@link JpaRepository} interface to provide CRUD operations and + * additional query methods for {@link Blueprint} objects.

+ * + *

This interface is a Spring Data JPA repository and will be implemented automatically + * by Spring at runtime.

+ * + *

Note: This repository currently does not include QueryDSL integration. + * If you need to perform complex dynamic queries with type safety, you may consider + * adding a custom repository interface and implementing QueryDSL functionality.

+ * + * @author whitem4rk + * @version 1.0 + * @see org.springframework.data.jpa.repository.JpaRepository + */ @Repository public interface BlueprintRepository extends JpaRepository { diff --git a/src/main/java/api/goraebab/domain/blueprint/service/BlueprintService.java b/src/main/java/api/goraebab/domain/blueprint/service/BlueprintService.java index 0aa76e5..035b639 100644 --- a/src/main/java/api/goraebab/domain/blueprint/service/BlueprintService.java +++ b/src/main/java/api/goraebab/domain/blueprint/service/BlueprintService.java @@ -7,6 +7,13 @@ import api.goraebab.domain.blueprint.dto.SyncResultDto; import java.util.List; +/** + * Service interface for managing blueprints. + * Provides methods for creating, modifying, retrieving, applying blueprints to Docker. + * + * @author whitem4rk + * @version 1.0 + */ public interface BlueprintService { List getBlueprints(Long storageId); diff --git a/src/main/java/api/goraebab/domain/blueprint/service/BlueprintServiceImpl.java b/src/main/java/api/goraebab/domain/blueprint/service/BlueprintServiceImpl.java index f7ccb3c..3d197d0 100644 --- a/src/main/java/api/goraebab/domain/blueprint/service/BlueprintServiceImpl.java +++ b/src/main/java/api/goraebab/domain/blueprint/service/BlueprintServiceImpl.java @@ -22,6 +22,14 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +/** + * Implementation of the {@link BlueprintService} interface. + * This service interacts with the database using repositories and synchronizes data with Docker + * through {@link DockerSyncServiceImpl}. + * + * @author whitem4rk + * @version 1.0 + */ @Service @RequiredArgsConstructor public class BlueprintServiceImpl implements BlueprintService { @@ -72,6 +80,14 @@ public BlueprintResDto getBlueprintById(Long storageId, Long blueprintId) { return BlueprintMapper.INSTANCE.toBlueprintResDto(blueprint); } + /** + * Saves a new blueprint and synchronizes it with Docker. + * + * @param storageId the ID of the storage + * @param blueprintReqDto the data of the blueprint to be saved, represented by {@link BlueprintReqDto} + * @return the result of the synchronization, represented by {@link SyncResultDto} + * @throws CustomException if saving or synchronization fails. + */ @Override @Transactional public SyncResultDto saveBlueprint(Long storageId, BlueprintReqDto blueprintReqDto) { diff --git a/src/main/java/api/goraebab/domain/blueprint/service/DockerSyncService.java b/src/main/java/api/goraebab/domain/blueprint/service/DockerSyncService.java index bbf1974..8834995 100644 --- a/src/main/java/api/goraebab/domain/blueprint/service/DockerSyncService.java +++ b/src/main/java/api/goraebab/domain/blueprint/service/DockerSyncService.java @@ -5,6 +5,13 @@ import java.util.List; import java.util.Map; +/** + * Service interface for synchronizing Docker containers with blueprint data. + * Provides methods to manage Docker container operations based on the given processed data. + * + * @author whitem4rk + * @version 1.0 + */ public interface DockerSyncService { List> syncDockerWithBlueprintData(ProcessedData processedData); diff --git a/src/main/java/api/goraebab/domain/blueprint/service/DockerSyncServiceImpl.java b/src/main/java/api/goraebab/domain/blueprint/service/DockerSyncServiceImpl.java index b6a4dcb..12b6b33 100644 --- a/src/main/java/api/goraebab/domain/blueprint/service/DockerSyncServiceImpl.java +++ b/src/main/java/api/goraebab/domain/blueprint/service/DockerSyncServiceImpl.java @@ -27,6 +27,20 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +/** + * Implementation of the {@link DockerSyncService} interface. + *

+ * This class uses DockerClient to manage Docker resources locally or remotely. It performs + * operations such as: + *

    + *
  • Removing existing Docker resources (containers, networks, volumes).
  • + *
  • Synchronizing networks, volumes, and containers with the provided blueprint data.
  • + *
  • Managing Docker images and ensuring the correct state of containers.
  • + *
+ * + * @author whitem4rk + * @version 1.0 + */ @Service @RequiredArgsConstructor @Slf4j @@ -55,18 +69,36 @@ public class DockerSyncServiceImpl implements DockerSyncService { private static final String DEFAULT_BRIDGE_NETWORK_NAME = "bridge"; + /** + * Synchronizes Docker resources (networks, volumes, and containers) with the provided blueprint data. + * + *

This method performs the following operations for each host in the blueprint data:

+ *
    + *
  1. Attempts to establish a connection with the Docker daemon on the local or remote host and verifies it via a ping request.
  2. + *
  3. Removes all non-default Docker resources (networks, containers, volumes) from the host.
  4. + *
  5. Synchronizes networks, ensuring that any required custom networks are created.
  6. + *
  7. Synchronizes volumes by creating any new volumes specified in the blueprint data.
  8. + *
  9. Synchronizes containers by pulling necessary images (if not already available), configuring, and starting the containers in the target network.
  10. + *
+ * + *

Each operation produces results that are returned as a list of status maps, with each map providing details + * about the status (e.g., success or failure) of container synchronization.

+ * + * @param processedData the blueprint data containing configuration for networks, volumes, and containers + * @return a list of maps containing the results of the synchronization for each container. + * Each map includes the container name, status (success or failure), and any associated messages. + * @throws CustomException if any Docker-related error occurs during synchronization + */ @Override public List> syncDockerWithBlueprintData(ProcessedData processedData) { List> containerResults = new ArrayList<>(); try { - // 1. host list 추출 DockerClient dockerClient; List customHosts = processedData.getCustomHost(); for (CustomHost customHost : customHosts) { - // 2. local, remote 연결 시도(`/_ping`), 확인 if (!customHost.getIsRemote()) { testDockerPing(LOCAL_HOST_IP, DOCKER_DAEMON_PORT); dockerClient = dockerClientFactory.createLocalDockerClient(); @@ -75,24 +107,12 @@ public List> syncDockerWithBlueprintData(ProcessedData proce dockerClient = dockerClientFactory.createRemoteDockerClient(customHost.getIp()); } - // 3. default로 생성되는것들은 제외하고 local, remote의 모든 network, container, volume 삭제 - // network - `none` , `bridge`, `customHost` , `goraebab_network` - // container - `goraebab-backend` removeAllContainers(dockerClient); removeAllNetworks(dockerClient); removeAllVolumes(dockerClient); - // 4. network list 추출 - // default network`인지 확인하고 만약 아니라면 생성 syncNetworks(dockerClient, customHost.getCustomNetwork()); - - // 5. volume list 추출 - // volume 생성 syncVolumes(dockerClient, customHost.getCustomVolume()); - - // 6. container list 추출 - // 필요한 image를 확인하고 만약 image를 가지고 있지 않다면 image pull - // 타겟 네트워크에 container 실행 List> syncResult = syncContainers(dockerClient, customHost.getCustomNetwork()); containerResults.addAll(syncResult); @@ -107,6 +127,12 @@ public List> syncDockerWithBlueprintData(ProcessedData proce return containerResults; } + /** + * Check whether input networks settings are valid considering NAME, SUBNET, IP + * + * @param customNetworkList network list to be executed + * @throws CustomException if network settings are invalid + */ private void customNetworkValidationCheck(List customNetworkList) { for (CustomNetwork customNetwork : customNetworkList) { for (CustomConfig config : customNetwork.getCustomIpam().getCustomConfig()) { @@ -118,6 +144,13 @@ private void customNetworkValidationCheck(List customNetworkList) } } + /** + * Existing networks are left unchanged, and only newly added networks are created. + * + * @param dockerClient connection with Docker daemon + * @param customNetworkList network list to be executed + * @throws DockerException if any Docker-related operation fails + */ private void syncNetworks(DockerClient dockerClient, List customNetworkList) throws DockerException { customNetworkValidationCheck(customNetworkList); @@ -128,7 +161,6 @@ private void syncNetworks(DockerClient dockerClient, List customN boolean networkExists = existingNetworks.stream() .anyMatch(existingNetwork -> existingNetwork.getName().equals(customNetworkName)); - // default network 가 아닐 시 생성 if (!networkExists) { List ipamConfigList = new ArrayList<>(); @@ -148,6 +180,13 @@ private void syncNetworks(DockerClient dockerClient, List customN } + /** + * Existing volumes are left unchanged, and only newly added volumes are created. + * + * @param dockerClient connection with Docker daemon + * @param customVolumeList volume list to be executed + * @throws DockerException if any Docker-related operation fails + */ private void syncVolumes(DockerClient dockerClient, List customVolumeList) throws DockerException { List existingVolumes = dockerClient.listVolumesCmd().exec().getVolumes(); @@ -155,7 +194,6 @@ private void syncVolumes(DockerClient dockerClient, List customVol for (CustomVolume customVolume : customVolumeList) { String volumeName = customVolume.getName(); - // 볼륨이 이미 존재하는지 확인 boolean volumeExists = existingVolumes.stream() .anyMatch(existingVolume -> existingVolume.getName().equals(volumeName)); @@ -169,6 +207,24 @@ private void syncVolumes(DockerClient dockerClient, List customVol } + /** + * Creates containers by performing the following steps: + *
    + *
  1. Check if the required Docker image exists on the host.
  2. + *
  3. If the image does not exist, pull the image from Docker Hub.
  4. + *
  5. Set up ports, volumes, and mounts, and then create the containers.
  6. + *
+ * + *

This method ensures that each container is properly configured before starting. + * If any step fails, an appropriate exception is thrown.

+ * + * @param dockerClient the connection to the Docker daemon used to manage containers + * @param customNetworkList the list of networks containing container configurations to be executed + * @return a list of maps containing the results of the container creation process, + * including the container name, status, and any messages. + * @throws DockerException if any Docker-related operation fails + * @throws InterruptedException if pulling images is interrupted or delayed + */ private List> syncContainers(DockerClient dockerClient, List customNetworkList) throws DockerException, InterruptedException { @@ -184,20 +240,16 @@ private List> syncContainers(DockerClient dockerClient, List String imageName = customContainer.getCustomImage().getName(); String tag = customContainer.getCustomImage().getTag(); - // 이미지가 존재하는지 확인 try { dockerClient.inspectImageCmd(imageName).exec(); } catch (NotFoundException e) { - // 이미지가 없으면 pull dockerClient.pullImageCmd(imageName).withTag(tag).start().awaitCompletion(); } - // 포트 바인딩 설정 List portBindings = customContainer.getCustomPorts().stream() .map(customPort -> PortBinding.parse(customPort.getPublicPort() + ":" + customPort.getPrivatePort())) .collect(Collectors.toList()); - // 마운트 설정 List binds = new ArrayList<>(); List mounts = new ArrayList<>(); @@ -216,7 +268,6 @@ private List> syncContainers(DockerClient dockerClient, List } }); - // 포트 바인딩 및 볼륨 바인딩 설정 HostConfig hostConfig = HostConfig.newHostConfig() .withPortBindings(portBindings) .withBinds(binds) @@ -224,9 +275,8 @@ private List> syncContainers(DockerClient dockerClient, List ContainerNetwork containerNetwork = new ContainerNetwork() .withIpamConfig(new ContainerNetwork.Ipam()) - .withIpv4Address(customContainer.getCustomNetworkSettings().getIpAddress()); // IP 주소 설정 + .withIpv4Address(customContainer.getCustomNetworkSettings().getIpAddress()); - // 컨테이너 생성 CreateContainerResponse containerResponse = dockerClient.createContainerCmd(imageName) .withName(containerName) .withHostConfig(hostConfig) @@ -258,6 +308,12 @@ private List> syncContainers(DockerClient dockerClient, List return containerResults; } + /** + * Remove all containers except Docker default containers and Goraebab custom containers + * + * @param dockerClient connection with Docker daemon + * @throws DockerException if any Docker-related operation fails + */ private void removeAllContainers(DockerClient dockerClient) throws DockerException{ List containerList = dockerClient.listContainersCmd().withShowAll(true).exec(); @@ -281,6 +337,12 @@ private void removeAllContainers(DockerClient dockerClient) throws DockerExcepti } } + /** + * Remove all networks except Docker default networks and Goraebab custom network + * + * @param dockerClient connection with Docker daemon + * @throws DockerException if any Docker-related operation fails + */ private void removeAllNetworks(DockerClient dockerClient) throws DockerException{ List networkList = dockerClient.listNetworksCmd().exec(); @@ -292,10 +354,16 @@ private void removeAllNetworks(DockerClient dockerClient) throws DockerException } } + /** + * Retrieve all containers in execution and check whether volume is used by containers and + * remove all volumes except volumes not in use + * + * @param dockerClient connection with Docker daemon + * @throws DockerException if any Docker-related operation fails + */ private void removeAllVolumes(DockerClient dockerClient) throws DockerException{ List volumeList = dockerClient.listVolumesCmd().exec().getVolumes(); - // 사용중인 볼륨 목록 가져오기 (컨테이너 -> 볼륨) List runningContainers = dockerClient.listContainersCmd().exec(); Set usedVolumes = runningContainers.stream() .map(Container::getId) @@ -306,7 +374,6 @@ private void removeAllVolumes(DockerClient dockerClient) throws DockerException{ }) .collect(Collectors.toSet()); - // 사용중이지 않은 볼륨 삭제 for (InspectVolumeResponse volume : volumeList) { String volumeName = volume.getName(); if (!usedVolumes.contains(volumeName)) {