我正在尝试在我的 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"]
这里
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
选项的参数。同样,请参阅手册页了解详细信息。
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/
具体到此设置,三个答案:
永远没有理由使用
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 Hubnginx
图像已经知道如何运行此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 代理服务器端应用程序,则需要在单独的容器中运行它。 您在单独的问题中询问此问题。
我还发现,如果您直接在 shell 外部调用“rm”(例如,从“cargo make”任务或 java),文件掩码不起作用(至少对于“rm”)。 但有了 'sh' 一切都正常。