“sh -c”有什么作用?

问题描述 投票:0回答:4

我正在尝试在我的 Express 应用程序中使用 nginx,并且我正在按照此处的教程进行操作

https://cloud.google.com/community/tutorials/deploy-react-nginx-cloud-run

最后我看到了这个命令

CMD sh -c "envsubst '\$PORT' < /etc/nginx/conf.d/configfile.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"

请问上面的命令是做什么的?

最具体地说,

"envsubst '\$PORT' < /etc/nginx/conf.d/configfile.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
有什么作用?

另外,如何在上面的命令之后运行另一个命令,因为我似乎不能有多个

CMD
语句。我需要在最后一个命令之后运行以下命令

CMD["node","server.js"]

node.js docker unix sh google-cloud-run
4个回答
2
投票

这里

sh -c
的目的已经准确的说是在一条语句中运行多个命令。
-c
之后的字符串可以包含任意数量的命令,由命令分隔符分隔。只需添加更多即可,任意数量。

CMD sh -c "envsubst '\$PORT' < /etc/nginx/conf.d/configfile.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;' && node server.js"

在某些时候,随着命令行变得越来越复杂,将命令放入文件中,

COPY
放入容器中,然后简单地将该文件作为您的
CMD
,会更有意义。您也可以在您的
Dockerfile
;

中创建它
RUN printf '%s\n' >cmd.sh \
    "envsubst '\$PORT' < /etc/nginx/conf.d/configfile.template > /etc/nginx/conf.d/default.conf &&" \
    "nginx -g 'daemon off;' &&" \
    "node server.js"
# ...
CMD ["sh", "cmd.sh"]

至于这些命令的作用,

envsubst '\$PORT' < /etc/nginx/conf.d/configfile.template > /etc/nginx/conf.d/default.conf

通过运行

/etc/nginx/conf.d/default.conf
命令从模板文件
/etc/nginx/conf.d/configfile.temp
生成
envsubst
;有关详细信息,请参阅其手册页。 (
$PORT
中美元符号之前的反斜杠实际上并不是命令的一部分;它是必需的,因为封闭的字符串由 Docker 解释,Docker 有自己的变量替换机制,如果美元符号在构建时会替换该值,标志没有被转义;我们不想在这里。)

&&

是一个命令分隔符,表示仅在上一个命令成功时才继续。换句话说,

a && b
运行
a
,如果
b
没有失败,则运行
a
。 (成功或失败是通过检查
a
中的退出代码来确定的,该退出代码在 shell 变量
$?
中也暂时可用,直到您运行另一个外部命令。)

nginx -g 'daemon off;'

运行

nginx
,并将字符串作为
-g
选项的参数。同样,请参阅手册页了解详细信息。


1
投票

sh -c
只是意味着你给你的 shell (sh) 一个命令来作为参数执行。 在你的情况下,这就像在 docker 实例上的终端中输入
envsubst '\$PORT' < /etc/nginx/conf.d/configfile.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'
` 此行设置容器的 nginx 配置。

要从 您的 docker 实例运行节点 ,请使用

RUN node server.js

我建议快速阅读有关 Docker 运行和 cmd 命令的内容:https://www.geeksforgeeks.org/difference- Between-run-vs-cmd-vs-entrypoint-docker-commands/


1
投票

具体到此设置,三个答案:

永远没有理由使用

CMD sh -c '...'
@tripleee 的回答描述了一般情况下您何时需要
sh -c
。 不过,Dockerfile
CMD
指令有两种形式,如果您使用其 shell 形式(该命令不是 JSON 数组),那么 Docker 会自动为您插入
sh -c
包装器。 也就是说,您可以将其简化为

CMD envsubst '$PORT' < /etc/nginx/conf.d/configfile.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'

少一级引用。

nginx
图像已经知道如何执行此操作。从Nginx 1.19开始,Docker Hub
nginx
图像
已经知道如何运行此
envsubst
命令(在该页面中搜索“在nginx中使用环境变量”配置”),并且基础镜像已经有一个启动 Nginx 的
CMD
。 所以如果你把模板化的配置文件放在正确的位置,就根本不需要这么啰嗦
CMD

从您链接到的页面复制并调整完整的 Dockerfile:

FROM node:14-alpine as react-build
...
FROM nginx:alpine
COPY nginx.conf /etc/nginx/templates/default.conf.template
# NOTE: different path    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

COPY --from=react-build /app/build /usr/share/nginx/html
ENV PORT 8080
ENV HOST 0.0.0.0
EXPOSE 8080
# No CMD in this derived Dockerfile

此设置构建一个静态 React 应用程序。它使用多阶段构建首先将应用程序编译为静态文件,然后将其复制到 Nginx 映像中。

FROM node:14-alpine as react-build
WORKDIR /app
...
RUN yarn build

FROM nginx:alpine
COPY --from=react-build /app/build /usr/share/nginx/html

如果您需要使用 Nginx 代理服务器端应用程序,则需要在单独的容器中运行它。 您在单独的问题中询问此问题。


0
投票

我还发现,如果您直接在 shell 外部调用“rm”(例如,从“cargo make”任务或 java),文件掩码不起作用(至少对于“rm”)。 但有了 'sh' 一切都正常。

© www.soinside.com 2019 - 2024. All rights reserved.