#Copying a file from one container to another fails if I use build instead of from

1 messages · Page 1 of 1 (latest)

tacit pebble
#

If I do this:

        const image = client.directory().withNewFile(
            "Dockerfile",
            `
                FROM alpine    
            `
        );

        const builder = client
            .container()
            .build(image)
            .withWorkdir("/")
            .withEntrypoint(["sh", "-c"])
            .withExec(["echo htrshtrhrthrts > file.txt"])
            .withExec(["cat file.txt"]);

        const anotherImage = client
            .container()
            .from("alpine")
            .withWorkdir("/")
            .withFile("/copied-file.txt", builder.file("/file.txt"))
            .withEntrypoint(["sh", "-c"])
            .withExec(["cat copied-file.txt"]);

It fails. But if I do this:

        const builder = client
            .container()
            .from("alpine") // from instead of build
            .withWorkdir("/")
            .withEntrypoint(["sh", "-c"])
            .withExec(["echo htrshtrhrthrts > file.txt"])
            .withExec(["cat file.txt"]);

        const anotherImage = client
            .container()
            .from("alpine")
            .withWorkdir("/")
            .withFile("/copied-file.txt", builder.file("/file.txt"))
            .withEntrypoint(["sh", "-c"])
            .withExec(["cat copied-file.txt"]);

It works. Why is that? 🐛 ?

#

For science I ported the code to the go SDK and it works:

    // Build our app
    builder := client.
        Container().
        Build(image). // works fine
        WithWorkdir("/").
        WithEntrypoint([]string{"sh", "-c"}).
        WithExec([]string{"echo htrshtrhrthrts > file.txt"}).
        WithExec([]string{"cat file.txt"})

    prodImage := client.
        Container().
        From("alpine").
        WithWorkdir("/").
        WithFile("/copied-file.txt", builder.File("/file.txt")).
        WithEntrypoint([]string{"sh", "-c"}).
        WithExec([]string{"cat copied-file.txt"})

    out, err := prodImage.Stdout(ctx)

Am I missing something?

meager crow
#

/cc @quick quarry @chilly edge @blazing marten

#

Do you happen to have the error message, @tacit pebble? Also which version of the SDK you're using in the failing example?

quick quarry
#

OH NOES

#

I guess I gotta dig

#

Good catch @tacit pebble

tacit pebble
#

Node: 0.3.0
Go: 0.4.2

  errors: [
        {
          message: 'Syntax Error GraphQL request (5:26) Expected Name, found String "_queryTree"\n' +
            '\n' +
            '4:       \n' +
            '5:         build (context: {"_queryTree":[{operation:"directory","args":{}},{operation:"withNewFile","args":{path:"Dockerfile","contents":"\\n                FROM alpine    \\n            "}}],"clientHost":"127.0.0.1:45369","client":{url:"http://127.0.0.1:45369/query","options":{}}}) {\n' +
            '                            ^\n' +
            '6:       \n',
          locations: [ [Object] ]
        }
      ],
tacit pebble
#

I can also break it by doing this:

        const builder = client
            .container()
            .from("alpine")
            .withSecretVariable("TOKEN", client.host().envVariable("FOOBAR").secret()) // adding this line borks it 
            .withWorkdir("/")
            .withEntrypoint(["sh", "-c"])
            .withExec(["echo htrshtrhrthrts > file.txt"])
            .withExec(["cat file.txt"]);

        const anotherImage = client
            .container()
            .from("alpine")
            .withWorkdir("/")
            .withFile("/copied-file.txt", builder.file("/file.txt"))
            .withEntrypoint(["sh", "-c"])
            .withExec(["cat copied-file.txt"]);

        const out = await anotherImage.stdout();

Same error as above. And it works fine in Go.

fallen wing
#

NOTE: My comments below refer to the the second case above about .withSecretVariable.

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

// initialize Dagger client
connect(async (client) => {

    const builder = client
            .container()
            .from("alpine")
            .withSecretVariable("TOKEN", "baz")// adding this line borks it 
            .withWorkdir("/")
            .withEntrypoint(["sh", "-c"])
            .withExec(["echo htrshtrhrthrts > file.txt"])
            .withEnvVariable("CACHEBUSTER", Date.now().toString())
            .withExec(["cat file.txt"]);

        const anotherImage = client
            .container()
            .from("alpine")
            .withWorkdir("/")
            .withFile("/copied-file.txt", builder.file("/file.txt"))
            .withEntrypoint(["sh", "-c"])
            .withEnvVariable("CACHEBUSTER", Date.now().toString())
            .withExec(["cat copied-file.txt"]);

        const out = await anotherImage.stdout();
}, {LogOutput: process.stdout})
#

save as index.mjs, run as node index.mjs
after install
npm install @dagger.io/dagger --save-dev

fallen wing
#

If I use this line with a secret value in plaintext, I get this error

.withSecretVariable("TOKEN", "baz")
Node.js v18.11.0
#3 resolve docker.io/library/alpine:latest 0.1s done
#3 CACHED

#4 sh -c echo htrshtrhrthrts > file.txt
#4 ERROR: failed to decode *core.secretIDPayload bytes: illegal base64 data at input byte 0
------
> sh -c echo htrshtrhrthrts > file.txt:
------
fallen wing
#

@tacit pebble what were you hoping for this line to do?

.withSecretVariable("TOKEN", client.host().envVariable("FOOBAR").secret())
#

I'm assuming that you want the value $FOOBAR on the host to be the value of the TOKEN env var in the container. I'll run with that assumption.

#

So I used that ID in my call to withSecretVariable()

#
.withSecretVariable("TOKEN", "eyJob3N0X2VudiI6IkZPT0JBUiJ9")
#

This works ☝️ @quick quarry but I noticed that old cached values of the env var are used if I don't use a CACHEBUSTER, even though the secret is more of a reference to a host env var.

Also, I suspect this wasn't working in code like

.withSecretVariable("TOKEN", client.host().envVariable("FOOBAR").secret())

because the equivalent call in the Node.js SDK returns not a Base64-encoded string, but rather an object:

const sec = client.host().envVariable("FOOBAR").secret()
await console.log(sec)

returns

Secret {
  _queryTree: [
    { operation: 'host' },
    { operation: 'envVariable', args: [Object] },
    { operation: 'secret' }
  ],
  clientHost: '127.0.0.1:58538',
  client: GraphQLClient { url: 'http://127.0.0.1:58538/query', options: {} }
}

and

await console.log(sec._queryTree[1])

returns

{ operation: 'envVariable', args: { name: 'FOOBAR' } }
quick quarry
chilly edge