Dagger Cloud in Action: Going 100% Faster, Spending 75% Less at Airbyte
Read more

Using Dockerfiles with Dagger

May 9th, 2023By Jeremy Adams
image credits:https://unsplash.com/photos/yZygONrUBe8?utm_source=unsplash&utm_medium=referral&utm_content=creditShareLink

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.

  • Keep your existing Dockerfiles and drive Docker builds from Dagger
  • Turn your Dockerfiles into Dagger code

Let’s examine each of these.

Build from your existing Dockerfiles

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")


Read more about building Dockerfiles in the Python SDK Reference.

package main

import (

func main() {
 ctx := context.Background()
 client, err := dagger.Connect(ctx, dagger.WithLogOutput(os.Stderr))
 if err != nil {
 defer client.Close()

 _, err = client.Host().Directory(".").
   Publish(ctx, "jeremyatdockerhub/myexample:latest")
 if err != nil {

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(".").

}, { LogOutput: process.stderr })

Read more about building Dockerfiles in the Node.js SDK Reference.

GraphQL API:
query {
  host {
    directory(path: ".") {
      dockerBuild(dockerfile: "./Dockerfile") {
    	 publish(address: "jeremyatdockerhub/myexample:latest")

Read more about building Dockerfiles in the API Reference.

Turn your Dockerfiles into Dagger code

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

  • Understand and break down a Dockerfile into steps
  • Create a Dagger client
  • Write a Dagger pipeline to replicate the Dockerfile build process, taking advantage of functions and the Dagger API implemented by your SDK of choice to:
  • Configure a container with all required dependencies and environment variables for an application
    • Download and build the application source code in the container
    • Set the container entrypoint
    • Publish the built container image to Docker Hub
  • Test the Dagger pipeline locally

Read the guide.

Mapping Dockerfiles to Dagger

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.

DockerfilePython SDKGo SDKNode.js SDK
FROM alpine:3container().from_(“alpine:3”)Container.From(“alpine:3”)container.from(“alpine:3”)
COPY.with_file() or .with_directory()WithFile() or WithDirectory()withFile() or withDirectory()


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!