Most organizations have Dockerfiles somewhere. Some have a lot of them. They might be managed by another team, and maybe your team only interacts with the built images, but chances are that if you’re thinking about CI, you’ve thought about writing, maintaining, simplifying, or getting rid of your Dockerfiles.
If you’re using Dagger to turn your pipelines into code via a Dagger SDK in Go, Python, or Node.js (or via the GraphQL API directly), then you have a couple of options on how to handle your Dockerfiles.
Let’s examine each of these.
You might want to do this if you have a deep investment in Dockerfiles and they are an important interface for developers or platform engineers. You might also want to focus on orchestrating the rest of your pipeline first and tackling your working Dockerfiles later.
It’s easy to read in a directory of content that includes a Dockerfile and produce an image with Dagger. You can also initialize a new Container in Dagger from a Directory with a Dockerfile in it.
import anyio
import sys
import dagger
async def main():
async with dagger.Connection(dagger.Config(log_output=sys.stderr)) as client:
build = client.host().directory(".").docker_build()
await build.publish("jeremyatdockerhub/myexample:latest")
anyio.run(main)
Read more about building Dockerfiles in the Python SDK Reference.
package main
import (
"context"
"os"
"dagger.io/dagger"
)
func main() {
ctx := context.Background()
client, err := dagger.Connect(ctx, dagger.WithLogOutput(os.Stderr))
if err != nil {
panic(err)
}
defer client.Close()
_, err = client.Host().Directory(".").
DockerBuild().
Publish(ctx, "jeremyatdockerhub/myexample:latest")
if err != nil {
panic(err)
}
}
Read more about building Dockerfiles in the Go SDK Reference.
import { connect } from "@dagger.io/dagger"
connect(async (client) => {
const imageRef = await client.host().directory(".").
dockerBuild().
publish("jeremyatdockerhub/myexample:latest")
}, { LogOutput: process.stderr })
Read more about building Dockerfiles in the Node.js SDK Reference.
query {
host {
directory(path: ".") {
dockerBuild(dockerfile: "./Dockerfile") {
publish(address: "jeremyatdockerhub/myexample:latest")
}
}
}
Read more about building Dockerfiles in the API Reference.
Whether your Dockerfiles are super simple (and thus trivial to turn into Dagger SDK code), or super gnarly, converting your existing Dockerfiles into Dagger code means you can take full advantage of both Dagger and your language of choice to create testable, extensible builds and pipelines. It might be that Dockerfile syntax is a mystery to many of your engineers and thus folks are reluctant to touch them, or that you’ve outgrown the Dockerfile format and need more control that a full programming language can offer including types, functions, loops, and conditionals.
If you’re familiar with Dockerfiles or the concepts behind them, you’ll find the Dagger API implemented by the SDKs has familiar constructs for working with Containers, Directories, Files, Git, Environment Variables, Secrets, etc.
Luckily we have an excellent blog post and technical guide that illustrates the approach in Go, Python and Node.js. It shows you how to
To help with mapping your Dockerfile to Dagger, here’s a handy table of some of the common Dockerfile commands and their Dagger equivalents. It actually helps to think of Dagger as much more than a Dockerfile equivalent, because it is! Some things are more akin to what you’d do with docker build or docker run or buildx. For example mounting directories, cache mounts, and build args. A lot of this functionality can be found in the docs under the Container type, so that’s a great place to browse.
Dockerfile | Python SDK | Go SDK | Node.js SDK |
---|---|---|---|
FROM alpine:3 | container().from_(“alpine:3”) | Container.From(“alpine:3”) | container.from(“alpine:3”) |
COPY | .with_file() or .with_directory() | WithFile() or WithDirectory() | withFile() or withDirectory() |
RUN | .with_exec() | WithExec() | withExec() |
ENV | .with_env_variable() | WithEnvVariable() | withEnvVariable() |
WORKDIR | .with_workdir() | WithWorkdir() | withWorkdir() |
ENTRYPOINT | .with_entrypoint() | WithEntryPoint() | withEntryPoint() |
CMD | .with_default_args() | WithDefaultArgs() | withDefaultArgs() |
USER | .with_user() | WithUser() | withUser() |
LABEL | .with_label() | WithLabel() | withLabel() |
Whether you need to keep your existing Dockerfiles around for a while or are ready to turn them into Dagger SDK code, you’ve now got the tools to incorporate your existing Dockerfiles into your Dagger pipelines. As always, we’re available in Discord if you need help!