#Can Dagger Mount Unix Sockets Cross Container?

1 messages · Page 1 of 1 (latest)

glass wagon
#

I have two containers I am trying to orchestrate with Dagger: call them producer and consumer. The consumer listens for HTTP traffic on a unix domain socket that it creates. This socket also orchestrates its termination. The producer "tees" the output of some process into HTTP messages into the domain socket.

Is there any way to share just the socket and not the containing directory? It's not a huge deal but was just curious

Example of one way that seems to work and one that does not https://gist.github.com/elee/03b4c4a9d4351e26ed9be5c4e69e55a4

Gist

Dagger With Socket Sharing. GitHub Gist: instantly share code, notes, and snippets.

pliant ether
pliant ether
glass wagon
#

Yeah.. I am using WithDirectory for something more sophisticated so.. stay tuned 😎

But that's helpful context, I may just fiddle with the workload to use a TCP socket in a different mode if I can't get it behave portably

glass wagon
#

For future generations: this actually didn't work. The side effects on mutating the Directory do not get shared between containers

pliant ether
#

if the service doesn't allow exposing via TCP, I guess you could also try:

  • Adding a Unix socket <> TCP proxy inside the service container. IIRC socat helps here.
  • Using cache volumes. This might work but it also probably has some side-effects given that cache volumes were not designed with this use-case in mind 🙏

cc @fallen oxide

glass wagon
#

I'm leaning towards having netcat forward the traffic to the unix socket listening service locally -- I think my WithExec will just be executing a small script to background the service and wire up nc on a port which I'll WithExposedPort

grand sky
#

Hi there, maybe someone has a good example how to run ssh-agent as service and mount socket cross containers?

slender totem
unkempt folio
# glass wagon I have two containers I am trying to orchestrate with Dagger: call them producer...

I am trying to do something similar. My usecase is rather more convoluted, but I think that by sharing sockets I would be able to make progress.

Basically during Docker builds from regular docker files it is possible to access the docker socket on host via host.docker.internal hostname. Within Dockerfile this hostnames binds to the localhost of the host, where container is built. Why would you want to do that? My reason is to run tests based on testcontainers as part of "docker build". Now I would like to build this Docker file with Dagger.

I have managed to start the Dockerd as service, and bind it as a service, but I am unable to expose it in the build step, which builds the Dockerfile.

I have tried running socat using with_exec(["/bin/sh", "-c", "socat <tcp all traffic on 2375 port> <to docker tcp on port 2375>"]) but that does not work, since command seems to simply exit or somehow otherwise terminate.

If I was able to mount the docker socket from the service into my container, then that would likely work.

pliant ether
#

Having said that, I'd personally recommend starting dockerd listening in a TCP socket instead of UDS so you don't have to rely on the cache volume stopgap

unkempt folio
#

Yeah, I used TCP socket, but to no avail. It is not possible to acces bound services during Docker build,even when I forward them to localhost via socat and try to access them via host.docker.internal hostname

pliant ether
#

Oh, you want to use services when building Dockerfiles? Yes, that won't work unfortunately

#

It's the same limitation that I've posted in the previous thread

unkempt folio
#

Not even via host.docker.internal? Could you link please to that discussion?

#

I posted that problem with details in general

pliant ether
#

We need to make Serviced work with Docker build basically

pliant ether
#

@unkempt folio here's a stopgap in Go to achieve what you need with DockerBuild

func (m *Lala) Test(src *dagger.Directory) *dagger.Container {

    ctx := context.Background()
    svc := dag.Container().From("nginx").WithExposedPort(80).AsService(dagger.ContainerAsServiceOpts{UseEntrypoint: true})

    svcIP, _ := dag.Container().From("alpine").
        WithServiceBinding("web", svc).
        WithExec([]string{"sh", "-c", "getent ahostsv4 web | tail -n 1 | cut  -d ' ' -f1"}).Stdout(ctx)

    return dag.Container().
        WithServiceBinding("web", svc).
        //From("alpine")
        Build(src, dagger.ContainerBuildOpts{BuildArgs: []dagger.BuildArg{{"NGINX_IP", svcIP}}})
}

^ what I'm doing there is basically getting the ip of the service, and then passing that as a BuildArg I can use in my Dockerfile afterwards like this:

FROM alpine
ARG NGINX_IP

RUN apk add curl bind-tools
RUN curl $NGINX_IP

It's not super clean but it does the job

unkempt folio
#

Thank you! I understand your solution. It is very nice of you that you went out of your way to write that up for me, I appreciate that!

I note that Dagger has very steep learning curve for me, because it is not at all transparent to me how it works, and "what is accessible" in my container. For example it was not at all clear to me that the building of Dockerfile steps can access the same IPs, as the container from which the build of Dockerfile was triggered, I assumed that build steps were executed in nested separate container with isolated network stack.

The documentation is very slim in that regard, and there are more than few "oddities", or situations where it is clear that there are multiple ways to do it, but it is not at all obvious which way was implemented in Dagger.

#

One more example of an oddity which I faced is chained "with_exec" calls in Python SDK. After one with_exec terminates, the process is not running anymore in the next with_exec. Yes, Services should be used for that, but it is relatively conceptually far away from how traditional CI scripts can be written.

pliant ether
#

when you're writing a Dagger pipieline you're basically composing steps within a pipeline that get executed in isolation but re-using the underlying FS that gets modified between the different steps. Again, same way as Dockerfiles

unkempt folio
#

Exactly! But that is not explained in docs. You can hear it in couple of Solomons talks, but it is not obvious.

#

I will open an issue for that tomorrow, maybe handle it myself

pliant ether
#

having said that we appreciate the feedback and we'll make sure to improve our docs based on it. cc @jolly notch

pliant ether
#

we're good at writing our issues, PRs and tests but we should defintiely improve our in-depth docs

unkempt folio
#

Note: I found almost no docs on how to work on jenkins plugins

pliant ether