Docker Compose未正确设置Secrets问题排查求助
我希望通过Docker Compose将一组Secrets设置为环境变量,但运行compose.yml时终端提示这些变量未被设置。我的配置和环境如下:
我的docker-compose.yml配置
version: '3.8' networks: aline-microservices: secrets: mysql-db: file: './secrets/MYSQL_DATABASE' mysql-pass: file: './secrets/MYSQL_PASSWORD' mysql-user: file: './secrets/MYSQL_USER' root-pass: file: './secrets/ROOT_PASSWORD' db-url: file: './secrets/DB_URL' jwt: file: './secrets/JWT_SECRET_KEY' secret-key: file: './secrets/SECRET_KEY' services: aline-mysql: image: mysql:8.0.33 ports: - 3307:3306 environment: - MYSQL_ROOT_PASSWORD: /run/secrets/root-pass - MYSQL_USER: /run/secrets/mysql-user - MYSQL_PASSWORD: /run/secrets/mysql-pass - MYSQL_DATABASE: aline-/run/secrets/mysql-db secrets: - root-pass - mysql-user - mysql-pass - mysql-db healthcheck: test: [ "CMD", 'mysqladmin', 'ping', '-h', 'localhost', '-u', 'root', '-p$MYSQL_ROOT_PASSWORD' ] interval: 30s timeout: 10s retries: 5
文件系统结构
Dockerfile docker-compose.yml secrets (folder) everything else
Secret文件内容
密码以纯字符串形式存储在./secrets/ROOT_PASSWORD等文件中,例如:
<实际密码内容>
请问我的配置是否存在错误?
问题分析与修复方案
你的配置存在几处明显错误,导致Secrets无法正确作为环境变量生效:
环境变量赋值语法错误
Docker Compose的environment字段中,列表形式的变量必须用KEY=VALUE格式,而你用了冒号:,这会导致变量无法被正确解析。正确写法是- MYSQL_ROOT_PASSWORD=/run/secrets/root-pass。MYSQL_DATABASE字段拼接错误
aline-/run/secrets/mysql-db这种写法不合法,Docker Compose不支持直接在环境变量值里拼接Secret路径。如果你的数据库名是aline-加上secret文件里的内容,需要通过自定义entrypoint脚本读取secret并拼接,或者直接在MYSQL_DATABASE的secret文件里写入完整的数据库名(比如aline-mydb)。Healthcheck的变量解析问题
Healthcheck的test用数组形式时,不会触发shell的变量替换,$MYSQL_ROOT_PASSWORD会被当作字符串直接传递,导致mysqladmin无法识别密码。可以改成shell形式的命令:test: "mysqladmin ping -h localhost -u root -p$(cat /run/secrets/root-pass)"或者直接读取secret文件内容,避免依赖环境变量。
Secret文件的换行符问题
如果创建secret文件时用了普通的echo "password" > file,文件末尾会多一个换行符,导致密码实际包含换行,引发验证失败。建议用echo -n "password" > ./secrets/ROOT_PASSWORD创建,确保没有多余换行。
修复后的docker-compose.yml示例
version: '3.8' networks: aline-microservices: secrets: mysql-db: file: './secrets/MYSQL_DATABASE' mysql-pass: file: './secrets/MYSQL_PASSWORD' mysql-user: file: './secrets/MYSQL_USER' root-pass: file: './secrets/ROOT_PASSWORD' db-url: file: './secrets/DB_URL' jwt: file: './secrets/JWT_SECRET_KEY' secret-key: file: './secrets/SECRET_KEY' services: aline-mysql: image: mysql:8.0.33 ports: - 3307:3306 environment: - MYSQL_ROOT_PASSWORD=/run/secrets/root-pass - MYSQL_USER=/run/secrets/mysql-user - MYSQL_PASSWORD=/run/secrets/mysql-pass - MYSQL_DATABASE=/run/secrets/mysql-db secrets: - root-pass - mysql-user - mysql-pass - mysql-db healthcheck: test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root -p$(cat /run/secrets/root-pass) || exit 1"] interval: 30s timeout: 10s retries: 5
注:如果确实需要拼接数据库名,需要编写自定义entrypoint脚本,在容器启动时读取secret并设置环境变量,再执行mysql的原始entrypoint。
内容的提问来源于stack exchange,提问作者skoleosho97

