Learning Notes #68 β Buildpacks and Dockerfile
- What is an OCI ?
- Does Docker Create OCI Images?
- What is a Buildpack ?
- Overview of Buildpack Process
- Builder: The Image That Executes the Build
- Installation and Initial Setups
- Basic Build of an Image (Python Project)
- Unique Benefits of Buildpacks
- Generating SBOM in Buildpacks
Last few days, i was exploring on Buildpacks. I am amused at this tool features on reducing the developerβs pain. In this blog i jot down my experience on Buildpacks.
Before going to try Buildpacks, we need to understand what is an OCI ?
What is an OCI ?
An OCI Image (Open Container Initiative Image) is a standard format for container images, defined by the Open Container Initiative (OCI) to ensure interoperability across different container runtimes (Docker, Podman, containerd, etc.).
It consists of,
- Manifest β Metadata describing the image (layers, config, etc.).
- Config JSON β Information about how the container should run (CMD, ENV, etc.).
- Filesystem Layers β The actual file system of the container.
OCI Image Specification ensures that container images built once can run on any OCI-compliant runtime.
Does Docker Create OCI Images?
Yes, Docker creates OCI-compliant images. Since Docker v1.10+, Docker has been aligned with the OCI Image Specification, and all Docker images are OCI-compliant by default.
- When you build an image with
docker build
, it follows the OCI Image format. - When you push/pull images to registries like Docker Hub, they follow the OCI Image Specification.
However, Docker also supports its legacy Docker Image format, which existed before OCI was introduced. Most modern registries and runtimes (Kubernetes, Podman, containerd) support OCI images natively.
What is a Buildpack ?
A buildpack is a framework for transforming application source code into a runnable image by handling dependencies, compilation, and configuration. Buildpacks are widely used in cloud environments like Heroku, Cloud Foundry, and Kubernetes (via Cloud Native Buildpacks).
Overview of Buildpack Process
The buildpack process consists of two primary phases
- Detection Phase: Determines if the buildpack should be applied based on the appβs dependencies.
- Build Phase: Executes the necessary steps to prepare the application for running in a container.
Buildpacks work with a lifecycle manager (e.g., Cloud Native Buildpacksβ lifecycle
) that orchestrates the execution of multiple buildpacks in an ordered sequence.
Builder: The Image That Executes the Build
A builder is an image that contains all necessary components to run a buildpack.
Components of a Builder Image
- Build Image β Used during the build phase (includes compilers, dependencies, etc.).
- Run Image β A minimal environment for running the final built application.
- Lifecycle β The core mechanism that executes buildpacks, orchestrates the process, and ensures reproducibility.
Stack: The Combination of Build and Run Images
- Build Image + Run Image = Stack
- Build Image: Base OS with tools required for building (e.g., Ubuntu, Alpine).
- Run Image: Lightweight OS with only the runtime dependencies for execution.
Installation and Initial Setups
- For Installation: https://buildpacks.io/docs/app-journey/
- For App Developers: https://buildpacks.io/docs/for-app-developers/
Basic Build of an Image (Python Project)
Project Source: https://github.com/syedjaferk/gh_action_docker_build_push_fastapi_app
Building an image using buildpack
Before running these commands, ensure you have Pack CLI (pack
) installed.
a) Detect builder suggest
pack builder suggest
b) Build the image
pack build my-app --builder paketobuildpacks/builder:base
c) Run the image locally
docker run -p 8080:8080 my-python-app
Building an Image using Dockerfile
a) Dockerfile
FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY ./random_id_generator ./random_id_generator COPY app.py app.py EXPOSE 8080 CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"]
b) Build and Run
docker build -t my-python-app . docker run -p 8080:8080 my-python-app
Unique Benefits of Buildpacks
No Need for a Dockerfile
(Auto-Detection)
Buildpacks automatically detect the language and dependencies, removing the need for Dockerfile
.
pack build my-python-app --builder paketobuildpacks/builder:base
It detects Python, installs dependencies, and builds the app into a container. Docker requires a Dockerfile
, which developers must manually configure and maintain.
Automatic Security Updates
Buildpacks automatically patch base images for security vulnerabilities.
If thereβs a CVE in the OS layer, Buildpacks update the base image without rebuilding the app.
pack rebase my-python-app
No need to rebuild! It replaces only the OS layers while keeping the app the same.
Standardized & Reproducible Builds
Ensures consistent images across environments (dev, CI/CD, production). Example: Running the same build locally and on Heroku/Cloud Run,
pack build my-app
Extensibility: Custom Buildpacks
Developers can create custom Buildpacks to add special dependencies.
Example: Adding ffmpeg
to a Python buildpack,
pack buildpack package my-custom-python-buildpack --path .
Generating SBOM in Buildpacks
a) Using pack
CLI to Generate SBOM
After building an image with pack
, run,
pack sbom download my-python-app --output-dir ./sbom
- This fetches the SBOM for your built image.
- The SBOM is saved in the
./sbom/
directory.
Supported formats:
- SPDX (
sbom.spdx.json
) - CycloneDX (
sbom.cdx.json
)
b) Generate SBOM in Docker
trivy image --format cyclonedx -o sbom.json my-python-app
Both are helpful in creating images. Its all about the tradeoffs.