使用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路径,但问题仍然存在。
原因分析
- 命名卷特性误解:Docker命名卷是独立于本地文件系统的容器存储,不会自动将本地目录的文件同步到卷中。你配置的
vault-scripts命名卷默认是空的,容器内/vault/scripts目录下没有实际脚本文件。 - Windows换行符冲突:Windows系统下保存的Shell脚本默认使用CRLF换行符,而Linux容器中的
sh无法识别该格式,会触发类似"文件未找到"的错误。 - 脚本权限不足:本地脚本可能未设置可执行权限,导致容器内无法直接运行。
- 脚本逻辑冲突:
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"
验证步骤
- 清理现有容器和卷:
docker-compose down -v - 重新启动服务:
docker-compose up -d - 查看容器日志:
docker logs vault,确认脚本执行正常、Vault启动成功
内容的提问来源于stack exchange,提问作者Nicolas Pierre
相关产品推荐
相关产品推荐

