#docker

1 messages Β· Page 1 of 1 (latest)

dense arrow
#

Will dagger parse cache vols in dockerfiles? or do I have to mount them explicitly with the sdk?

example
RUN --mount=type=cache,target=/var/cache/apt apt-get update

Corresponding dagger is pretty simple.

runtimeContainer := daggerClient.Container().Build(buildDir)
mint estuary
#

I can't recall how that worked exactly, but should be quite easy to try πŸ˜„

#

I assume it'd work automatically.. but can't be 100% sure

#

it works, just verified it quickly

dense arrow
#

Is there some way to check caching like this? Cache vols etc?

#

I see the "CACHED" in output, but tbh it's a little opaque where the cache comes from (vols or dagger/buildkit magic)

mint estuary
#

CACHED will always come from dagger

#

if you see a CACHED for the build op is because the Dockerfile didn't get re-executed

dense arrow
#

I guess it's not exactly relevant then if the cache is coming from a mounted volume?

#

That's moreso just a tweak to help handle the storage of the cache?

#

and to clarify I see cached on just that run step

mint estuary
#

if you see CACHED from the run step that means that it wasn't re-executed.

#

I think I got a bit lost about what your main doubt is

dense arrow
#

I guess I'm a little lost on what a cache volume actually does that's different from regular caching. I'll read up on it in buildkit docs - doesn't sound like a dagger thing

bright plinth
#

Cache volumes are directories that Dagger persists for you in between runs, in a best effort way. This allows application-specific caching to work properly in Dagger.

#

Just today @dim gyro suggested we could call them just "volumes"

#

which would maybe reduce confusion with the "other" dagger caching?

marsh wraith
#

I have a Podman build/run host going but finding building user-provided Dockerfiles from scratch in it each time takes quite a while - is there any way to utilize Dagger or another tool to automatically cache individual steps wihtin a dockerfile so subsequent runs wiht similr initial steps are faster? I saw the mode=max from the old version of Dagger and seemed along the lines of what I'm looking for

#

(Or alternatively is there a container dependency spec format like Dockerfile which Dagger could use and do that intermediate caching?)

mint estuary
marsh wraith
mint estuary
pulsar adder
#

I remember seeing a package that created dagger service containers from a docker compose file. Is that around somewhere or I was just dreaming?

Also, if it is around, does it support features like health checks? (ie. wait for containers to be healthy before running some actual tests)

desert thicket
cursive leaf
#

Question: Can Daggers Python SDK parse dockerfile snippets?

Im exploring an idea where Dagger creates a "base image" and our developers can use a partial Dockerfile to extend that base image

bright plinth
#

which will produce a container

#

but parsing without executing - no

dim gyro
neon void
#

πŸ‘‹ Hey folks. I'm trying to understand what's going on under the hood with Dagger and I feel like I'm missing something. The docs suggest that Dagger runs docker CLI commands. But as actions are running I don't see any containers running when I run docker ps other than the Dagger image registry. I assumed I would see something. What am I missing?

bright plinth
bright plinth
#

@neon void at the system level (linux cgroups, namespaces etc) you will see dagger-managed and docker-managed containers side by side

#

but actually I’m wondering if we could improve compat with docker specifically, by taking advantage of the fact that we share the underlying dependency on containerd.

neon void
bright plinth
neon void
#

do you have a repo or code snippet you

neon void
# bright plinth do you have a repo or code snippet you can share?

This is the repo: https://github.com/mattupstate/acme (it's a hobby project I teach myself things through) but there isn't any Dagger code in there yet. My first attempt looked like this

import { connect } from "@dagger.io/dagger"

connect(async (client) => {
    const mavenCache = client.cacheVolume("maven-cache")
    const gradleCache = client.cacheVolume("gradle-cache")

    const test = client.container().from("gradle:8.3.0-jdk17")
        .withUnixSocket("/var/run/docker.sock", client.host().unix_socket("/var/run/docker.sock"))
        .withMountedCache("/home/gradle/.m2", mavenCache)
        .withMountedCache("/home/gradle/.gradle", gradleCache)
        .withDirectory("/home/gradle", client.host().directory("."), { exclude: [".gradle/", "ci/", "node_modules/", "acme-app/acme-app-web/node_modules/"] })
        .withExec(["gradle", "test"]).stderr()
    
    console.log(test)

}, { LogOutput: process.stdout })

But that obviosly doesn't work since the containers aren't addressable from the gradle container. I tried running the docker engine as a service container but didn't really get anywhere with that either.

bright plinth
#

By passing insecureRootCapabilities as an option to WithExec

neon void
#

RIght, I gathered that much. I had something that looked like this:

import { connect } from "@dagger.io/dagger"

connect(async (client) => {
    const dockerEngine = client.container().from("docker:dind")
        .withExposedPort(2375)
        .withExec(["dockerd", "--host=tcp://0.0.0.0:2375"], { insecureRootCapabilities: true})

    const mavenCache = client.cacheVolume("maven-cache")
    const gradleCache = client.cacheVolume("gradle-cache")

    const test = client.container().from("gradle:8.3.0-jdk17")
        .withServiceBinding("docker", dockerEngine)
        .withMountedCache("/home/gradle/.m2", mavenCache)
        .withMountedCache(process.cwd() + "/.gradle", gradleCache)
        .withDirectory(process.cwd(), client.host().directory("."), { exclude: [".gradle/", "ci/", "node_modules/", "acme-app/acme-app-web/node_modules/"] })
        .withWorkdir(process.cwd())
        .withEnvVariable("DOCKER_HOST", "tcp://docker:2375")
        .withExec(["gradle", "test"]).stderr()
    
    console.log(test)

}, { LogOutput: process.stdout })

But I hit this error with testcontainers and kinda gave up after getting this error in the attachment

tiny jay
#

Hey, I'm also hitting my head when trying to give access to my CDK container to run Docker build. Any tips? Using Golang. Iterated with what there's above and ended up with this, but it's still complaining that Unable to execute 'docker'

package main

import (
    "context"
    "fmt"
    "os"
    "path"
    "path/filepath"

    "dagger.io/dagger"
)

const WORKDIR = "/app"

func main() {
    ctx := context.Background()

    // create Dagger client
    client, err := dagger.Connect(ctx, dagger.WithLogOutput(os.Stderr))

    if err != nil {
        panic(err)
    }
    defer client.Close()

    codePath, err := filepath.Abs("..")
    if err != nil {
        panic(err)
    }
    cdkDir := client.Host().Directory(codePath)

    dockerEngine := client.Container().From("docker:dind").
        WithExposedPort(2375).
        WithExec([]string{"dockerd", "--host=tcp://0.0.0.0:2375"}, dagger.ContainerWithExecOpts{InsecureRootCapabilities: true})

    ctr := client.Container().
        From("robertd/alpine-aws-cdk:2.99.0").
        WithServiceBinding("docker", dockerEngine).
        WithDirectory(WORKDIR, cdkDir).
        WithWorkdir(path.Join(WORKDIR, "infra")).
        WithUnixSocket("/var/run/docker.sock", client.Host().UnixSocket("/var/run/docker.sock")).
        WithEnvVariable("DOCKER_HOST", "tcp://docker:2375").
        WithEnvVariable("AWS_DEFAULT_REGION", "eu-north-1").
        WithEnvVariable("AWS_ACCESS_KEY_ID", os.Getenv("AWS_ACCESS_KEY_ID")).
        WithEnvVariable("AWS_SECRET_ACCESS_KEY", os.Getenv("AWS_SECRET_ACCESS_KEY")).
        WithExec([]string{"cdk", "deploy", "--all"})

    stdout, err := ctr.Stdout(ctx)
    fmt.Println(stdout)

    if err != nil {
        panic(err)
    }
}
latent pebble
#

Hey is there a way to pass --cgroupns host to the container at the moment? I need to access /sys/fs/cgroup from container

mint estuary
latent pebble
mint estuary
polar gyro
#

Hello I'd like to asks, I try to run dagger engine on docker container, and uses _EXPERIMENTAL_DAGGER_RUNNER_HOST env var. I'm following this comment to run the engine.

When I run it, the logs always return Unknown desc = server not found once, before succeeding. Is anyone know how to resolve it?

GitHub

What are you trying to do? I'm trying to achieve a workflow where dev machines could spin up dagger engine as the state can shared on buildkit. I would like to avoid using Docker to spin up Bui...

mint estuary
#

you can run the engine in docker as simple as: docker run -d --privileged --name dagger-engine registry.dagger.io/engine:v0.8.8

you can then set _EXPERIMENTAL_DAGGER_RUNNER_HOST=docker-container://dagger-engine and it should work

polar gyro
#

Ah yeah I think I didn’t explain me well
I run the engine manually with that command, but expose it via TCP instead. And that so what I’ve got

mint estuary
#

this worked for me:

docker run -d --privileged --name dagger-engine-779fedd2902d2511 -p 1111:1111  registry.dagger.io/engine:v0.8.8 --addr tcp://0.0.0.0:1111

_EXPERIMENTAL_DAGGER_RUNNER_HOST=tcp://0.0.0.0:1111 dagger run go run main.go
polar gyro
#
➜ _EXPERIMENTAL_DAGGER_RUNNER_HOST=tcp://private-ip:1234 go test -v
=== RUN   TestStructure
Creating new Engine session... OK!
Establishing connection to Engine... 1: connect
1: > in init
1: starting engine 
1: starting engine [0.10s]
1: starting session 
1: [0.14s] Failed to connect; retrying... name:"error" value:"make request: Post \"http://dagger/query\": rpc error: code = Unknown desc = server \"abneknncwm0x16252f0lm9f5i\" not found"
1: [0.28s] OK!
1: starting session [0.18s]
1: connect DONE
OK!
#

The execution is done, no error at the end, but the logs always come like this.

mint estuary
#

but the pipeline works

polar gyro
#

Thanks for link it up back πŸ‘

cold glen
#

πŸ‘‹ i am looking for host network equivalent in dagger. docker run/build --network host using Go SDK. anyone know how? ty

cold glen
bright plinth
# cold glen I did go through that doc. The trouble is I am using tailscale and the image pul...

sorry for the slow response, I am at Kubecon at the moment. If I understand correctly, your host machine is on the tailscale network, and your docker build requires access to that network so it can pull an image.

Dagger doesn’t support the equivalent of docker build β€”network host. But there are a few options:

  1. You could run tailscale in a container, managed by dagger, and maybe we can find a way to hook that up to the dockerBuild call. Perhaps we could add a service binding call? @heavy garden @hard sundial @dusk ridge

  2. if it’s an option, consider replacing that Dockerfile with a pure Go implementation, then you can definitely hook up tailscale for your image pull

dusk ridge
mint estuary
#

I was chatting with Solomon about this and I have the theory that the problem here is not networking per-se but DNS (of course, it always is). Since tailscale ruining on the host only sets up a tun device and modifies routing tables accordingly. It also modifies the host resolv.conf file by adding their special 100.100.100.100 DNS entry for their magic DNS thingy. I have a hunch that what's happening here is that dagger containers are not getting set the correct DNS server and therefore they can't resolve the proper IP so they're routed through the tailnet. I'll give it a try next week to validate this.

bright plinth
mint estuary
bright plinth
mint estuary
#

Stateless as the dagger-engine process stops once the pipeline finishes

mint estuary
#

Thing is because we run it containerized (and long living) locally, these weird networking drifts are exposed.

rough peak
#

Hey πŸ‘‹, I have an existing set of integration tests that are using testcontainers-go and I'm migrating our automation tooling to use dagger. Test containers is spinning up lots of containers on dynamic ports that the test are then connecting to. Because I don't know the ports that the containers will be running on ahead of time I cannot mount the host's docker socket and map the ports. I've ended up using docker in docker (docker:dind) to get this to work with various hacks. Just wondering if there's a better way to approach this that doesn't require migrating the tests to dagger services as well?? Thanks!

latent pebble
dim gyro
rough peak
latent pebble
rough peak
#

Hey @latent pebble , just an update. So using your dind module worked to allow the tests (and testcontainers-go) to talk to the Docker daemon. However, once the containers (e.g. Redis) were spun up the tests could not reach their exposed ports as Dagger doesn't know those ports in advance and thus can't map them. Given test containers randomly allocates these ports at runtime I'm not sure how I could wrap them in a service either without dropping test containers and using Dagger instead so I've had to stick with running everything (tests + docker) inside the same container which is proving pretty slow and flakey.

latent pebble
#

This could give an idea to how to continue

rough peak
#

Thanks, so I'm using Dagger to ultimately invoke a go test command that has some setup using testcontainers-go. I've updated those test so when we build the config for our services off the containers we use the container IP and no port mapping. The test containers are running on the bridge network. I'm getting the error dial tcp 172.17.0.15:3306: connect: no route to host from the tests. Is there anything Dagger specific I should be doing to allow the tests that are executing in a container created by Dagger to connect to those containers created by test containers on the bridge network? Appreciate your help! πŸ™

bright plinth
hard sundial
# bright plinth <@108011715077091328> we may need your help on this…

This is probably worth a guide/cookbook/something in the docs, seems like a lot of people are trying to do it. cc @uncut mason (Also doesn't Airbyte do this? I know they use dind and TestContainers but can't find where the two fingers on the Sistine Chapel meet... https://github.com/airbytehq/airbyte/blob/ea5e4bf07de4ec2d366c4013d2f487f2ece91606/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/system/docker.py#L30)

@rough peak Dagger's container-to-container networking doesn't need to map ports upfront; it's all just over DNS/IP. If there's some way to configure TestContainers to expose service ports to the dind container, they'll be reachable via the service's address (or alias) as long as those ports are listening on 0.0.0.0. You should just need to take the IP:port returned by TestContainers and swap the host portion out for either your WithServiceBinding("<alias>", dind) alias or dind.Hostname(). I'm not super familiar with using TestContainers but that seems like the best bet.

rough peak
#

Thanks everyone πŸ™. I got it working, the key was updating the tests to use the service alias for the hostname which I hadn't appreciated would resolve from the tests.

hard sundial
serene tulip
rough peak
#

one thing I have noticed with using Dagger + TestContainer is when running test suites in parellel (each that are using test containers) I get flakey behavior and some testcontainers fail to be created. Explicitly running with -p=1 works consistently though

lethal rampart
#

My coworker and I are working through an interesting issue. We want to be able to select the tag we use for our build container using a docker build arg.

We wrote the following typescript and Dockerfile.

import { connect } from "https://esm.sh/@dagger.io/dagger@0.9.3";
import path from "node:path";
import { fileURLToPath } from "node:url";
import process from "node:process";

const projectDir = path.resolve(fileURLToPath(import.meta.url), `../..`);

const buildTag = Deno.env.get("BUILD_TAG") || "latest";

connect(
  async (client) => {
    const source = client.host().directory(projectDir);

    console.log(`Building with alpine:${buildTag}`);

    await source
      .dockerBuild({
        buildArgs: [
          {
            name: "BUILD_TAG",
            value: "3.14.2",
          },
        ],
      })
      .stdout();
  },
  {
    LogOutput: process.stdout,
  },
);
ARG BUILD_TAG

FROM alpine:${BUILD_TAG} as build

RUN echo "Build TAG: ${BUILD_TAG}"

This docker file works in docker but not when using dagger.

#

The build arg is just not populated.

lethal rampart
#

Seems like we should just maybe refactor to remove the dockerfile.

shy radish
#

@lethal rampart I think you could def refactor to remove the Dockerfile, but could you tell me, how are your running this with deno?

I'm super interested in what your final command line invocation looks like πŸ™‚

lethal rampart
shy radish
#

I was entertained as deno asked me for each permission for file-read, file-write, env-read, etc

#

works!

shy radish
#

My adjusted file.ts

import { connect } from "https://esm.sh/@dagger.io/dagger@0.9.3";
import path from "node:path";
import { fileURLToPath } from "node:url";
import process from "node:process";

const buildTag = Deno.env.get("BUILD_TAG") || "latest";

connect(
  async (client) => {
    const source = client.host().directory(".");

    console.log(`Building with alpine:${buildTag}`);

    await source
      .dockerBuild({
        buildArgs: [
          {
            name: "BUILD_TAG",
            value: "3.14.2",
          },
        ],
      })
      .stdout();
  },
  {
    LogOutput: process.stdout,
  },
);
#

My simple project:

Dockerfile
file.ts
viscid basin
#

For the goal of having an identical build pipeline between CI & local, one area where Dagger has been falling short for me container artifacts. With pretty much all of my pipelines, the end result is a container. Testing locally, I obviously don't want to publish that to our company registry. I've been using the container export, but it's pretty inconvenient - spitting out a tar that needs to be imported and tagged on the host. One possibility I'm considering is writing a "helper" function that eliminates some of that inconvenience, but I want to pursue another option first.

Publishing to a local registry is obviously going to be a lot simpler and more consistent between local & CI runs. My only hesitation in just going for it is I don't want these images stored on my disk twice over - once in the registry, once in Docker/Podman itself. This got me thinking, there's got to be a way to use the "Docker/Podman itself" storage as a registry. So, at the moment, I'm searching through GitHub and Google, trying to find such a thing, and somewhat surprised that I'm at a loss so far.

Has anybody ever come across anything like that? Is it possible to have Dagger push the final image into the host's OCI image storage as if it were a registry? Or is there some other solution and I'm going about this the wrong way?

dusk ridge
#

Each container runtime will have a different way to import images - so if we implemented something like DockerImport in dagger, then it would just work for dagger/similar commands.
Also worth keeping in mind that the image store that docker uses out-of-the-box is quite bad for storing images (yes, that's weird) - it mutates image digests, it removes OCI annotations, it can't handle multi-platform, etc. Thankfully, that's changing with https://github.com/docker/roadmap/issues/371 (just a side note, maybe it affects you wanting to import to docker).

GitHub

Tell us about your request Docker started the containerd project with the plan for the Docker Engine to be migrated to use it. The Docker Engine already uses containerd to manage container lifecycl...

green laurel
#

Push to local registry

bright plinth
#

@viscid basin I think the upcoming Zenith release will help with this. It introduces a concept of Dagger Function, which lets you break down your pipeline logic into discrete units with clear inputs and outputs. So instead of trying to make the entire pipeline the same across CI and dev, you would simply call the same functions, with slightly different inputs or outputs connected

steady timber
#

Is there a way to get around DinD? using kaniko or whatever else?

shy radish
viscid basin
#

Dagger-in-Docker should be possible with normal (not Kubernetes) Docker/Podman, and without a docker cli binary, right? From everything I've read it seems like it should work but I must be missing some detail. I have the socket piped into the container via a host service. .withExec['curl'...] can communicate with my Podman socket successfully, but .withExec['sh', '-c', 'echo ... | dagger query'] hangs forever on Dagger trying to connect to the engine. I have _EXPERIMENTAL_DAGGER_RUNNER_HOST = "docker-container://dagger-engine.dev", and this is confirmed to echo out properly in the withExec as well.

stark dragon
#

hi, maybe it is a dumb question... but here it is
what I like about docker is that is kind become a standard, but I have the impression that with dagger we should do without a Dockerfile nor docker compose / docker buildx bake πŸ€” did I get it wrong? is it possible or advised to keep them / use them in dagger?

bright plinth
# stark dragon hi, maybe it is a dumb question... but here it is what I like about docker is th...

Dagger is designed to adapt to you πŸ™‚

So if you have Dockerfiles and want to use them, it's perfectly fine to do so, and we have native Dockerfile compatibility in the Dagger API to make that easy.

In other cases, Dockerfiles are just not powerful enough to express your build logic, and it's better to orchestrate your build as code.

Both are equally find, and supported.

I hope this helps!

stark dragon
shy radish
bright plinth
#

Sorry for missing this!

Personally yes, with Functions support now shipped, I would start my new project with pure Dagger from the beginning. Granted I am already comfortable with it πŸ™‚

#

So my baseline would be pure Dagger, and I would then accommodate other constraints in a pragmatic fashion: my teammate's preference for certain tools, pre-existing stack, etc

minor tapir
#

Out of curiosity I searched for "Dagger Service Containers" and ended up here with a warning that the documentation is updated: https://archive.docs.dagger.io/0.9/757394/use-services/

Is there an equivalent page in the current docs?

Dagger v0.9.0 includes a breaking change for binding service containers. The Container.withServiceBinding API now takes a Service instead of a Container, so you must call Container.asService on its argument. See the section on binding service containers for examples.

bright plinth
#

You can follow the guide as-is, you'll just need to replace the main() function from your own Dagger Function in the examples, and it works the same.

minor tapir
#

Awesome, thanks for the speedy reply πŸ’–

violet marsh
#

Is there something like docker compose for dagger, so we can easily "as-service up" multiple services?

dim gyro
#

Is there something like docker compose

leaden scarab
#

Hi there, I'm trying to replace our docker-compose file with a dagger script(not using functions for this). We use postgres:16-alpine with an extra init-database.sh script. The problem I have is that the healtcheck succeeds as soon as postgress is running so my tests starts but the init-database.sh script isn't finished.

#

I saw there isn't support for custom healthchecks yet, but is there any other way to delay the service being used?

bright plinth
leaden scarab
leaden scarab
#

I have another question.. We spin up an openstack cluster in a single vm using a templated image that contains kolla-ansible. We don't have a DNS server with api available so we pull some dns tricks in /etc/hosts and --add-hosts to make it work. Since every pipeline spins up its own openstack instance the ip changes(but the dns record stays the same). Currently I'm solving this by starting up a dagger engine per pipeline: docker run -d --add-host=openstack-lab.company.net:${ip_address} --privileged --name dagger-${ip_address} registry.dagger.io/engine:v0.11.4. But that is not a great solution due to not being able to reuse the cache etc. Is there a way to add dns entries to dag.Containers()?

bright plinth
#

Yes you can pass a host service as argument to your function, and attach it to a container with Container.WithServiceBinding

#

Dagger's Service type can be backed either by a container, or by a tunnel to a service in the client's context

#

you need a static set of ports to forward though. do you have that with openstack?

leaden scarab
bright plinth
#

no it can be remote, as long as it's reachable on the client's network

leaden scarab
#

aah

bright plinth
#

dagger call myfunc --openstack-server=tcp://1.2.3.4:4242

#

the CLI will translate that url to a Service object backed by a tunnel

#

I don't know if the single port is a limitation of the engine's tunnel API, or of the CLI

leaden scarab
#

(I'm not using functions, since we're on gitea and thus can't pull modules directly. So still just running from a single file. But think I get the idea)

#

Is it possible to forward to the same host on multiple ports?

bright plinth
bright plinth
#

That is what the dagger call CLI does under the hood

#

You can also find the API reference for your SDK of choice

leaden scarab
#

awesome thanks! Think this should do the trick. If this works I should probably record something for #1075928318802657340 . We(safespring.com) are doing something pretty cool here. we've build an api around openstack and okd as a kind of self-service project. We can connect multiple openstack sites and okd clusters to it and have customers manage all their stuff(projects, quota's, users) from a single api. I'm working on getting the code tested against a full openstack cluster on every change while keeping the ci/cd times minimal.

bright plinth
#

That sounds very cool. Yes you should absolutely show it at a community call!

leaden scarab
#

yes. call dag.Host().Service(). See

lone cypress
#

Is there any documentation around how dagger's caching is better than docker's standard caching? I'm just assuming it is...maybe its not? πŸ™‚ I see things like

Caching by default: Dagger caches everything. Expect 2x to 10x speed-ups.
but I'm looking for info around how its better/what makes it better.

#

Ah when I searched again I got more hits and I think this answers my question

The layers cache: This caches build instructions and the results of withExec() API calls. It is implemented by Buildkit.

dim gyro
teal burrow
ember smelt
#

Hey, I have a question.
I am in the process of converting some GitHub Workflow actions+scripts to some Dagger modules.

Specifically for creating OCI containers I am a bit confused.
It seems that Dagger Containers are very similar to traditional Docker containers.
However, for a Container that is not meant to be constructed and used in a Dagger function, but rather built and published so that it can run somewhere, I am missing or perhaps just misunderstanding a few things.
Am I supposed to still use docker build or such for this, or should I be able to use Dagger Containers?
If I should be able to use Dagger Containers, how do I add health checks and metadata? Also, it seems Entrypoint works slightly different than a Dockerfile ENTRYPOINT.

bright plinth
bright plinth
#

the only difference with entrypoint is that Dagger doesn't need it when running a container, because being programmable, you can just implement the same thing directly in code. Same idea for healthcheck, onbuild.. Those are stopgaps to compensate for Docker not being properly programmable.

That said we should have full support for those OCI fields so that Dagger can build any image.

ember smelt
# bright plinth the only difference with entrypoint is that Dagger doesn't need it when running ...

Thanks for you answers.
What I meant with Entrypoint behaving slightly different, is based on how I understand Dockerfile vs Dagger Container.
For Dockerfile, ENTRYPOINT is combined with CMD, or docker run args, to form the runtime command.
Dockerfile also has RUN which does not utilize ENTRYPOINT.
On the other hand, Dagger Container combines Entrypoint and WithExec, into what I would say roughly corresponds to RUN in Dockerfile.
However, when a Dagger Container is turned into a Dagger Service, the last WithExec becomes the runtime command (sort of like CMD).
I just wanted to highlight my confusion around these concepts.

timber jungle
#

When i was also working with understanding WithExec, WithoutEntrypoint etc etc. I came into a similiar situation as you @ember smelt

#

I wonder if a sort of "matrix/grid" like table that helps describe behavioural differences which may help people understand and migrate from docker to dagger easier?

green laurel
muted sundial
#

hey folks, how do i use a local docker image in a Container.From invocation?

#

it keeps prepending docker hub

#

oof... just read that it's not supported by design

bright plinth
#

@muted sundial it's not supported in the core but you can do it yourself in code (written by you, or by another module). It's a very common use case.

muted sundial
#

probably easiest for me right now is to just mirror gcr in the engine config

bright plinth
#

General idea: you run the docker CLI in a container, with your local engine's unix socket passed as an argument. Then you translate container content back and forth with the likes of docker load and docker save

#

there are several dagger modules that implement this

muted sundial
#

makes sense

#

thank you

bright plinth
#

Note that until very recently, you couldn't pass a unix socket as argument to the CLI. So these modules focused on running an ephemeral docker engine in Dagger (yes you can do that too). That is very useful in many docker integration scenarios, but not what you're looking for in this case. Most of the logic orchestrating the docker CLI in a container is the same

#

@hard sundial @heavy garden can a Service be backed by a unix socket? If not, in this case I would probably still run a tcp-to-unix proxy in the container. Then the containerized Docker CLI is always configured to talk TCP.

finite pelican
charred tide
finite pelican
charred tide
#

Just for vanilla usage of devcontainer that may be enough. But if you wanted to "live-reload" something that devcontainers is hosting it may not be enough. The devcontainers CLI will have to support it. VSCode extension of devcontainers supports that. Maybe you can host the code-server and proxy that port. I've used devcontainers but by no means an expert on it.

finite pelican
charred tide
#

I have not.

finite pelican
charred tide
finite pelican
crisp blade
#

Is there an equivalent of ADD --link foo.tar to provide whole layer tarballs to dagger to build an image?

bright plinth
#

I'm not super familiar with it, but it looks like a hack to work around the lack of real programmability.

#

Since Dagger is programmable, you can just use variables and arguments to pass different directory or container states around

#

(but it's possible that I'm missing something)

crisp blade
#

Maybe --link is a distraction, but we already generate layer tarballs (with bazel) so I'm wondering how that would fit in with dagger

#

I'm totally new to dagger, just trying to get a feel for what it would replace of our existing stack

dusk ridge
#

the link is all automatic fyi - it uses MergeOp internally in buildkit, which is the same underlying operation as dagger's WithDirectory

crisp blade
#

Ah cool

#

Like the goal is to make a docker image that contains a bunch of python, some c++ python extensions and some java

bright plinth
#

@dusk ridge @crisp blade the part I'm not sure I understand, is the reference to foo.tar, and to layer tarballs. I don't think COPY --link handles layer tarballs in any special way. And although Dagger has the ability to export an OCI tarball, I'm not it supports importing one

crisp blade
#

My concern is about changes to one layer causing a change to the hash of every subsequent layer, resulting in large uploads for a relatively small change when pushing the image

bright plinth
#

Generally you only need to worry about this kind of "mass cache invalidation" when chaining lots of exec operations (withExec in the Dagger API) in a naive way.

crisp blade
#

Cool I’ll give it a shot

rocky spoke
#

Hey all! Checking out dagger for a work project, trying to daggerize an existing docker-compose file. One of the containers brought up is a mongodb container, and we use the docker compose health check thing to wait for it to be up before starting other apps

Does something like this exist in dagger? Waiting for one container to finish initializing? I havent found anything like it in the docs, I may be searching for the wrong thing

bright plinth
rocky spoke
#

Awesome! Thank you!

granite mason
#

Hi πŸ‘‹
I'm looking through the cookbook and I'm trying to simply build a docker image (using a Dockerfile) without publishing it, is it possible?
I have no problem building the image but I feel like I'm missing something to "write" it without publishing it (basically, doing a docker build -t name:tag.
EDIT: I'm realizing I might be trying to use dagger to do something it's not intended for πŸ€”

dusk ridge
#

essentially, you just need to export the container to a file, and then you can docker load that in

granite mason
#

Indeed ! Thanks a lot, I don't know how I missed that!

pure tusk
#

I'm sure this is a FAQ, but I swear I could not find an answer. Dagger integrated in Azure pipeline: I cannot use curl to download it. I was thinking to running dagger as a docker container. Is this possible? I could not find the right image to use.

bright plinth
#

Either way, the engine will run in a container - and either way, that container needs to be privileged, so that it can run more containers

pure tusk
#

@bright plinth Little suggestion: I would include 1 in the How to install documentation: finding that the image to use is registry.dagger.io/engine is not immediate

#

Would you mind helping me translate dagger call container-echo --string-arg="hello, world!" to docker run .... ? Or, would you address me to the documentation page about it?

pure tusk
#

Last one I tried is docker run --privileged --entrypoint=dagger registry.dagger.io/engine call container-echo --string-arg="hello" but it does not seem to work.

bright plinth
#

@pure tusk if you are trying to load a local module, the container will not be able to access it. For local use I recommend using the CLI directly. The docker image is for server-side use, eg. deploying dagger in your self-hosted CI cluster. Any reason you don't want to use the CLI directly?

calm plinth
#

Is there a way to inspect an actually running container in dagger? The usual container resource as a just-in-time resource does allow inspecting files, ENVs, ARGs etc., but I didnt find a way to check what processes would actually run in it.
While obviously container shouldn't be used as a VM I have to interact with some VM-like containers, where I need to check that all expected processes ( πŸ™ˆ ) are actually running.

#

service container do run, but as far as I understood the documentation you cannot execute arbitatrary commands like ps aux inside of them

pliant canopy
#

Not sure if it's the best channel to ask but is there a way to append to RUN stanzas that match a certain signature or even the ability to specify exact matches on the lines as part of a DockerBuild(). Use case is consuming Dockerfiles I don't own but want to publish. Mostly I want to clean up after apt install, make install, pyc artifacts, etc so the layers are lighter and not carrying a bunch of intermediate work files.

#

Example in original:

RUN python3 -m venv /app/venv && \
    . /app/venv/bin/activate && \
    pip install --no-cache-dir -r requirements.txt --extra-index-url https://download.pytorch.org/whl/nvidia-cudnn-cu12

Rewritten to something that is effectively does clean up in the layer:

RUN python3 -m venv /app/venv && \
    . /app/venv/bin/activate && \
    pip install --no-cache-dir -r requirements.txt --extra-index-url https://download.pytorch.org/whl/nvidia-cudnn-cu12 && \
    rm -rf /root/.cache/pip && \
    find / -type d -name '__pycache__' -exec rm -rf {} + && \
    find / -type f -name '*.pyc' -delete
charred tide
#

I don't think there's a way to do that other than download the dockerfile and modify it. Maybe you could translate those dockerfiles into dagger calls?

dim gyro
#
return (
  dag.container().from_("original")
  .with_exec(["rm", "-rf", "/root/.cache/pip"])
  .with_exec ...
)
pliant canopy
#

Yea it would be neat if you could specify DockerFile instead of DockerBuild and rewrite it and then call Build

dim gyro
#

Sure, but in this case if you're just running more things at the end, is there a difference?

pliant canopy
#

@dim gyro wouldn't that still leave the earlier layer "fat"?

#

Python virtual envs are probably not the ideal example as you can copy forward the venv to another container. apt list/cache cleanup and object files from a make install might be a better example if it's spreading artifacts at various points in the container.

sharp trellis
#

Does dagger support buildkit syntax 1.6+? Tried to run it against a dockerfile with a heredoc and it didn't work. Saw in the go source code it's a generic major version but that's the only reference

https://github.com/dagger/dagger/blob/main/core/integration/container_test.go#L287

https://www.docker.com/blog/introduction-to-heredocs-in-dockerfiles/

Learn from Docker experts to simplify and advance your app development and management with Docker. Stay up to date on Docker events and new version

GitHub

An engine to run your pipelines in containers. Contribute to dagger/dagger development by creating an account on GitHub.

sharp trellis
#

Introduction to heredocs in Dockerfiles ...

pliant canopy
bright plinth
pliant canopy
#

Done let me know if you want anymore details.

pliant canopy
clever verge
#

stupid question, i am almost done converting a pretty complex docker setup to dagger and it's very cool! how do I migrate the dockerfile VOLUME instruction to dagger though? https://docs.docker.com/reference/dockerfile/#volume

Docker Documentation

Find all the available commands you can use in a Dockerfile and learn how to use them, including COPY, ARG, ENTRYPOINT, and more.

clever verge
charred tide
clever verge
charred tide
#

it populates the volume with the contents of the docker container.
Sounds like a CacheVolume? Dagger supports that too.

clever verge
bright plinth
#

Yeah if I remember correctly:

  • VOLUME simply adds metadata to the final OCI image?
  • Cache volumes are more like mount options in Dockerfile RUN
clever verge
bright plinth
#

Yup!

#

The only issue will be what to call it, to avoid confusing people

#

Maybe we'll tuck it under withOCIConfig or something

#

withVolume looks like you're actually attaching a volume to the live container

clever verge
#

i am not opposed to that. VOLUME is for sure confusing

charred tide
#

Not being familiar with VOLUME thoroughly threw me off

bright plinth
#

I love these conversations because I still remember the IRC conversations we had 10+ years ago when designing these keywords πŸ˜›

clever verge
#

i have a problem. I am pretty much done with transitioning our stuff to dagger. I am using a remote engine with _EXPERIMENTAL_DAGGER_RUNNER_HOST, but running .export(/tmp/test.tar) on the finished container, the tar is nowhere to be found. it's a bit unclear where I should expect it in the first place: on the dev machine or the remote machine, but it's in neither place.

#

oh wait I just tried simply returning the container and then piping to the export function in dagger shell and that works

#

but the question remains why it doesn't work in the typescript sdk

#

(yes I am awaiting the promise)

charred tide
#

Hey @clever verge , what you are seeing is the expected behavior. You can't export anything from code to your host machine unless you do the --export or -o from the dagger CLI. There is no implicit export. When you do .export from the code, it exports to a folder inside the module runtime (container) and will not be available on your host. It's a tradeoff made to maintain the sandbox.

uncut mason
#

OK, I'll make that clearer, opening a ticket for it

clever verge
clever verge
#

mhm we also have a CI step where we run some smoketest on our built containers. it would be nice to do this directly with dagger, but there doesn't seem to be a good way to run containers and to then interact with that container. i know that dagger is for building containers and not for running them, still it would be nice

amber basin
amber basin
# clever verge mhm we also have a CI step where we run some smoketest on our built containers. ...

You could add/make a new function (e.g. smoketest/qa) that takes that built image address, dagger.Container, or dagger.Service and interact with a given set of instructions (e.g. ping this endpoint, this file should exist at this path). Or depending on your needs, might be worth adding a QA style agent with the new LLM integration to let it run checks based on a prompt? https://docs.dagger.io/features/llm

clever verge
amber basin
clever verge
amber basin
clever verge
#

Thanks for the pointers!

#

I am still too much in the docker mindset

amber basin
clever verge
amber basin
clever verge
#

alright! glad it's already being considered!

clever verge
#

is it possible to not start a service (withServiceBinding) when the layer that needs the service is cached? wastes quite a few seconds on every run (as it waits for the service to be healthy)

daring prairie
#

Hi all,

I'm working on a Dagger module that scans a local container image using sysdig-cli-scanner. How can I pass a local Docker image without Dagger trying to pull it from a registry?

My current workaround is for the function to take a .tar file instead that it can then scan.

charred tide
charred tide
daring prairie
#

@charred tide Just saw the message after posting mine here. The sysdig-cli-scanner can also use a tarball. However, when I tried updating the method to take a *dagger.Container and then always mount the tarball using Container.AsTarBall, and then running my scan on that, it seemed that Dagger would still always pull the image from a registry instead of using my local image.

If everything we did used Dagger, I think this would work. But since we are still new to using Dagger, it needs to be used with our existing workflows that build a Docker image locally and then run the scan on that.

Currently, I was planning on using docker save before calling the Dagger module so that I can just pass the .tar file instead of a container. But I was hoping it was possible to pass a local Docker image as a *dagger.Container.

charred tide
daring prairie
viscid bear
#

Is there an easy way to create a dagger container from a locally built docker image? I've done some research but have what seems like conflicting information and various approaches I've tried have not worked. Can anyone point me in the right direction? Basically I would love to do container | from my-pre-built-image but if I need to do something extra that is fine, but ideally the simplest approach to do some adhoc testing with dagger on that image. NOTE: I'd prefer not to use a registry or build the docker file with dagger since I have a pre-existing docker bake setup I'd like to re-use for now.

cedar gust
viscid bear
cedar gust
graceful kelp
mossy monolith
#

Hey good people of Dagger! After today's talk by @bright plinth I figured I need to see if anybody in the Dagger community has been playing with integrating inference servers into the Dagger pipelines. Lo and behold https://dagger.io/blog/docker-model-runner this was a good starting point. However, Docker model runner is but a tiny-tiny local inference server (which I'm sure will grow over time) but the real game in town are things like Triton Inference Server, Seldon Core and to a certain extent BentoML (which maybe the closest conceptually the vibes of Dagger). Has anyone integrated any of those into the non-trivial pipelines?

Better yet -- am I even in the right channel askin this question here πŸ˜‰

Build powerful software environments and containerized operations from modular components and simple functions. Perfect for complex software delivery and AI agents. Built by the creators of Docker.

bright plinth
#

@mossy monolith note that the blog post is not about running docker model runner inside Dagger, but connecting to it as a client, to power agentic functions in Dagger

#

@mossy monolith for running the inference server, my guess is that GPU access is the only real issue. Otherwise it's "just" a matter of running the server in a container.

For GPU access, here's a good reference -> https://dagger.io/blog/gpu-challenges

Build powerful software environments and containerized operations from modular components and simple functions. Perfect for complex software delivery and AI agents. Built by the creators of Docker.

mossy monolith
main moth
#

Would it be fair to say that Dagger replaces Docker Compose use case for dev environments?

I could just start services and keep them running.

bright plinth
#

The biggest gap is live sync of volumes while the service is running

#

but @dusk ridge is working on it πŸ™‚

main moth
#

Ahh that’s of course would be a deal breaker πŸ™

bright plinth
#

But for now, it works great for running local instances of your service dependencies

main moth
#

Ya makes sense. Like a database and redis.

bright plinth
#

The gateway drug usually is standing up ephemeral services for e2e test environments

bright plinth
main moth
#

My dream was always a single setup for local dev and CI. Complete unification.

#

Otherwise you have compose on local, weird Action services in Ci, deploying to ECS. It’s a cacophony of solutions.

bright plinth
#

e2e test environments usually build up a lot of cruft and hacky scripts. Daggerizing them works great because they're repeatable of course, but also you can parametrize all the stuff that tends to change between dev and CI, making your scripts not portable across them.

For example you can parametrize a DB dependency, simply by passing an argument called db to your function, of type Service. Then depending on the context, you can pass an ephemeral container, or a tunnel to a dev DB running on your local machine, or even to staging or prod.

main moth
#

One dag as you guys say is my vision too for a looong long time.

bright plinth
#

You can also parametrize secrets... etc

#

You can stack up those building blocks as high as you want, and the whole system holds. For example we build and test dagger end-to-end in dagger.

main moth
#

I wish I could hard code secret refs actually. Was surprised I had to supply 1P refs via CLI params. Seems like a difficult thing to do if you have 20 of them. Wouldn’t it be better to put refs in code?

bright plinth
#

You can get a full end-to-end build of dagger (CLI + engine) and try it out interactively right now from your computer, for any branch or tag, with one command.

Say, a PR I'm working on to add .env support:

dagger call -m github.com/dagger/dagger@pull/11034/head dev terminal
bright plinth
#

You just write the arguments you want to pass to dagger call, encoded to a var in .env, and dagger will automatically merge it into the schema as a default value.

main moth
#

Nooo

#

This is where I diverge from dag vision 🀣

#

I HATE dot envs with a passion of 1000 suns.

bright plinth
#

eg.

$ cat .env
github_token=op://foo/bar/baz
aws_secret_key=vault://hello/there
base_container=myregistry/goldbase:v42
bright plinth
#

Note that you don't have to actually write secret values in the .env πŸ™‚ This is where our use difders from the current state of the art

#

You just use it to persist default arguments. You can keep your secrets in 1password, hashicorp vault etc

#

@main moth what do you use as an alternative to .env? Some fancy environment variable sync service? We could add direct integration to that

main moth
#

I just want to supply well know secret refs to the functions. These don’t change. Every dev has access to them via 1P. So putting them into dot env seems weird. As you technically not even supposed to commit that.

bright plinth
#

btw this is where we're discussing the particular topic of persisting user defaults (via .env or otherwise): #1413254056188579901

bright plinth
#

Convenience is always tempting, but it's what got the current devops stack in the mess it's in.

Even if you only used it sparingly and preserved the portability and safety of your functions. Not everyone will, and an ecosystem is only as good as its weakest link.

main moth
bright plinth
#

So by forcing dagger functions to remain sandboxed, we improve the quality of the ecosystem for everybody.

#

In other words: if we allow anyone to hardcode eg. 1password references in their code, what will actually happen is that lazy devs everywhere will hardcode everything all over the place, and the promise of Dagger functions being truly portable and parametrizable will vanish.

main moth
#

Still not seeing how dotenv solves portability. It’s just code too. Just a weird format of code that pretends to be environment variable.

bright plinth
#

Our implementation is just a dumb key=value, with variable interpolation and quotes

main moth
#

I’m thinking of a typical dot end .env

bright plinth
#

definitely not code

main moth
#

It’s code in a sense that it’s a file in your repo. It’s not text either. It’s not a document.

#

It has variables in it. It’s code.

#

It’s convenient to pretend it’s not code though. But it is.

bright plinth
#

I see. The useful part for us, is that there's already a convention that its lifecycle is not the same as your code's lifecycle. You typically don't check it into git. And if you do, you're advised to do it carefully and remember the difference. So we just piggyback on that.

main moth
#

It’s also a poor syntax with gotchas and quickly adds variable expansion. And it’s definitely code then.

main moth
bright plinth
#

I agree it's not the cleanest separation of code and configuration. There are other solutions, usually they involve an external service. For example 1password has an "environments" feature now. Doppler is a service that offers this also.

If you have a favorite alternative, I can make a note to prototype support for it πŸ™‚

bright plinth
main moth
#

I want to hard code refs into actual code that is TypeScript not .env

bright plinth
#

Got it. Well Dagger doesn't do that, sorry

main moth
#

It should

bright plinth
#

There is an escape hatch, that we want to improve - seems like what you'll want ⏬

main moth
#

Secret loading is a massive pain

bright plinth
#

You can always run the 1password client yourself in a container, orchestrated by a dagger function

main moth
bright plinth
#

The problem is that it's tricky to safely get the plaintext value from that command execution, without leaking it into the dagger cache or logs

#

But it will get solved eventually

main moth
#

I sense that you plan to add secret loading as EE in the future. πŸ˜‚ fair of course.

bright plinth
#

Then you'll still need to get the 1password service account token into the function πŸ™‚

bright plinth
main moth
#

Have you seen DMNO?

It kinda reminds me of dagger for secret loading.

#

I think something like that could be part of dagger itself.

#
DMNO

DMNO makes your configuration safer and smarter. It integrates with the tools you already use and it's powered by TypeScript and Vite.

bright plinth
#

I didn't know about it but it looks interesting.

I think our approach will be to integrate with whatever your favorite environment configuration system is, outside the dagger sandbox. I guess that could be DMNO, too

main moth
#

That’d be quite meta. I was just envisioning a concept of a β€œsecret provider” that can load secrets from somewhere

bright plinth
main moth
#

1P or vault. But this is from code with refs. Not from dotenv. Like a proper codified secret scheme with defaults and fallback values.

main moth
lament grove
#

Maybe that's a weird question, but does dockerBuild cache intermediate instructions results the same way as if they would have been executed via the Dagger API? This was my assumption.

I am facing this issue (have been facing from the very beginning with Dagger): I am keeping most of my base build steps in Dockerfile and hand it to Dagger to perform some fine-grained dynamic steps after the main bulk has been finished.

And apparently it hasn't been cached for this entire time (like 8 moths lol).

I am experiencing full rebuilds of the dockerBuild step quite frequently (even when doing innocent changes to other projects in my monorepo). I think it is cached across dagger call invocations within the same GitHub Actions run, but not across runs (commits).

@bright plinth could you helm me out here, please? I wasn't able to find any docs on this.


related issue? https://github.com/dagger/dagger/issues/6170

GitHub

What is the issue? While using the support for Dockerfiles in Dagger, each time the pipeline is executed, the disk space grows indefinitely even if all operations are cached Log output N/A Steps to...

obtuse niche
#

I want to test with Selenium using Dagger. Is there a way to specify memory size like Docker's --shm-size, or pass an option to the backend Docker?

obtuse niche
marsh rover
#

No

mint estuary
marsh rover
#

Ah, was in response to some spammer

#

Disregard πŸ™‚

elder kiln
#

Hi, does dagger use docker in docker?

cedar gust
# elder kiln Hi, does dagger use docker in docker?

No. Dagger needs a container runtime. It can be docker, it can be something else (like apple containers) or natively on linux. And then all the containers Dagger is creating are not docker containers. No docker in docker.

elder kiln
# cedar gust No. Dagger needs a container runtime. It can be docker, it can be something else...

I confused now i get answer from @bright plinth "No, Dagger does not have a runtime dependency on docker. It bundles its own container runtime and calls the underlying linux kernel directly to orchestrate containers."

Question is now is Dagger needs container runtime or not πŸ™‚ how it's working actually can I found it somewhere on docs please. Or i appriacite explanation here if you have time

cedar gust
# elder kiln I confused now i get answer from <@488409085998530571> "No, Dagger does not hav...

Well, yes, that's me, I wasn't clear enough. If you're not on linux, it will use a container runtime to spin up its engine. It can be docker or anything else. For instance on my machine I'm running docker so I have a dagger engine container running:

$ docker ps
CONTAINER ID   IMAGE                                  COMMAND                  CREATED        STATUS                     PORTS     NAMES
9191d944cd24   registry.dagger.io/engine:v0.19.11     "dagger-entrypoint.s…"   24 hours ago   Up 24 hours                          dagger-engine-v0.19.11

But once it's started, all the rest is going through dagger's container runtime and creating containers directly by talking to the linux kernel. There's no docker in docker (or similar).
The only thing is you need this linux kernel, and on mac for instance it doesn't exist. So we are using the one provided, as a vm, by the container solution, for instance the vm provided by Docker Desktop in which docker will create containers.
Here is a quick schema that should be close enough to how it works

elder kiln
bright plinth
# elder kiln Perfect thanks for explanation now it's much clearer, so in VM in Github Actions...

In CI runners, the three most common ways the dagger engine is started:

  1. By default, auto-started using docker, podman, or other equivalent tools. If the CI runner itself is running inside docker, then this would qualify as "docker-in-docker". As we discussed earlier, once started the engine doesn't rely on docker at all - it's just that in some cases it might be running inside a (privileged) docker container.

  2. Optionally, you can deploy a the dagger engine yourself, for example to a dedicated machine or kubernetes cluster, and configure the CI runners to connect to it. This is often done in production deployments of Dagger, for better control and performance, and also sometimes to avoid docker-in-docker.

  3. Optionally, you can use Dagger Cloud to deploy dagger engines for you on demand, auto-scaled and with persistent cache. DM me if that's an interesting option πŸ™‚

--> I know the answer to "docker-in-docker" can seem confusing. What complicates the answer, is that the engine doesn't call docker, but it can sometimes run inside docker.

thick field
#

Before I start a lengthy help thread, finding ONBUILD is ignored by Dagger's Directory.DockerBuild? Build an image with Docker it works, build it with Dagger it doesn't. Compare the two, the Docker-built image has the correct COPY/ENTRYPOINT/CMD instructions (all from ONBUILD) and the Dagger image doesn't. It's a very easy test - the Dagger-built image doesn't have the ONBUILD COPY content, the Docker-built image does.

Found https://github.com/dagger/dagger/issues/7530 which describes exactly our usecase. Building a base image that has ONBUILD instructions, used by other images. Is this not supported?

GitHub

Problem Some OCI image fields can be set by a Dockerfike but are not supported by the Dagger API. For example, healthcheck. Solution Add missing functions to the Container type to reach feature par...