Mastering the Tabula Rasa Approach: A Comprehensive Engineering Guide to Docker FROM scratch

The architectural philosophy of containerization is often centered around the concept of layering. For the vast majority of developers and DevOps engineers, the journey of creating a container begins with a predefined base image—a curated environment like Ubuntu, Alpine, or Python that provides a shell, package managers, and essential system libraries. However, there exists a more fundamental, surgical approach to image construction: the FROM scratch directive. To build from scratch is to embrace the concept of tabula rasa, or a clean slate. It is the process of constructing a container image starting with absolutely nothing, where every single byte of the resulting filesystem is explicitly placed there by the developer. This approach is not merely a technical curiosity but a critical strategy for creating super-minimal images, optimizing the attack surface for security-critical applications, and constructing the very base images that other containers rely upon. Understanding FROM scratch requires a shift in perspective from "configuring an environment" to "assembling a filesystem."

The Fundamental Nature of the scratch Image

In the Docker ecosystem, scratch is a reserved, minimal image. Unlike standard images, it does not contain any files, directories, or binaries. It is an empty starting point.

  • Technical Mechanism: Using the scratch image signals to the Docker build engine that the subsequent command in the Dockerfile must be the first filesystem layer of the image. It effectively tells the builder to ignore any inherited layers and start with a completely empty root directory.
  • Administrative Impact: Because it is a reserved keyword, scratch behaves differently than a standard repository. It cannot be pulled via docker pull, it cannot be run as a standalone container, and it cannot be tagged. Its only valid utility is as a starting point in a Dockerfile.
  • Performance Layer: Since Docker 1.5.0 (specifically referenced in docker/docker#8827), FROM scratch is treated as a no-op (no operation). This means it does not create an additional metadata layer in the final image. If an image was previously constructed in a way that would have resulted in two layers, the use of scratch ensures it remains a single-layer image, optimizing the storage and distribution efficiency.
  • Contextual Connectivity: This void-like state is what makes it the primary tool for creating "distroless" images or the same official base images (like Debian or BusyBox) that most users take for granted.

Strategic Applications of Minimal Image Construction

Building from scratch is reserved for specific high-stakes architectural requirements where the overhead of a general-purpose operating system is unacceptable.

  • Base Image Creation: This is the primary method for building the fundamental images that serve as the foundation for others. For example, a developer creating a custom Linux distribution for a container would start with FROM scratch and add the necessary kernel headers and root filesystem.
  • Super Minimal Binary Execution: When an application is compiled as a statically linked binary (such as those written in Go, Rust, or C++), it does not require external shared libraries or a shell to execute. In these cases, the image only needs the binary itself.
  • Security and CVE Mitigation: From an Enterprise IT Virtualization perspective, using canned images means inheriting the assumptions and potential vulnerabilities of the image author. By building from scratch, an architect can eliminate all unnecessary binaries (like curl, wget, or sh) that an attacker could use for lateral movement after an initial exploit. This drastically reduces the Common Vulnerabilities and Exposures (CVE) footprint.
  • Dependency Control: Starting from nothing ensures that the developer understands every single assumption required for the application to run, preventing the "it works on my machine" syndrome caused by hidden dependencies present in a standard base image.

Technical Implementation: The Static Binary Workflow

The most common use case for FROM scratch is the deployment of a single, statically compiled binary. Because there is no shell and no package manager, the binary must be entirely self-sufficient.

  • Implementation Process: The binary is compiled on the host machine and then copied into the empty image.

The following configuration illustrates the minimal required Dockerfile for this process:

dockerfile FROM scratch COPY hello / CMD ["/hello"]

  • Technical Layer: The COPY command takes the binary named hello from the local build context and places it at the root directory / of the image.
  • Impact Layer: The resulting image contains exactly one file. There is no /bin, /etc, or /lib directory. This results in an image size that is virtually identical to the size of the binary itself.
  • Contextual Layer: This contrasts sharply with an image based on ubuntu, which would include hundreds of megabytes of system utilities, most of which are irrelevant to the execution of a single binary.

Advanced Implementation: Constructing a Root Filesystem

While a single binary is the simplest use case, it is often necessary to have a minimal set of tools (like a shell) to interact with the container. Since FROM scratch provides no tools, the developer must provide a pre-packaged root filesystem.

  • The Challenge of Bootstrapping: Because the scratch image is empty, it contains no utilities such as wget or curl. Consequently, you cannot download files from the internet inside the Dockerfile during the build process. All required assets must be downloaded to the host machine first.

  • The Alpine Mini Root Filesystem Process:

    1. Download the mini root filesystem to the host:

    bash wget -O alpine-minirootfs.tgz https://bit.ly/alpine-minirootfs-3-19-1

    1. Create a Dockerfile that layers this filesystem onto the empty base:

    dockerfile FROM scratch ADD alpine-minirootfs.tgz / CMD ["/bin/sh"]

    1. Build the image:

    bash docker build -t scratch-alpine .

  • Technical Analysis of ADD: The ADD command is specifically used here because it has the capability to automatically unpack a local tarball (like alpine-minirootfs.tgz) into the image's root directory. This effectively "installs" a minimal Linux environment into the void of the scratch image.

Comparative Analysis: Scratch-Based vs. Official Images

To understand the efficiency of the FROM scratch method, it is useful to compare a manually constructed minimal image with an official distribution.

Image Name Base Image Method of Construction Resulting Size Contents
scratch-alpine scratch ADD alpine-minirootfs.tgz 7.37 MB Minimal Root FS + /bin/sh
alpine:3.19.1 Official Curated Build Process 7.38 MB Official Alpine Distribution
  • Analysis of Results: The scratch-alpine image, created manually from a root filesystem, is 7.37 MB. The official Alpine image is 7.38 MB. This demonstrates that the official minimal images are themselves constructed using a process very similar to the FROM scratch method.
  • Impact: The negligible difference in size confirms that building from scratch allows developers to achieve the same level of optimization as the official Docker maintainers.

Operational Workflow and Tooling

The transition from standard Docker development to FROM scratch development requires a different set of tools and a more rigorous understanding of the underlying operating system.

  • The Build Sequence:

    1. Prepare the binary or root filesystem on the host.
    2. Define the Dockerfile using the FROM scratch directive.
    3. Execute the docker build command.
    4. Inspect the image using docker image ls to verify the size.
    5. Use docker pull on official images (like alpine:3.19.1) only for comparison or as a reference.
  • Inspection and Debugging: Because images built from scratch often lack a shell, debugging becomes difficult. If a developer uses FROM scratch and only copies a binary, they cannot use docker exec -it <container> /bin/sh because the /bin/sh binary does not exist. This necessitates the use of specialized debugging tools or the temporary addition of a minimal root filesystem during the development phase.

Conceptual Comparison: Docker vs. Podman in the Scratch Context

In the broader DevOps landscape, the concepts introduced by FROM scratch are applicable across different container engines.

  • Docker Integration: Docker treats scratch as a reserved keyword integrated into the build engine to prevent the creation of unnecessary layers.
  • Podman Compatibility: As an alternative to Docker, Podman also supports the FROM scratch directive, following the same OCI (Open Container Initiative) standards. The fundamental goal—creating a container from a blank slate—remains consistent across both platforms.

Conclusion: The Architectural Significance of the Blank Slate

The use of FROM scratch represents the pinnacle of container optimization and security. By removing the abstraction of a base operating system, developers transition from being "users" of an environment to "architects" of a filesystem. This method eliminates the "inherited mindset" of third-party image authors, ensuring that every single file within the container is there by intent and necessity.

From a technical perspective, the ability to use scratch as a no-op layer allows for the creation of the most efficient images possible, reducing both the storage footprint and the time required to pull images across a network. From a security perspective, it is the ultimate defense-in-depth strategy; by removing the shell and standard utilities, the attacker is left with no tools to execute scripts or explore the network. While the complexity of this approach is higher—requiring the manual acquisition of root filesystems and the use of statically linked binaries—the reward is a hardened, high-performance container that is stripped of all waste and vulnerability. In the modern DevOps era, where the goal is to move toward "distroless" architectures, mastering the FROM scratch directive is an essential skill for any engineer aiming for absolute control over their infrastructure.

Sources

  1. Docker from Scratch - ivonet.nl
  2. Docker Hub - Scratch Image
  3. DataWookie - Docker Image from Scratch
  4. Docker Forums - How to create my own from scratch OS image

Related Posts