You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

在GitHub Actions中通过动态生成文件传递Secrets到Docker容器时遇到解析异常

在GitHub Actions中通过动态生成文件传递Secrets到Docker容器时遇到解析异常

我明白你遇到的问题了——核心原因是GitHub Actions的表达式解析时机:它只会在工作流执行前,解析yaml文件里直接写的${{ ... }}表达式,不会去处理动态生成的文件内容里的这类表达式。

你第一个脚本能正常工作,是因为yaml里的${{ secrets.TEST_1 }}在工作流启动前就被替换成了真实的secret值;但当你把${{ secrets.TEST_1 }}写到txt文件里再读取时,GitHub Actions不会再去解析这个字符串,只会原样传递,所以容器里拿到的就是字面量${{ secrets.TEST_1 }}

下面给你几个可行的解决方案,你可以根据自己的需求选择:

方案1:生成文件时直接写入真实的Secret值

既然你用Node脚本动态生成文件,那完全可以在生成阶段就把Secret值替换进去,而不是写GitHub Actions表达式。

GitHub Actions会自动把仓库Secrets注入到环境变量中(变量名和Secret名称一致,全大写),你可以在Node脚本里直接读取这些环境变量,写入文件:

const fs = require('fs');

// 处理Secret中的单引号,避免shell语法错误
const escapeSingleQuotes = (str) => str.replace(/'/g, "\\'");

const envVars = [
  `TEST_1='${escapeSingleQuotes(process.env.TEST_1)}'`,
  `TEST_2='${escapeSingleQuotes(process.env.TEST_2)}'`,
  `GITHUB_USER='${escapeSingleQuotes(process.env.TEST_1)}'`,
  `GITHUB_REPO_NAME='${escapeSingleQuotes(process.env.TEST_2)}'`
].join(' ');

fs.writeFileSync('ss-build-files/output-docker-compose-github-secrets.txt', envVars);

这样生成的文件里就是真实的Secret值,后续cat出来拼接命令时,自然会传递正确的值到容器。

方案2:在GitHub Actions中直接构建环境变量字符串

如果不想生成文件,也可以在shell脚本里直接循环构建需要的环境变量字符串,利用Shell的变量间接引用功能:

- name: Backend - Build Container (dynamic env vars)
  run: |
    # 初始化环境变量字符串
    ENV_VARS=""
    
    # 循环需要的Secret键,拼接变量
    for secret_key in TEST_1 TEST_2; do
      # ${!secret_key} 是Shell间接引用,获取对应环境变量的值
      ENV_VARS+="$secret_key='${!secret_key}' "
    done
    
    # 添加映射的其他变量
    ENV_VARS+="GITHUB_USER='${TEST_1}' GITHUB_REPO_NAME='${TEST_2}' "
    
    # 构建完整的远程执行脚本
    BACKEND_CONTAINER_SH_SCRIPT="${ENV_VARS}docker-compose -f ss-build-files/ubuntu-container-build.yml up -d && docker-compose -f ss-build-files/ubuntu-container-build.yml logs; exit;"
    
    # 执行远程命令
    ssh -v -t -t -i id_rsa_ssh_key_server_temp.pem -o StrictHostKeyChecking=no ubuntu@${{ env.CONFIG_SERVER_IP }} "$BACKEND_CONTAINER_SH_SCRIPT"

方案3:使用Docker Compose的env_file(更推荐)

这是更符合Docker最佳实践的方式:不要在命令行前拼接环境变量,而是用env_file让Docker Compose自动读取变量。

  1. 在GitHub Actions中生成.env文件(直接写入真实Secret值):
- name: Generate .env file
  run: |
    cat > ss-build-files/.env << EOF
    TEST_1=${{ secrets.TEST_1 }}
    TEST_2=${{ secrets.TEST_2 }}
    GITHUB_USER=${{ secrets.TEST_1 }}
    GITHUB_REPO_NAME=${{ secrets.TEST_2 }}
    EOF
  1. 修改你的ubuntu-container-build.yml,添加env_file配置:
services:
  # 你的服务名称
  your-backend-service:
    # 其他配置...
    env_file: ./ss-build-files/.env
  1. 远程执行时,只需运行docker-compose up -d即可,不需要在命令前拼接变量:
- name: Backend - Build Container
  run: |
    BACKEND_CONTAINER_SH_SCRIPT="docker-compose -f ss-build-files/ubuntu-container-build.yml up -d && docker-compose -f ss-build-files/ubuntu-container-build.yml logs; exit;"
    ssh -v -t -t -i id_rsa_ssh_key_server_temp.pem -o StrictHostKeyChecking=no ubuntu@${{ env.CONFIG_SERVER_IP }} "$BACKEND_CONTAINER_SH_SCRIPT"

额外注意事项

  • 特殊字符处理:如果你的Secret包含单引号、空格或其他Shell特殊字符,一定要记得转义,否则会导致Shell语法错误(方案1里的escapeSingleQuotes函数就是干这个的)。
  • 安全性:不要在日志中输出Secret值,GitHub Actions会自动屏蔽Secrets,但如果自己手动echo生成的文件内容,可能会泄露敏感信息,一定要注意。

备注:内容来源于stack exchange,提问作者Jorge Mauricio

火山引擎 最新活动