Home / Class/ DockerComposeLifecycleManager Class — spring-boot Architecture

DockerComposeLifecycleManager Class — spring-boot Architecture

Architecture documentation for the DockerComposeLifecycleManager class in DockerComposeLifecycleManager.java from the spring-boot codebase.

Entity Profile

Relationship Graph

Source Code

core/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/lifecycle/DockerComposeLifecycleManager.java lines 54–184

class DockerComposeLifecycleManager {

	private static final Log logger = LogFactory.getLog(DockerComposeLifecycleManager.class);

	private static final String IGNORE_LABEL = "org.springframework.boot.ignore";

	private final @Nullable File workingDirectory;

	private final ApplicationContext applicationContext;

	private final @Nullable ClassLoader classLoader;

	private final SpringApplicationShutdownHandlers shutdownHandlers;

	private final DockerComposeProperties properties;

	private final Set<ApplicationListener<?>> eventListeners;

	private final DockerComposeSkipCheck skipCheck;

	private final ServiceReadinessChecks serviceReadinessChecks;

	DockerComposeLifecycleManager(ApplicationContext applicationContext,
			SpringApplicationShutdownHandlers shutdownHandlers, DockerComposeProperties properties,
			Set<ApplicationListener<?>> eventListeners) {
		this(null, applicationContext, shutdownHandlers, properties, eventListeners, new DockerComposeSkipCheck(),
				null);
	}

	DockerComposeLifecycleManager(@Nullable File workingDirectory, ApplicationContext applicationContext,
			SpringApplicationShutdownHandlers shutdownHandlers, DockerComposeProperties properties,
			Set<ApplicationListener<?>> eventListeners, DockerComposeSkipCheck skipCheck,
			@Nullable ServiceReadinessChecks serviceReadinessChecks) {
		this.workingDirectory = workingDirectory;
		this.applicationContext = applicationContext;
		this.classLoader = applicationContext.getClassLoader();
		this.shutdownHandlers = shutdownHandlers;
		this.properties = properties;
		this.eventListeners = eventListeners;
		this.skipCheck = skipCheck;
		this.serviceReadinessChecks = (serviceReadinessChecks != null) ? serviceReadinessChecks
				: new ServiceReadinessChecks(properties.getReadiness());
	}

	void start() {
		if (Boolean.getBoolean(AbstractAotProcessor.AOT_PROCESSING) || AotDetector.useGeneratedArtifacts()) {
			logger.trace("Docker Compose support disabled with AOT and native images");
			return;
		}
		if (!this.properties.isEnabled()) {
			logger.trace("Docker Compose support not enabled");
			return;
		}
		if (this.skipCheck.shouldSkip(this.classLoader, this.properties.getSkip())) {
			logger.trace("Docker Compose support skipped");
			return;
		}
		DockerComposeFile composeFile = getComposeFile();
		Set<String> activeProfiles = this.properties.getProfiles().getActive();
		List<String> arguments = this.properties.getArguments();
		DockerCompose dockerCompose = getDockerCompose(composeFile, activeProfiles, arguments);
		if (!dockerCompose.hasDefinedServices()) {
			logger.warn(LogMessage.format("No services defined in Docker Compose file %s with active profiles %s",
					composeFile, activeProfiles));
			return;
		}
		LifecycleManagement lifecycleManagement = this.properties.getLifecycleManagement();
		Start start = this.properties.getStart();
		Stop stop = this.properties.getStop();
		Wait wait = this.properties.getReadiness().getWait();
		List<RunningService> runningServices = dockerCompose.getRunningServices();
		if (lifecycleManagement.shouldStart()) {
			Skip skip = this.properties.getStart().getSkip();
			if (skip.shouldSkip(runningServices)) {
				logger.info(skip.getLogMessage());
			}
			else {
				start.getCommand().applyTo(dockerCompose, start.getLogLevel(), start.getArguments());
				runningServices = dockerCompose.getRunningServices();
				if (wait == Wait.ONLY_IF_STARTED) {
					wait = Wait.ALWAYS;
				}
				if (lifecycleManagement.shouldStop()) {
					this.shutdownHandlers
						.add(() -> stop.getCommand().applyTo(dockerCompose, stop.getTimeout(), stop.getArguments()));
				}
			}
		}
		List<RunningService> relevantServices = new ArrayList<>(runningServices);
		relevantServices.removeIf(this::isIgnored);
		if (wait == Wait.ALWAYS || wait == null) {
			this.serviceReadinessChecks.waitUntilReady(relevantServices);
		}
		publishEvent(new DockerComposeServicesReadyEvent(this.applicationContext, relevantServices));
	}

	protected DockerComposeFile getComposeFile() {
		DockerComposeFile composeFile = (CollectionUtils.isEmpty(this.properties.getFile()))
				? DockerComposeFile.find(this.workingDirectory) : DockerComposeFile.of(this.properties.getFile());
		Assert.state(composeFile != null, () -> "No Docker Compose file found in directory '%s'".formatted(
				((this.workingDirectory != null) ? this.workingDirectory : new File(".")).toPath().toAbsolutePath()));
		if (composeFile.getFiles().size() == 1) {
			logger.info(LogMessage.format("Using Docker Compose file %s", composeFile.getFiles().get(0)));
		}
		else {
			logger.info(LogMessage.format("Using Docker Compose files %s", composeFile.toString()));
		}
		return composeFile;
	}

	protected DockerCompose getDockerCompose(DockerComposeFile composeFile, Set<String> activeProfiles,
			List<String> arguments) {
		return DockerCompose.get(composeFile, this.properties.getHost(), activeProfiles, arguments);
	}

	private boolean isIgnored(RunningService service) {
		return service.labels().containsKey(IGNORE_LABEL);
	}

	/**
	 * Publish a {@link DockerComposeServicesReadyEvent} directly to the event listeners
	 * since we cannot call {@link ApplicationContext#publishEvent} this early.
	 * @param event the event to publish
	 */
	private void publishEvent(DockerComposeServicesReadyEvent event) {
		SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
		this.eventListeners.forEach(multicaster::addApplicationListener);
		multicaster.multicastEvent(event);
	}

}

Domain

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free