A simple Dockerfile parser written in ReasonML, and usable as both a library as well as a program.
The library provides a function, string_of_docker
, that can generate Dockerfile lines, although it cannot currently round-trip.
let src = [Arg("version", "10"), RunCommand("wc -l")]
List.iter((x) => {
print_endline(longshoreman,string_of_docker(x))
}, src)
Reading the Dockerfile specification, I don’t know if I will actually support round tripping the code; instead, I’ll probably focus on accurately parsing & canonicalizing, rather than round trip accuracy
Additionally, docker_of_string
is provided to parse Docker lines into t
objects that can be used:
let d = docker_of_line({|CMD ["/bin/sh", "-c", "echo test"]|}, 0); (1)
switch(d) {
| CMDArray(l) => {
List.iter((x) => print_endline("command exec arg: " ++ x), l)
}
| _ => print_endline("hmm, an error occurred; we expected a CMDArray, got: " ++ string_of_docker(d)) (2)
}
<1>: returns a CMDArray
ADT
Or, to show both:
let src = {|CMD ["/bin/ksh", "-c", "echo test this"]|};
let res = docker_of_line(src);
let roundtrip = string_of_docker(res);
print_endline("does it round trip? " ++ string_of_bool(roundtrip == src))
Currently, processing a Dockerfile is a slightly delicate effort, but if you have the file sliced into logical lines, you can parse it via:
#use "longshoreman.re";
let lines = ["FROM gcr.io/fuzzbench/base-image",
"ENV WORK /work",
"ENV SRC $WORK/src",
"RUN mkdir -p $SRC",
"ADD . $SRC/",
"ENTRYPOINT /bin/bash $SRC/docker/worker/startup-worker.sh"];
let dockerfile = List.map(docker_of_line(_, 0), lines);
Lastly, dockerfile_of_string
can slice up a string containing multiple docker statements:
#use "longshoreman.re";
let src = {|FROM gcr.io/fuzzbench/base-image
ENV WORK /work
ENV SRC $WORK/src
RUN mkdir -p $SRC
ADD . $SRC/
ENTRYPOINT /bin/bash $SRC/docker/worker/startup-worker.sh|};
let dockerfile = dockerfile_of_string(src)