【问题标题】:Nginx container fails to start on Cloud RunNginx 容器无法在 Cloud Run 上启动
【发布时间】:2019-10-12 13:19:00
【问题描述】:

我正在尝试在 Cloud Run 上使用 Nginx 提供简单的静态页面。但是容器无法正确开始服务。

容器正在启动,如从docker-entrypoint.sh 回显的调试行所示:

2019-05-26T22:19:02.340289Z testing config
2019-05-26T22:19:02.433935Z nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
2019-05-26T22:19:02.434903Z nginx: configuration file /etc/nginx/nginx.conf test is successful
2019-05-26T22:19:02.436605Z starting on 8080
2019-05-26T22:19:02.487188Z2019/05/26 22:19:02 [alert] 6#6: prctl(PR_SET_DUMPABLE) failed (22: Invalid argument)

并最终终止

2019-05-26T22:20:00.153060259ZContainer terminated by the container manager on signal 9.

为了符合Cloud Run service contract 专门监听$PORT 的要求,docker-entrypoint.sh 执行$PORT substitution in conf.d/*.conf

FROM nginx:1.15-alpine

COPY nginx-default.conf.template /etc/nginx/conf.d/default.conf.template

COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]

我很确定问题在于 docker-entrypoint.sh,因为一旦 $PORT 被硬编码为 8080 并且图像看起来像这样:

FROM nginx:1.15-alpine

COPY nginx-default.conf /etc/nginx/conf.d/default.conf

Cloud Run“运行”正常。

执行替换的代码:

export NGINX_PORT=${PORT:-8080}
for f in $(find /etc/nginx/conf.d/ -type f -name '*.conf'); do
  envsubst '$NGINX_PORT' < $f > $f
done

注意:读取&lt; $f 和写入&gt; $f 到同一个文件的工作方式与本地运行容器的测试结果相同。

预期

  • nginx 配置将$PORT 占位符替换为实际值
  • 容器在 Cloud Run 上运行并在 $PORT 上侦听

实际

  • 容器无法在 Cloud Run 上运行
  • 容器在本地运行并侦听 $PORT

【问题讨论】:

  • 您的脚本 (/docker-entrypoint.sh) 是否以类似于 #!/bin/bash 的 shebang 开头?
  • 在你的代码中你的问题是 COPY nginx-default.conf.template /etc/nginx/conf.d/default.conf.template .... 你是不是意思...配置文件的正确目的地?那如何成为真正的 nginx 配置文件?
  • 你的假设是错误的。不要这样做NOTE: reading &lt; $f and writing &gt; $f
  • 相反,对您的文件进行就地编辑,如下所示:sed -i 's/80/${PORT}/g' filename。这是一个示例,不是为您的配置文件编写的。
  • 你是说问题解决了吗?

标签: google-cloud-run


【解决方案1】:

通过替换修复

for f in $(find /etc/nginx/conf.d/ -type f -name '*.conf'); do
  envsubst '$NGINX_PORT' < $f > $f
done

sed -i "s/\${NGINX_PORT}/${NGINX_PORT}/g" /etc/nginx/conf.d/*.conf

并在 *.conf 文件中更改 $NGINX_PORT -> ${NGINX_PORT} 以避免替换歧义

【讨论】:

  • 你可以在你的答案之前和之后添加一个被改变的行的例子吗?仔细检查您的sed 行。您正在替换完全相同的项目。错字?
  • 不是错字:0. 假设环境变量NGINX_PORT 设置为8080 1. substitution 在双引号" 内,它首先被shell 解释,变成@987654331 @ 2. 注意 '\$' 转义了阻止替换模式以匹配的符号
  • 我的眼镜呢?我错过了转义字符。
【解决方案2】:

我发表了一篇博文来展示如何在 Cloud Run 容器中运行 nginx(以及一个进程)。

您可以在此处阅读文章:https://ahmet.im/blog/cloud-run-multiple-processes-easy-way/ 或查看代码库https://github.com/ahmetb/multi-process-container-lazy-solution

基本上,nginx.conf 文件应该是这样的:

events {}

http {
    server {
        listen 8080; # Cloud Run PORT env variable
        access_log /dev/stdout;
        error_log /dev/stdout;

        # if you need to serve static access, specify an absolute path like below
        location /static/ {
            alias /src/static/;
        }

        # anything else is routed to your app that you would start on port 8081
        location / {
            proxy_pass http://localhost:8081;
        }
    }
}

daemon off;
pid /run/nginx.pid;

您可以在 nginx.conf 中安全地硬编码端口 8080,因为它在可预见的未来不太可能在 Cloud Run 上发生变化。

【讨论】:

  • 这应该是公认的答案。我在这个问题上浪费了很多时间,却不知道 Cloud Run 上的应用程序只能在 8080 端口上运行。
  • 您现在实际上可以在 Cloud Run 中指定自定义端口号。无需为端口号更改 nginx.conf。
  • 我实际上尝试过,但容器运行状况检查一直失败,直到我在我的应用程序中将端口硬编码为 8080,并且我在 Cloud Run 中添加了与自定义端口相同的端口。不知道我是否错过了那里的任何东西。
猜你喜欢
  • 2020-04-18
  • 2021-12-26
  • 1970-01-01
  • 2022-01-27
  • 1970-01-01
  • 2020-05-20
  • 2021-05-24
  • 2021-06-13
  • 1970-01-01
相关资源
最近更新 更多