dockerfmt 1.0 makes formatting safe by construction and fixes a long list of
bugs found by fuzzing and review. Some defaults changed; see below.
Breaking changes
- The trailing newline is kept as it is. Without
--newlineor an
EditorConfiginsert_final_newline, the output now ends with a newline if
the input does. Before, it never did unless--newlinewas given.
--newline=falseremoves it. The JStrailingNewlineoption defaults the
same way. - The npm package requires Node.js 20 or later.
- The Go
libpackage exposes onlyFormat,Configand the indent size
constants.FormatFileLines,ExtendedNode,ParseState,FormatNode,
FormatOnBuild,BuildExtendedNode,GetHeredoc,GetFileLines,
StripWhitespace,FormatCommentsandIndentFollowingLineswere removed.
Formatreturns an error instead of exiting the process. - The default Docker image is based on distroless and has no shell. Use
ghcr.io/reteps/dockerfmt:alpinewhere a shell is needed, such as GitLab CI. - Redirects get a space by default (
> file), in the CLI and the JS
API;--space-redirects=false(spaceRedirects: false) turns it off. The
pre-commit hook no longer needs to pass it. --indentmust be from 1 to 16, and--writecan't be combined with
--checkor--diff.- Help is shown only when no files are given and stdin is a terminal; empty
piped input is an error.
Safety
- Each formatted instruction is checked with BuildKit's parser to mean the
same as the original, and to stay the same when formatted again. The whole
file is then checked as written. Anything that fails is left unchanged, with
a warning. FuzzFormatchecks these properties on random inputs; CI runs it on every
change.--writerewrites files in place: permissions, owner, hard links and
symbolic links are kept, it works in read-only directories, and a failed
write restores the original contents.
Build checks
Formatting now fixes these BuildKit build-check warnings:
- FromAsCasing:
from a as bbecomesFROM a AS b. - StageNameCasing: stage names are written in lower case, and so are the
references to them inCOPY --from,RUN --mount=...,from=andFROM.
BuildKit finds a stage ignoring case everywhere exceptFROM, so
FROM Buildernow builds on the stagebuilderas intended. - ExposeProtoCasing:
EXPOSE 80/TCPbecomesEXPOSE 80/tcp. - LegacyKeyValueFormat:
LABEL key valueis rewritten asLABEL key=value,
asENValready was, and so are values with quotes or escapes, whose
whitespace is escaped. A value written across several lines keeps its line
breaks inside quotes. - NoEmptyContinuation: blank lines inside
ENV,LABELand other
continued instructions are removed (BuildKit ignores them, and will reject
them in a future release). Lines holding only\are kept.
Formatting
-
Arguments written one per line stay one per line: COPY and ADD sources,
and the elements of JSON arrays. The continued arguments of the first
command in a&&chain are indented like those of the commands after it.
A heredoc stays on the line of a single--mountflag. -
Shell bodies with several statements, such as the
set -eux; \style of
the official images, andif,for,caseand{ }blocks, are
formatted, with each statement on its own continued line ending in; \.
Statements written on one line stay on one line. -
Comments get a space after the
#:#commentbecomes# comment.
Parser directives,# check=lines, shebangs and banners such as
#####are left alone.#dockerfmt-ignoreworks too. -
Indentation with tabs:
--use-tabs,indent_style = tabin EditorConfig,
oruseTabs(orindent: 0, as prettier-plugin-sh passes) in JS. -
HEALTHCHECKis formatted: flags andCMD/NONEare normalized, the
command is formatted likeCMD's, andCMDstays on its own line when
written that way. -
Words in
ENV,LABEL,ARG,VOLUME,USERandSTOPSIGNALare
separated by single spaces, trailing whitespace is removed, and a space goes
before a line continuation that ends a word.VOLUME's JSON form is
normalized.
Fixes
- Quoted flag values (
--chown="my user") kept their quotes;--ending the
flags is kept. - Backquoted command substitutions are no longer rewritten as
$(...), which
could change what they run. - Stages built on a PowerShell stage or a Windows image are not formatted as
POSIX shell. - Blank lines after a comment are collapsed to one instead of deleted.
# dockerfmt-ignoreapplies only as the last comment before an
instruction.- Indented comments that would become
# syntax=or# check=directives
keep their indentation. - Flags and continuations use the file's escape character with
# escape=. <<-heredoc scripts are indented with tabs.- Many edge cases with comments, separators, stray carriage returns and
continuations at the end of the file.
Other changes
-reads stdin;versionreports the module version forgo install
builds.- EditorConfig property names are case-insensitive,
indent_size = tabuses
tab_width, and invalid settings are reported once as warnings. - The JS API validates its options, reuses one WASM instance, and has an
onFallbackoption. - The npm launcher passes signals through and explains launch failures.
- Release binaries include darwin/amd64; prereleases aren't tagged
latest.