#Docker Image Building Approach

1 messages · Page 1 of 1 (latest)

zenith bramble
#

Hi, I'm trying to understand the best way to build a Linux Docker image using Dagger functions.
In the hello-world example from the documentation there's a build function that uses the build_env function.
If I understand this correctly the build_env function creates a Docker container based on node:21-slim and then uses that container to build the nginx container.
Is my understanding correct?

I'm not clear on why a build_env is needed for building a Docker container. Can someone briefly explain why it's necessary?
If it is a best practice, is the node image the best build_env to use for general Docker image building?

` @function
def build(self, source: dagger.Directory) -> dagger.Container:
"""Build the application container"""
build = (
self.build_env(source)
.with_exec(["npm", "run", "build"])
.directory("./dist")
)
return (
dag.container()
.from_("nginx:1.25-alpine")
.with_directory("/usr/share/nginx/html", build)
.with_exposed_port(80)
)

@function
def build_env(self, source: dagger.Directory) -> dagger.Container:
    """Build a ready-to-use development environment"""
    node_cache = dag.cache_volume("node")
    return (
        dag.container()
        .from_("node:21-slim")
        .with_directory("/src", source)
        .with_mounted_cache("/src/node_modules", node_cache)
        .with_workdir("/src")
        .with_exec(["npm", "install"])
    )`
real frost
#

Hey @zenith bramble!!

Containers get built by chaining functions together. If want to build a container by chaining everything together without any separation, thats fine too! Nothing forces you to create separate functions that build different parts of a container. In the build_env function you can see that it returns a dagger.Container. The build function uses that container to continue adding stuff on top of it. If you wanted, you could inline everything in the build function.

The nice thing about separating it is reusability. Often, you find yourself doing many different operations that all use the same base container, which is why this patterns of a function that returns a base container emerges