如何修复Docker Compose文件中的坏替换错误?

huangapple go评论69阅读模式
英文:

How can I fix bad substitution error inside docker-compose file?

问题

如何在docker-compose文件中运行/bin/bash循环?
它显示错误的替换,并且我不确定是否还有其他需要转义的字符。

environment:
  domains: (x.com,y.com)

entrypoint:
  - /bin/sh
  - -c
  - |
    curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf > "/etc/letsencrypt/options-ssl-nginx.conf"
    echo $$email
    curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem > "/etc/letsencrypt/ssl-dhparams.pem"
    ls -la /etc/letsencrypt/
    echo $$domains
    for domain in $${domains[@]}; do
      echo $$domain
    done    
英文:

How to run a /bin/bash for loop inside docker-compose file?
It's saying bad substitution error, and I'm not sure if there is another character to escape.

environment:
      domains: (x.com,y.com)

entrypoint:
      - /bin/sh
      - -c
      - |
        curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf > "/etc/letsencrypt/options-ssl-nginx.conf"        echo $$email
        curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem > "/etc/letsencrypt/ssl-dhparams.pem"
        ls -la /etc/letsencrypt/
        echo $$domains
        for domain in $${domains[@]}; do
          echo $$domain
        done

答案1

得分: 1

以下是您要翻译的内容:

未来,请包含足够的 docker-compose.yaml 部分,以便我们实际复制问题。我认为我知道问题出在哪里,但由于您的问题没有显示您正在使用的映像,所以只是一个基于经验的猜测。

您的 entrypoint 脚本正在使用 Bash 特定的功能(具体来说是数组)。尽管在许多 Linux 发行版上,/bin/sh 是指向 /bin/bash 的符号链接,但这并不是普遍适用的。在基于 Debian 的发行版,包括 Ubuntu,在 /bin/sh 中使用的是更传统的 Bourne-shell 实现,没有 Bash 中的额外功能。

如果在您的 docker-compose.yaml 中使用 fedora:38,其中 /bin/sh 实际上是 Bash,它会运行而不会出错(尽管它不会按您的意图执行);循环的输出如下:

example_1  | (x.com,y.com)

另一方面,如果我使用 ubuntu:22.04,我会得到您在问题中描述的错误:

example_1  | /bin/sh: 5: Bad substitution

为了使事情正常工作,我们首先需要处理逻辑错误 - 如上所示,当使用 Bash 时,脚本运行时不会出现错误,但实际上它不会将您的 domains 变量视为数组。

有两个问题:首先,Bash 数组语法使用空格而不是逗号来分隔项目;其次,在任何情况下,都不能将环境变量视为数组。但没关系,因为我们根本不需要数组变量!如果我们将 docker-compose.yaml 文件写成这样:

services:
  example:
    image: ubuntu:22.04
    environment:
      domains: "x.com y.com"
    entrypoint:
      - /bin/sh
      - -c
      - |
        for domain in $domains; do
          echo $domain
        done

那么输出将是:

x.com
y.com

这正是我们想要的。这不需要任何特定于 Bash 的语法,这意味着无论使用哪个发行版,您都可以安全地使用 /bin/sh

英文:

In the future, please include enough of your docker-compose.yaml for us to actually reproduce the problem. I think I know what the problem is, but because your question doesn't show what image you're using it's just an educated guess.

Your entrypoint script is using Bash-specific features (specifically, arrays). While on many Linux distributions, /bin/sh is a symlink to /bin/bash, this isn't universally true. On Debian-derived distributions, including Ubuntu, /bin/sh is a more traditional Bourne-shell implementation without the extra features available in Bash.

If use fedora:38 in your docker-compose.yaml, in which /bin/sh is actually Bash, it runs without errors (although it doesn't perform as you intend); the output of the loop is:

example_1  | (x.com,y.com)

On the other hand, if I use ubuntu:22.04, I get the error you've described in your question:

example_1  | /bin/sh: 5: Bad substitution

To get things working, we first need to deal with logic error -- as we saw above, when using Bash, the script runs without an error, but it doesn't actually treat your domains variable as an array.

There are two problems: first, Bash array syntax uses whitespace, rather than commas, to separate items; and second, you can't treat an environment variable as an array in any case. But that's okay, because we don't need an array variable at all! If we write the docker-compose.yaml file like this:

services:
  example:
    image: ubuntu:22.04
    environment:
      domains: "x.com y.com"
    entrypoint:
      - /bin/sh
      - -c
      - |
        for domain in $$domains; do
          echo $$domain
        done

Then the output is:

x.com
y.com

Which is what we want. This doesn't require any bash-specific syntax, which means you can safely use /bin/sh regardless of what distribution you're using.

huangapple
  • 本文由 发表于 2023年5月29日 20:44:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76357504.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定