In Dockerfiles, commands can be specified either as a single string or as a JSON array of strings. The latter is called an "exec form". However, when exec form is not a valid JSON, it will be silently treated as shell form. Usually, this will lead to a crash, but sometimes it can pass silently and lead to unexpected behavior.

Why is this an issue?

Some tricky issues with exec form include having symbols after the closing bracket (silently passes with Docker earlier than 27.1.0) or using incorrect symbol for quotes within a JSON array. In these cases, the exec form will be treated as shell form, and the build will pass, but the command will not be executed as expected, because the whole string will be passed to a shell.

How to fix it

Code examples

Noncompliant code example

FROM alpine:3.14
ENTRYPOINT ["/app", "-c", "config.json"] -D
FROM alpine:3.14
ENTRYPOINT [ "/bin/bash”, “-c” ]

Compliant solution

FROM alpine:3.14
ENTRYPOINT ["/app", "-c", "config.json", "-D"]
FROM alpine:3.14
ENTRYPOINT [ "/bin/bash", "-c" ]

Resources

Documentation