I had a chuckle when I looked at the source code and could not find a Dockerfile in there. I want to kick the tires on it and the easiest way would be to run it as a Docker container against an existing file and alas, I cannot.
I don't want to vouch for the flagged and dead comment https://news.ycombinator.com/item?id=43630653 because I suspect it was killed for its tone but wow it is really illustrative of the QA that didn't go into this product
What I can do for you is fix the bugs promptly! I resolved the bugs in the `0.2.7` release. I haven't graduated college yet and don't have a full time job, so my QA skills are still improving.
As far as I can tell from https://github.com/moby/moby/issues/4032, as of Debian 12 "bookworm" and Ubuntu 23.04 "Lunar", explicitly setting DEBIAN_FRONTEND is no longer necessary.
I'm firmly in that camp but I also always add `set -eux`, which makes it so much better at debugging as that gives you individual commands it runs before the output of them.
Docker also supports the `SHELL` syntax now, which is even better, because you can set it once at the top of the Dockerfile without having to do the whole `set -eux` on every line.
Readability is putting it mildly; do you write your shell scripts using that && style? No? Why not, is it for readability?
I also have a hard time reasoning about && with anything other than the most braindead sequence of commands because: $(thing && if other_thing; then inner_thing1 && thing2; fi && ohgawd)
And I just realized while typing that out that if its parser doesn't support ; then I guess one needs to
RUN if conditional_thing \
then good_luck && \
fi && \
echo "whew"
Meta: In HN, prefix a line with 2 spaces to get code formatting, ex.
# syntax=docker/dockerfile:1.3-labs
FROM alpine
RUN <<EOF
echo "This is a heredoc example"
echo "It allows multi-line commands"
EOF
Non-meta: Do you happen to know how portable that is across old docker, podman/buildah, kaniko, etc.? I'd like to adopt it but I don't want it to bite me when I'm not running a recent version of literal docker.
Or, you can write an actual shell script file (i.e. with a .sh extension) to be stored in your repository, ADD it in a throwaway context (i.e. multi-stage builds), then RUN --mount=type=bind to put it into a temporary directory in the build container so that you can execute it. This way, the script doesn't pollute the container, and you have proper separation of concerns, including the ability to use library functions, running shell linters directly, or using higher-level languages like Python if you really need it for some reason
> Try to make the Dockerfile easy to understand/read. It may be tempting, for the sake of brevity, to put complicated initialization details into a standalone script and merely add a RUN command in the Dockerfile. However, this causes the resulting Dockerfile to be overly opaque, and such Dockerfiles are unlikely to pass review. Instead, it is recommended to put all the commands for initialization into the Dockerfile as appropriate RUN or ENV command combinations. To find good examples, look at the current official images.
That's advice specifically for official images, and it dates back before multi-stage builds. Most people are not building official images. Most people benefit from clear encapsulation and separation of concerns. The Dockerfile sets up the environment to run the provisioning script, and a provisioning script does the actual provisioning. Official images are different because usually the provisioning script is hidden in an OS package installed with e.g. apk add (or are we going to pretend that OS packages are bad practice for the same reason?).
I use `mvdan/sh` [1] under the hood for processing the commands. So it will reformat
if [ foo ] ; then
bar
fi
to
if [ foo ]
then
bar
fi
And also format your example to
foo
bar
In this type of situation, it becomes a little trickier to disambiguate when I need to add semicolons and a backslash, and when I need to add only backslashes. If you use `&&` -- you have disambiguated the two cases so I can format it.
Between that and the difficulty with comments, it feels like maybe not an ideal tool for the job? Although, I can't throw stones; I'd do almost anything to avoid having to write my own parser. (And not meant as an attack regardless, just trying to constructively question this particular design point)
I am certainly not in the business of writing my own shell parser ;) Though this is a fair point -- I think I could get a more rich level of control over the output by hooking into their parser, albeit with a higher level of complexity.
/shrug Something to think about. Usually I'd say not to worry about it, but this particular point seems to be actively causing actual problems, so it might be worth looking at. Alternatively, if the pain points you've discovered really are all there are to find, then it might well be less trouble to just patch over them specifically and not worry about it. Ugly solutions that work well and don't take extra work are good solutions in my book;)
This reminds me of SQL indentation “best practices” discussion [1]
I personally don’t find this particularly helpful but can see it helping some folks. You write enough dockerfiles, the formatting becomes irrelevant.
What pisses me off though is _inconsistency_. One code base uses "formatting practices 1b", then another code base uses "formatting practices 2x". Then the worst offender: a service owners that can’t make up their mind and each developer makes up their own "best practices".
How does it handle multi-stage Dockerfiles? I always indent the steps following FROM to make the stages more obvious. I don't get why that isn't a norm because not doing it seems like not indenting function bodies in other languages.
I just use a yaml LSP which will probably try to lookup the schema.org Containerfile format for this. I first noticed this recently when working on a Github Actions yaml file. Pretty nifty.
You should read and understand the documentation for the containerfile format before continuing. This isn't some quirk because i'm using &&, you are breaking almost every dockerfile that doesn't use the array syntax for ENTRYPOINT.
If any organization adopted the spec I would hope they would at least make it adopt a standard file extension like .oci so it would at least be more easily recognizable by IDEs, I have never liked having to put the use case as the extension like Dockerfile.dev
But I do like that docker and buildkit have been able to freely evolve the spec with things like advanced caching directives that work great in buildx
Each of those has tradeoffs compared to Dockerfiles (I have no need for bazel, but if I did, then adding `rules_oci` might be a win-win, rather than using a Dockerfile). If I used Nix, then the Nix dockerTools would be a huge win (I don't use Nix). If I were shipping Go programs, `ko` would likely be a good baseline.
Buildah is the only serious alternative in my opinion.
You lose automatic layer caching, but in exchange you can use the same tools (RUN, ADD, etc) within a much more powerful shell environment.
I wrote a Buildah wrapper that uses a shell script harness to polyfill the familiar Dockerfile syntax while adding several extra goodies - mainly the ability to bake runtime arguments (mounts, ports...) into the image. Very handy!
Buildah's ability to mount the container in an unshare environment is pretty magical for copying stuff in and out of it.
That said, in the end I'd still rather build containers with something other than an imperative sequence of commands, so my heart is going to be forever with nix2container and bazel's rules_oci.
It's great to see auto-formatting continuing to become universal across all languages. As LLMs write more code, full auto-formatting helps keep diffs clean.
Full disclosure: I'm the founder of Qlty, which produces a universal code linter and formatter, Qlty CLI (https://github.com/qltysh/qlty). It is completely free and published under a Fair Source license.
> As LLMs write more code, full auto-formatting helps keep diffs clean.
Clean diffs matter irrespective of the author being a person or a program. But sure, I guess with the current hype a certain ratio of comments need to plug reminders that we are currently living in a code generation wasteland.