Skip to content

Conversation

fiifikcbentil
Copy link
Contributor

This PR introduces a new layers function val layers : t -> int that approximates the number of filesystem layers a given Dockerfile (Dockerfile.t) will produce.
The function inspects each instruction in the Dockerfile (Dockerfile.t) and counts only those that are guaranteed to create a new image layer in Docker, see: https://docs.docker.com/engine/storage/drivers/#images-and-layers. These are FROM, RUN, COPY, and ADD.
Being able to estimate the layer count from Dockerfile.t will help inform decisions regarding image size and build performance as well as help analyze the cost of adding new instructions

Copy link
Contributor

@MisterDA MisterDA left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@MisterDA MisterDA merged commit c30a1e7 into ocurrent:master Sep 26, 2025
1 check passed
@MisterDA
Copy link
Contributor

MisterDA commented Sep 26, 2025

This could be improved for the case of multi-stage builds.

# let dockerfile =
    let open Dockerfile in
    (from ~alias:"build" "alpine:latest")
    @@ (run "echo hello > /world")
    @@ (from "alpine:latest")
    @@ (copy ~from:"build" ~link:true ~src:["/world"] ~dst:"/world") ()
  ;;
val dockerfile : Dockerfile.t = <abstr>
# Dockerfile.layers dockerfile;;
- : int = 4
# Format.printf "%a" Dockerfile.pp dockerfile;;
FROM alpine:latest AS build
RUN echo hello > /world

FROM alpine:latest
COPY --link --from=build [ "/world", "/world" ]
- : unit = ()
> docker build -t ocaml-dockerfile - <<EOF
FROM alpine:latest AS build
RUN echo hello > /world

FROM alpine:latest
COPY --link --from=build [ "/world", "/world" ]
EOF
> docker history ocaml-dockerfile
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
ea6280f57fe7   7 minutes ago   COPY /world /world # buildkit                   6B        buildkit.dockerfile.v0
<missing>      2 months ago    CMD ["/bin/sh"]                                 0B        buildkit.dockerfile.v0
<missing>      2 months ago    ADD alpine-minirootfs-3.22.1-x86_64.tar.gz /…   8.31MB    buildkit.dockerfile.v0

That shows only two layers with a non-zero size. I think you should reset the count each time you encounter a `From.

@fiifikcbentil
Copy link
Contributor Author

Thanks for catching that. You're right in the case of multi-stage builds, it makes sense to reset the counter whenever we hit a new FROM statement. I'll put in a follow-up change

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants