运行 bash -c 和 运行 的开放形式的区别
Difference between RUN bash -c and open form of RUN
一些 Dockerfile 有
RUN bash -c "apt-get update -qq && ... \"
而其他人则没有引号,例如
RUN apt-get update -qq && ... \
这些变体之间有什么区别?其中一个比另一个更受欢迎吗?
您应该只写 RUN apt-get update ...
而无需手动插入 sh -c
包装器。
RUN
、CMD
和 ENTRYPOINT
指令都共享相同的语法。最好为 ENTRYPOINT
记录,但所有三个命令的工作方式相同。有两种方法可以为它们编写命令:您可以提供一组特定的命令字作为 JSON 数组 (exec form), or you can write a string and Docker will automatically wrap it sh -c
(shell form)。例如:
# Create a directory with a space in its name
RUN mkdir "a directory"
# JSON-array form: each array element is a shell word
RUN ["ls", "-ld", "a directory"]
# String form: Docker provides a shell, so these two are equivalent
RUN ls -ld 'a directory'
RUN ["/bin/sh", "-c", "ls -ld 'a directory'"]
这使您的第一种形式变得多余:如果您 RUN bash -c '...'
,它是一个字符串,Docker 会自动将其包装在 sh -c
中。这样你就生效了
# RUN bash -c '...'
RUN ["/bin/sh", "-c", "bash -c '...'"]
GNU bash 有许多不是 POSIX-standard 语法的扩展,并且可能 运行 遇到这些问题,特别是在 Alpine-based 图像上 /bin/sh
是 BusyBox 工具集中的最小值 shell。我可以将此视为使用 bash 而不是默认 shell 将 shell 命令强制为 运行 的尝试。对于 Docker 文件中出现的大多数内容,它们通常不会复杂到无法用标准语法轻松重写的程度。
# Needs bash for the non-standard `source` syntax
RUN bash -c 'source ./venv/bin/activate && pip list'
# But you can use the standard `.` instead
RUN . ./venv/bin/activate && pip list
如果你必须有bash解释RUN
行,那么我建议使用SHELL
指令来改变使用的命令解释裸字符串。
Style-wise,我偶尔也会看到 JSON-array 以显式 CMD ["/bin/sh", "-c", "..."]
开头的语法。没有理由把它写出来;使用字符串形式更短,同样清晰。
一些 Dockerfile 有
RUN bash -c "apt-get update -qq && ... \"
而其他人则没有引号,例如
RUN apt-get update -qq && ... \
这些变体之间有什么区别?其中一个比另一个更受欢迎吗?
您应该只写 RUN apt-get update ...
而无需手动插入 sh -c
包装器。
RUN
、CMD
和 ENTRYPOINT
指令都共享相同的语法。最好为 ENTRYPOINT
记录,但所有三个命令的工作方式相同。有两种方法可以为它们编写命令:您可以提供一组特定的命令字作为 JSON 数组 (exec form), or you can write a string and Docker will automatically wrap it sh -c
(shell form)。例如:
# Create a directory with a space in its name
RUN mkdir "a directory"
# JSON-array form: each array element is a shell word
RUN ["ls", "-ld", "a directory"]
# String form: Docker provides a shell, so these two are equivalent
RUN ls -ld 'a directory'
RUN ["/bin/sh", "-c", "ls -ld 'a directory'"]
这使您的第一种形式变得多余:如果您 RUN bash -c '...'
,它是一个字符串,Docker 会自动将其包装在 sh -c
中。这样你就生效了
# RUN bash -c '...'
RUN ["/bin/sh", "-c", "bash -c '...'"]
GNU bash 有许多不是 POSIX-standard 语法的扩展,并且可能 运行 遇到这些问题,特别是在 Alpine-based 图像上 /bin/sh
是 BusyBox 工具集中的最小值 shell。我可以将此视为使用 bash 而不是默认 shell 将 shell 命令强制为 运行 的尝试。对于 Docker 文件中出现的大多数内容,它们通常不会复杂到无法用标准语法轻松重写的程度。
# Needs bash for the non-standard `source` syntax
RUN bash -c 'source ./venv/bin/activate && pip list'
# But you can use the standard `.` instead
RUN . ./venv/bin/activate && pip list
如果你必须有bash解释RUN
行,那么我建议使用SHELL
指令来改变使用的命令解释裸字符串。
Style-wise,我偶尔也会看到 JSON-array 以显式 CMD ["/bin/sh", "-c", "..."]
开头的语法。没有理由把它写出来;使用字符串形式更短,同样清晰。