docker “sh -c”是做什么的?

9wbgstp7  于 2022-11-22  发布在  Docker
关注(0)|答案(3)|浏览(1545)

我正在尝试在我的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"]

wtzytmuj

wtzytmuj1#

这里的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

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

通过运行envsubst命令从模板文件/etc/nginx/conf.d/configfile.temp生成/etc/nginx/conf.d/default.conf;有关详细信息,请参阅它的manual page。($PORT中美元符号前面的反斜杠实际上不是该命令的一部分;它是必需的,因为封闭字符串是由Docker解释的,Docker有自己的变量替换机制,如果美元符号没有转义,它将在构建时替换该值;我们不希望出现这种情况。)

&&

是一个命令分隔符,表示只有在前一个命令成功时才继续。换句话说,a && b运行a,如果a没有失败,则运行b。(成功或失败是通过检查a的退出代码来确定的,在运行另一个外部命令之前,该退出代码也暂时存在于shell变量$?中。)

nginx -g 'daemon off;'

以字符串作为-g选项的参数来运行nginx。同样,有关详细信息,请参考man page

gpnt7bae

gpnt7bae2#

sh -c只是意味着你给你的shell(sh)一个命令作为参数来执行。在你的例子中,就像是在docker示例envsubst '\$PORT' < /etc/nginx/conf.d/configfile.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'上输入一个终端。
要从Docker示例运行节点**,请使用

RUN node server.js

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

ha5z0ras

ha5z0ras3#

具体到这个设置,有三个答案:

永远没有理由使用CMD sh -c '...'@tripleee的答案描述了一般情况下何时需要sh -c。不过,Dockerfile CMD指令有两种形式,如果使用它的shell形式(命令不是JSON数组),Docker会自动为您插入sh -c Package 器。也就是说,您可以简化为

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 image已经知道如何运行此envsubst命令(在该页面中搜索“Using environment variables in nginx configuration”),基本映像已经有一个CMD可以启动Nginx。您根本不需要这个冗长的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应用程序。**它使用multi-stage build首先将应用程序编译为静态文件,然后将这些文件复制到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来代理一个服务器端应用程序,你需要在一个单独的容器中运行它。

相关问题