Docker-compose脚本中如何转义bash命令里的美元符号$
解决Docker Compose中Nginx配置$符号丢失的问题
问题原因
你遇到的是多层Shell转义导致的$符号解析丢失:你的command里嵌套了两层Bash调用(bash -c 内部又用bash -s <<EOF),每一层都会解析$符号,所以原本的转义方式不足以保留最终需要的$1。
解决方案
方案1:增加转义层级(适配原有嵌套结构)
把rewrite行的/$$1改成/$$$$1,这样经过两层Shell解析后,最终写入nginx.conf的就是$1:
app-reverse-proxy: image: nginx:1.23 ports: - "9090:80" command: | bash -c 'bash -s << EOF cat > /etc/nginx/nginx.conf << EON daemon off; user www-data; events { worker_connections 1024; } http { gzip on; gzip_disable "msie6"; include /etc/nginx/mime.types; server { listen 80; root /var/www/html; index index.html; location ^~ /rooturl/ { proxy_pass http://other-app:8080; rewrite /rooturl(.*) /$$$$1 break; } } } EON nginx EOF' depends_on: - other-app networks: - docker-net
- 解析逻辑:最外层
bash -c会把$$$$解析为$$,内部bash -s再把$$解析为$,最终得到$1。
方案2:简化Shell调用(更易维护)
去掉多余的bash -s <<EOF嵌套,直接在bash -c里写命令,这样只需要一次转义(\$1)就能保留$1:
app-reverse-proxy: image: nginx:1.23 ports: - "9090:80" command: | bash -c ' cat > /etc/nginx/nginx.conf <<EON daemon off; user www-data; events { worker_connections 1024; } http { gzip on; gzip_disable "msie6"; include /etc/nginx/mime.types; server { listen 80; root /var/www/html; index index.html; location ^~ /rooturl/ { proxy_pass http://other-app:8080; rewrite /rooturl(.*) /\$1 break; } } } EON nginx ' depends_on: - other-app networks: - docker-net
方案3:无需rewrite,用proxy_pass路径直接实现前缀移除
更简洁的方式:在proxy_pass末尾加上/,Nginx会自动去掉/rooturl/前缀,把剩余路径转发到后端:
app-reverse-proxy: image: nginx:1.23 ports: - "9090:80" command: | bash -c ' cat > /etc/nginx/nginx.conf <<EON daemon off; user www-data; events { worker_connections 1024; } http { gzip on; gzip_disable "msie6"; include /etc/nginx/mime.types; server { listen 80; root /var/www/html; index index.html; location ^~ /rooturl/ { proxy_pass http://other-app:8080/; } } } EON nginx ' depends_on: - other-app networks: - docker-net
- 效果:比如请求
http://localhost:9090/rooturl/path/to/api会被转发到http://other-app:8080/path/to/api,完全满足你的需求,还避免了$符号转义的麻烦。
内容的提问来源于stack exchange,提问作者João Pedro Schmitt
相关产品推荐
相关产品推荐

