Version: spring-boot-docker-compose:3.1.2
I have created a project using spring-boot-docker-compose that lists three services (let's call them A, B, and C) in the compose.yml file. Everything works as expected on the first launch.
However, after the containers are created, if I manually start the container for service A using the Docker API (docker start $service_A_container_id), and then attempt to start the Spring application again without first stopping it, the spring-boot-docker-compose skips the container startup phase. This results in services B and C not being started correctly.
Upon inspecting the code, I found the cause of this issue lies in the condition used to determine whether the Docker API should be called in org.springframework.boot.docker.compose.lifecycle.DockerComposeLifecycleManager#start:
if (lifecycleManagement.shouldStart() && runningServices.isEmpty()){
...
}
This condition stipulates that no currently running services should be found.
I believe the startup phase should not be skipped in this scenario for the following reasons: 1. If the service I'm starting is a database, there are instances where I would want to connect to the database to inspect data without needing to start the entire application. This necessitates the ability to start the container independently. 2. The Docker-Compose API supports the restarting of already started containers. Hence, removing the restriction to skip startup wouldn't lead to any errors.
Comment From: wilkinsona
This behavior is intentional. We tried to clarify the documentation in https://github.com/spring-projects/spring-boot/issues/36483.
If the service I'm starting is a database, there are instances where I would want to connect to the database to inspect data without needing to start the entire application. This necessitates the ability to start the container independently.
You can still do this if you then stop the container before starting the app.
The Docker-Compose API supports the restarting of already started containers. Hence, removing the restriction to skip startup wouldn't lead to any errors.
That may not be what the user wants and restarting may lose a non-persistent change that had been made to the container.
If we want to support something in this area, I think we'd have to offer a configuration option and make restarting already running containers an opt-in feature.
Comment From: lianej
That may not be what the user wants and restarting may lose a non-persistent change that had been made to the container.
I agree.
Could we provide clearer error messages or warning log for services are partially running?
Comment From: wilkinsona
Spring Boot does not parse the compose YAML file so we don't know how many services should be running. All we can easily detect at the moment is that one or more services is running. Given this, I think an error or warning would be too much. We could perhaps log an info level message indicating that the services won't be started as one or more is already running. We'll discuss this as a team and decide what, if anything, we want to do.
Comment From: mhalbritter
We could use the compose config command to detect that not all defined services are running (we do that for org.springframework.boot.docker.compose.core.DefaultDockerCompose#hasDefinedServices). However, I don't think we should do that.
We could perhaps log an info level message indicating that the services won't be started as one or more is already running.
That's fine for me.
Comment From: rupert-jung-mw
ATM (Spring Boot 3.3.3), spring-docker-compose just ignores everything set in the specified docker-compose file, even if it's completely different. Just because there is any docker container already running. That is just very unexpected. It should just start all missing services and that's it?
Comment From: wilkinsona
Just because there is any docker container already running.
That's incorrect. The container has to be managed by the same Docker Compose YAML file as is being used by the app that's being started. Only then will the skipping occur.
Comment From: rupert-jung-mw
I did in fact use two different docker-compose files and the behavior was in fact the same... One was used by Spring (which was running in the background), the other one was used by integration test and was skipped unfortunately.
EDIT: I had to upgrade Spring to 3.3.0+ and then use the new property spring.docker.compose.start.skip set to 'never' to make it work.