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

使用Docker Compose命名卷仍找不到Vault初始化脚本

问题:Docker Compose启动Vault时找不到初始化脚本

问题现象

启动Vault容器时持续出现以下错误:

/bin/sh: /vault/scripts/init-vault.sh: not found
/bin/sh: /vault/scripts/init-vault.sh: not found

本地已确认services/vault/scripts/init-vault.sh脚本存在,且配置了命名卷vault-scripts挂载到容器内/vault/scripts路径,但问题仍然存在。

原因分析

  1. 命名卷特性误解:Docker命名卷是独立于本地文件系统的容器存储,不会自动将本地目录的文件同步到卷中。你配置的vault-scripts命名卷默认是空的,容器内/vault/scripts目录下没有实际脚本文件。
  2. Windows换行符冲突:Windows系统下保存的Shell脚本默认使用CRLF换行符,而Linux容器中的sh无法识别该格式,会触发类似"文件未找到"的错误。
  3. 脚本权限不足:本地脚本可能未设置可执行权限,导致容器内无法直接运行。
  4. 脚本逻辑冲突:init-vault.sh中先执行了前台运行的vault server命令,后续初始化代码无法执行;同时Docker Compose的command字段又重复启动了vault server,逻辑矛盾。

解决方案

1. 替换命名卷为绑定挂载

将vault-scripts命名卷改为绑定挂载,直接映射本地脚本目录到容器内:
修改docker-compose.yml中Vault服务的volumes配置:

volumes:
  - vault-data:/vault/data
  - vault-logs:/vault/logs
  # 替换命名卷为绑定挂载,直接映射本地脚本目录
  - ./services/vault/scripts:/vault/scripts

同时删除volumes定义中的vault-scripts条目:

volumes:
  consul-data:
    external: ${USE_EXTERNAL_VOLUMES:-false}
    name: ${CONSUL_DATA_VOLUME:-consul-data}
  vault-data:
    external: ${USE_EXTERNAL_VOLUMES:-false}
    name: ${VAULT_DATA_VOLUME:-vault-data}
  vault-logs:
    external: ${USE_EXTERNAL_VOLUMES:-false}
    name: ${VAULT_LOGS_VOLUME:-vault-logs}
# 删除以下无效的命名卷配置
#  vault-scripts:
#    external: ${USE_EXTERNAL_VOLUMES:-false}
#    name: ${VAULT_SCRIPTS_VOLUME:-vault-scripts}

2. 修复脚本换行符格式

将init-vault.sh的换行符改为Linux兼容的LF格式:

  • VS Code:点击右下角的"CRLF"按钮,切换为"LF"
  • PowerShell命令:
    (Get-Content .\services\vault\scripts\init-vault.sh) -replace "`r`n", "`n" | Set-Content .\services\vault\scripts\init-vault.sh -Force
    
  • Git Bash/WSL命令:
    sed -i 's/\r$//' ./services/vault/scripts/init-vault.sh
    

3. 添加脚本执行权限

在本地给脚本添加可执行权限(通过Git Bash或WSL执行):

chmod +x ./services/vault/scripts/init-vault.sh

4. 修正脚本启动逻辑

修改init-vault.sh,将vault server改为后台启动,确保后续初始化代码能执行,最后保持容器运行:

#!/bin/bash
# init-vault.sh

# 加载策略函数
load_policies() {
    local token=$1
    
    vault login "$token"
    
    echo "Loading policies..."
    vault policy write admin /vault/policies/admin.hcl
    vault policy write readonly /vault/policies/readonly.hcl
}

# 后台启动Vault server
vault server -config=/vault/config/vault.hcl &
VAULT_PID=$!

# 等待Consul就绪
until curl -fs http://localhost:8500/v1/status/leader > /dev/null; do
    echo "Waiting for Consul to be ready..."
    sleep 2
done

# 等待Vault启动完成
until curl -fs http://localhost:8200/v1/sys/health > /dev/null; do
    echo "Waiting for Vault to start..."
    sleep 2
done

# 检查Vault是否已初始化
if ! vault status > /dev/null 2>&1; then
    echo "Initializing Vault..."
    
    # 初始化Vault
    init_output=$(vault operator init \
        -key-shares=5 \
        -key-threshold=3 \
        -format=json)

    # 保存初始化信息到Vault
    echo "$init_output" | vault kv put secret/init-keys keys=- 

    # 提取根令牌和解封密钥
    root_token=$(echo "$init_output" | jq -r '.root_token')
    unseal_key_1=$(echo "$init_output" | jq -r '.unseal_keys_b64[0]')
    unseal_key_2=$(echo "$init_output" | jq -r '.unseal_keys_b64[1]')
    unseal_key_3=$(echo "$init_output" | jq -r '.unseal_keys_b64[2]')

    # 解封Vault
    vault operator unseal "$unseal_key_1"
    vault operator unseal "$unseal_key_2"
    vault operator unseal "$unseal_key_3"

    # 加载策略
    load_policies "$root_token"

    # 启用OIDC认证
    vault auth enable oidc

    # 配置Microsoft Entra ID OIDC
    vault write auth/oidc/config \
        oidc_discovery_url="https://login.microsoftonline.com/${ENTRA_TENANT_ID}/v2.0" \
        oidc_client_id="${ENTRA_CLIENT_ID}" \
        oidc_client_secret="${ENTRA_CLIENT_SECRET}" \
        default_role="readonly"

    # 创建管理员角色
    vault write auth/oidc/role/admin \
        bound_audiences="${ENTRA_CLIENT_ID}" \
        allowed_redirect_uris="${VAULT_REDIRECT_URIS}" \
        user_claim="email" \
        groups_claim="groups" \
        bound_claims="groups=${ENTRA_ADMIN_GROUP_ID}" \
        policies="admin" \
        ttl=1h \
        max_ttl=24h

    # 创建只读角色
    vault write auth/oidc/role/readonly \
        bound_audiences="${ENTRA_CLIENT_ID}" \
        allowed_redirect_uris="${VAULT_REDIRECT_URIS}" \
        user_claim="email" \
        groups_claim="groups" \
        bound_claims="groups=${ENTRA_READONLY_GROUP_ID}" \
        policies="readonly" \
        ttl=1h \
        max_ttl=8h

    echo "Vault初始化完成,请从secret/init-keys中保存根令牌和解封密钥"
    
else
    echo "Vault已初始化"
fi

# 启用审计日志
vault audit enable file file_path=/vault/logs/audit.log

echo "Vault配置完成"

# 等待Vault后台进程,保持容器运行
wait $VAULT_PID

同时修改Docker Compose中Vault服务的command,移除重复的vault server启动命令:

entrypoint: sh -c
command: "/vault/scripts/init-vault.sh"

验证步骤

  1. 清理现有容器和卷:docker-compose down -v
  2. 重新启动服务:docker-compose up -d
  3. 查看容器日志:docker logs vault,确认脚本执行正常、Vault启动成功

内容的提问来源于stack exchange,提问作者Nicolas Pierre

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 12:00:55