Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document how to get socket location for image building configuration with podman #34435

Closed
lazystone opened this issue Mar 2, 2023 · 9 comments
Assignees
Labels
type: documentation A documentation update
Milestone

Comments

@lazystone
Copy link

lazystone commented Mar 2, 2023

At the moment current documentation recommends this approach to configure PodMan:

tasks.named<BootBuildImage>("bootBuildImage") {
	docker {
		host.set("unix:///run/user/1000/podman/podman.sock")
		bindHostToBuilder.set(true)
	}
}

Where 1000 is an uid of a user, which is usually a 1000, but might be different in some cases.

So, more generic approach to configure PodMan(in theory it's also compatible with Docker) would be:

tasks.named<BootBuildImage>("bootBuildImage") {
    docker {
        fun String.runCommand(
            workingDir: File = File("."),
            timeoutAmount: Long = 60,
            timeoutUnit: TimeUnit = TimeUnit.SECONDS
        ): String? = runCatching {
            ProcessBuilder("\\s".toRegex().split(this))
                .directory(workingDir)
                .redirectOutput(ProcessBuilder.Redirect.PIPE)
                .redirectError(ProcessBuilder.Redirect.PIPE)
                .start().also { it.waitFor(timeoutAmount, timeoutUnit) }
                .inputStream.bufferedReader().readText().trim()
        }.onFailure { it.printStackTrace() }.getOrNull()

        val uid = "id -u".runCommand() ?: 0;
        val socketPath = "/run/user/$uid/podman/podman.sock";
        if (file(socketPath).exists()) {
            host.set("unix://$socketPath")
            bindHostToBuilder.set(true)
        }
    }
}

Which is ugly. It would be nice to move this logic inside of Spring Boot Gradle(and probably maven) plugins to eliminate that boilerplate from configs.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Mar 2, 2023
@mhalbritter
Copy link
Contributor

On my system, an env variable UID is populated, which can be used with Gradle. Would that be an acceptable workaround?

@mhalbritter mhalbritter added the status: waiting-for-feedback We need additional information before we can continue label Mar 2, 2023
@lazystone
Copy link
Author

There is something special about that variable:

# In terminal
echo ${UID}                            
1000

but System.getenv("UID") in java returns null.

I mean that it's possible to come up with some workarounds, but it would be much better if Spring Boot plugin could auto-detect PodMan.

@mhalbritter
Copy link
Contributor

Huh, you're right. It's not shown in env output, either. TIL.

@lazystone
Copy link
Author

lazystone commented Mar 2, 2023

I think it's set in shell(in bash or zsh for example) - not globally.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Mar 2, 2023
@scottfrederick
Copy link
Contributor

With podman installed, you can run the command podman info -f "{{.Host.RemoteSocket.Path}}") to get the socket that should be used to connect to it. With this, you can set the DOCKER_HOST environment variable that many tools will use to connect (for example, on Linux export DOCKER_HOST="unix://$(podman info -f "{{.Host.RemoteSocket.Path}}")").

That's enough for Spring Boot to use podman for downloading the builder and run images, as well as any configured buildpack images, since the Boot plugins will honor the DOCKER_HOST environment variable. The other part is that the processes running inside the builder image need to connect to the podman socket, which is what the docker.bindHostToBuilder option does. If you can set the DOCKER_HOST environment variable, then this would be as simple as checking for that in your build script and setting bindHostToBuilder accordingly (as this user is doing).

@lazystone Does this technique suit your needs?

@lazystone
Copy link
Author

Ok, that's way better than mine approach. But what would be a downside to do following by default inside the plugin?

val dockerHost = System.getenv("DOCKER_HOST")
if (dockerHost != null) {
    docker {
        host.set(dockerHost)
        bindHostToBuilder.set(true)
    }
}

I guess if DOCKER_HOST environment variable is defined, then it should be used by all sub-processes anyway?

@scottfrederick
Copy link
Contributor

scottfrederick commented Mar 2, 2023

I guess if DOCKER_HOST environment variable is defined, then it should be used by all sub-processes anyway?

That's not necessarily true. In the minikube example, it is necessary to set the address of the Docker host as a remote address (not a socket), but bindHostToBuilder is not required because minikube exposes the default /var/run/docker.sock socket location inside of running containers. This is dependent on how each Docker-like daemon chooses to implement things.

I think it would be good to add a note about the podman info command to the Boot documentation to make it more clear how you should get the value to provide to docker.host, but I'm not sure we can assume anything more than we currently do.

@scottfrederick scottfrederick added type: documentation A documentation update and removed status: waiting-for-triage An issue we've not yet triaged status: feedback-provided Feedback has been provided labels Mar 2, 2023
@scottfrederick scottfrederick changed the title Autodetect PodMan Document how to get socket location for image building configuration with podman Mar 2, 2023
@scottfrederick scottfrederick added this to the 2.7.x milestone Mar 2, 2023
@scottfrederick scottfrederick self-assigned this Mar 2, 2023
@lazystone
Copy link
Author

I'm not sure we can assume anything more than we currently do

I understand. The only problem as I see it: bootBuildImage "just works" with Docker, but for PodMan it requires a little bit of more effort, because docker integration looks for unix:///var/run/docker.sock by default but does not look for unix:///run/user/${UID}/podman/podman.sock as a fallback.

That could be not a problem in Spring Boot gradle/maven plugin per se, but in whatever library is used for docker integration.

My point is that bootBuildImage should "just work" with both Docker and PodMan - because if we don't look into special cases(like DOCKER_HOST is defined or minikube), then the only difference is that unix socket path.

But I don't insist - I can live with that workaround :)

@philwebb philwebb added the for: team-meeting An issue we'd like to discuss as a team to make progress label Mar 2, 2023
@scottfrederick scottfrederick modified the milestones: 2.7.x, 2.7.10 Mar 3, 2023
@scottfrederick
Copy link
Contributor

scottfrederick commented Mar 6, 2023

When discussing the idea of testing for fallback connections to a Docker-compatible daemon, we should also consider the Colima project, which provides another alternative similar in some ways to podman. Colima does not provide a CLI, but it's expected that the docker CLI is used with Colima. On Linux, the socket provided by Colima for connection to the daemon can be discovered using the command docker context inspect colima -f '{{.Endpoints.docker.Host}}'. A typical path for the socket is unix:///$HOME/.colima/docker.sock.

Setting the DOCKER_HOST environment variable to the socket location provided by Colima is sufficient for Spring Boot to interact with the Colima daemon (provided the daemon API is not secured with SSL/TLS), or the socket can be set explicitly in the build configuration with the docker.host parameter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: documentation A documentation update
Projects
None yet
Development

No branches or pull requests

5 participants