You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将自定义脚本嵌入provectuslabs/kafka-ui镜像并解决执行问题

Kafka UI + Docker Swarm Secrets 配置问题解决

问题背景

使用provectuslabs/kafka-ui:v0.7.1镜像,想通过自定义脚本读取Docker Swarm Secrets(路径/run/secrets/),把形如DOCKER-SECRET->kafka_ui_user的模板变量替换为真实密钥值。过程中遇到两个问题:

  1. 启动容器时报错exec /script.sh: no such file or directory
  2. 安装bash后脚本能运行,但Kafka UI依旧使用Compose里的模板变量,不识别转换后的环境变量

初始Dockerfile:

FROM provectuslabs/kafka-ui:v0.7.1

USER root
COPY script.sh /script.sh
RUN chmod +x /script.sh

EXPOSE 8080

ENTRYPOINT ["/script.sh"]

CMD ["/bin/sh" "-c" "java --add-opens java.rmi/javax.rmi.ssl=ALL-UNNAMED  $JAVA_OPTS -jar kafka-ui-api.jar"]

自定义密钥解析脚本script.sh:

#!/bin/bash

env_secret_expand() {
    var="$1"
    eval val=\$$var
    if secret_name=$(expr match "$val" "DOCKER-SECRET->\([^}]\+\)$"); then
        secret="${ENV_SECRETS_DIR}/${secret_name}"
        if [ -f "$secret" ]; then
            val=$(cat "${secret}")
            export "$var"="$val"
        fi
    fi
}

env_secrets_expand() {
    for env_var in $(printenv | cut -f1 -d"=")
    do
        env_secret_expand $env_var
    done
}

env_secrets_expand

添加RUN apk add --no-cache bash后脚本可运行,但变量替换未生效。

解决方案

1. 解决脚本找不到的错误

报错原因是镜像默认使用ash shell,而脚本指定了#!/bin/bash但镜像未安装bash。两种修复方式:

  • 在Dockerfile中添加RUN apk add --no-cache bash(已做)
  • 或者把脚本的shebang改为#!/bin/sh(需确保脚本语法兼容ash)

2. 确保Kafka UI读取替换后的环境变量

核心问题是当前脚本执行完后没有正确启动Kafka UI,导致新环境变量没被JVM进程继承。需要修改脚本和Dockerfile的ENTRYPOINT/CMD配置:

步骤1:更新脚本script.sh

在脚本末尾添加命令执行逻辑,保证信号能传递到Kafka UI进程:

#!/bin/bash

env_secret_expand() {
    var="$1"
    eval val=\$$var
    if secret_name=$(expr match "$val" "DOCKER-SECRET->\([^}]\+\)$"); then
        # 设置默认Secrets路径,避免依赖环境变量
        secret="${ENV_SECRETS_DIR:-/run/secrets}/${secret_name}"
        if [ -f "$secret" ]; then
            val=$(cat "${secret}")
            export "$var"="$val"
        fi
    fi
}

env_secrets_expand() {
    for env_var in $(printenv | cut -f1 -d"=")
    do
        env_secret_expand $env_var
    done
}

env_secrets_expand

# 执行后续启动命令,用exec替换当前shell,保证信号传递
exec "$@"

步骤2:修正Dockerfile

调整CMD格式,避免使用sh -c(会创建子shell,导致环境变量传递问题):

FROM provectuslabs/kafka-ui:v0.7.1

USER root
# 安装bash以支持脚本
RUN apk add --no-cache bash
COPY script.sh /script.sh
RUN chmod +x /script.sh

EXPOSE 8080

ENTRYPOINT ["/script.sh"]
# 使用数组格式传递启动命令,直接启动JVM
CMD ["java", "--add-opens", "java.rmi/javax.rmi.ssl=ALL-UNNAMED", "-jar", "kafka-ui-api.jar"]

关键要点

  • exec "$@"会把ENTRYPOINT后的CMD参数作为当前进程执行,确保Kafka UI能继承脚本设置的环境变量,同时接收Docker的停止信号
  • 去掉sh -c包装,直接用java命令的数组格式,避免环境变量在子shell中丢失
  • 给ENV_SECRETS_DIR设置默认值/run/secrets,增强脚本鲁棒性

内容的提问来源于stack exchange,提问作者Михаил Васильев

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 20:08:10