spring-projects / spring-boot

Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss.
https://spring.io/projects/spring-boot
Apache License 2.0
75.03k stars 40.66k forks source link

Add support for DevContainers #41692

Open dieter-medium opened 2 months ago

dieter-medium commented 2 months ago

I am using DevContainers in my development setup with Docker Compose, but I am encountering difficulties in integrating it seamlessly with Spring Boot's Docker Compose support. Specifically, my devcontainer.json configuration looks like this:

{
  "dockerComposeFile": [
    "../compose.yaml",
    "./compose.override.yaml"
  ],
  "mounts": [
    "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"
  ]
}

Due to this setup, I can't use Spring Boot's Docker Compose integration directly. Currently, I have to disable Docker Compose with:

spring.docker.compose.enabled=false

Then, I manually configure a DockerCompose bean:

@Bean
public DockerCompose dockerCompose() {
    return DockerCompose.get(
            DockerComposeFile.find(new File(".")),
            null,
            new HashSet<String>()
    );
}

While this allows me to get a list of all services, to obtain service connections, I need to copy and modify for instance RedisDockerComposeConnectionDetailsFactory, change some access modifiers, and tweak RunningService slightly.

Suggested Solution:

Benefits:

mhalbritter commented 2 months ago

Hello - I don't understand this code snippet where you re-define the DockerCompose bean. What should that achieve?

Can't you point Spring Boot to the compose.yaml file and this then takes care of the docker containers?

I see that you're using multiple files, which is handled by https://github.com/spring-projects/spring-boot/issues/41691

Regarding the mounts: I don't see a way to pass the mounts to the docker compose command, so I'm not sure what devcontainers is doing there under the hood.

Usually, mounts are done via volumes in Docker Compose.

It should be possible to rewrite the mounts from the devcontainer.json to the docker compose format.

With https://github.com/spring-projects/spring-boot/issues/41691 and the rewritten mounts, Spring Boot should already be able to support your workflow. Or did I miss something?

dieter-medium commented 2 months ago

Maybe it's not needed to redefine the bean.

Perhaps this demo repo https://github.com/dieter-medium/microfrontends/tree/master/spring-boot-devcontainer can shed some light on this issue. Please take a look at the config package.

Next week, I can go into more details.

Am 5. August 2024 10:49:57 MESZ schrieb Moritz Halbritter @.***>:

Hello - I don't understand this code snippet where you re-define the DockerCompose bean. What should that achieve?

Can't you point Spring Boot to the compose.yaml file and this then takes care of the docker containers?

I see that you're using multiple files, which is handled by https://github.com/spring-projects/spring-boot/issues/41691

Regarding the mounts: I don't see a way to pass the mounts to the docker compose command, so I'm not sure what devcontainers is doing there under the hood.

Usually, mounts are done via volumes in Docker Compose.

It should be possible to rewrite the mounts from the devcontainer.json to the docker compose format.

With https://github.com/spring-projects/spring-boot/issues/41691 and the rewritten mounts, Spring Boot should already be able to support your workflow. Or did I miss something?

-- Reply to this email directly or view it on GitHub: https://github.com/spring-projects/spring-boot/issues/41692#issuecomment-2268516901 You are receiving this because you authored the thread.

Message ID: @.***>

dieter-medium commented 2 months ago

I wanted to clarify my scenario in more detail.

With DevContainer, my Spring application runs inside a container. To access Docker from within this container, I have two options: mount the Docker socket inside the container or use Docker-in-Docker (dind). I prefer not to use dind for various reasons.

Therefore, I mount the Docker socket. Spring Boot Docker works fine as long as I don't mount any folder within my compose.yaml. The issue arises due to the mismatch of the filesystem layout inside and outside the container.

As a result, in cases where I mount folders within compose.yaml, I need to disable Spring Boot Docker and hand over Docker Compose control to DevContainer.

However, Spring Boot Docker Compose has excellent service connection support that I want to utilize. Unfortunately, I haven't been able to get it working out of the box.

One special aspect to consider is that DevContainer uses container networks, so no port mapping is needed. The services are accessible at their default ports on localhost, but the credentials and database details are dynamic, managed through a .env file.

Additionally, I need support for a second compose file to add labels to the containers. These labels would indicate that the containers are part of a container network, instructing Spring Boot Docker Compose to not look for port mappings and to expose the original port in the connection details.

At the moment, I need to copy some classes from Spring Boot Docker Compose because the needed classes from the service connection package are package-private.