Docker Stack部署报错:网络名称不符合DNS组件规范问题排查
执行docker stack deploy -c docker-compose.yaml mynetwork时出现错误,创建网络mynetwork_失败,提示名称需为有效的DNS名称组件。使用Docker Secrets管理network_name等变量时触发该错误,不使用Secrets则正常;已尝试重启Docker、清理所有容器、网络、服务及镜像,问题仍未解决。
项目结构
项目包含.scripts目录(内含schema.sql和data.sql)、docker-compose.yaml配置文件、部署脚本文件。
docker-compose.yaml配置
version: "3.3" services: database: image: mysql:8 command: --default-authentication-plugin=mysql_native_password environment: MYSQL_USER: ${mysql_user} MYSQL_PASSWORD: ${mysql_password} MYSQL_ROOT_PASSWORD: ${mysql_root_password} ports: - "6033:3306" networks: - ${network_name} volumes: - dbdata:/var/lib/mysql - "./.scripts/schema.sql:/docker-entrypoint-initdb.d/1.sql" - "./.scripts/data.sql:/docker-entrypoint-initdb.d/2.sql" secrets: - mysql_user - mysql_password - mysql_root_password - container_name - network_name secrets: mysql_user: file: /run/secrets/mysql_user mysql_password: file: /run/secrets/mysql_password mysql_root_password: file: /run/secrets/mysql_root_password network_name: file: /run/secrets/network_name networks: ${network_name}: driver: bridge
部署脚本
#!/bin/bash # Leave current swarm docker swarm leave --force # Initialize the host as a Swarm manager docker swarm init # Create the secrets echo "server_user" | docker secret create mysql_user - echo "server_password" | docker secret create mysql_password - echo "a1128f69-e6f7-4e93-a2df-3d4db6030abc" | docker secret create mysql_root_password - echo "template_network" | docker secret create network_name - # Deploy the stack using the secrets docker stack deploy -c docker-compose.yaml mynetwork
错误日志
Node left the swarm. Swarm initialized: current node (y46rjvlu57bibyhgwk7nthykw) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-161prfq442ha035laq1plnv1o2qfqs026dmg6aslpd4kao7o0i-bnwc5zxiwt3ctmfbxfoszbick 192.168.65.3:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. l3nrkqhy7ygtrb05x7c5rvavu xrhp70n50waaas1hqha8fk2j2 wj1y8runsi8vydpzc09hp9bmp u5b6suutp7tkt4lqd5i90bgif Creating network mynetwork_ failed to create network mynetwork_: Error response from daemon: rpc error: code = InvalidArgument desc = name must be valid as a DNS name component
核心原因
Docker Secrets无法用于解析docker-compose.yaml中的顶层配置变量(如网络、服务名称)。Secrets的作用域仅局限于容器内部运行时,部署阶段Docker无法从Secrets读取network_name的值,导致变量未被替换,最终尝试创建名称为mynetwork_(栈名+下划线)的无效网络。
修复步骤
改用环境变量传递网络名称:将
network_name从Secrets移到部署脚本的环境变量中,部署时传递给docker stack deploy。修改部署脚本:#!/bin/bash # Leave current swarm docker swarm leave --force # Initialize the host as a Swarm manager docker swarm init # 定义网络名称变量 export network_name="template_network" # Create the secrets(移除network_name相关的secret创建) echo "server_user" | docker secret create mysql_user - echo "server_password" | docker secret create mysql_password - echo "a1128f69-e6f7-4e93-a2df-3d4db6030abc" | docker secret create mysql_root_password - # Deploy the stack,通过环境变量传递network_name docker stack deploy -c docker-compose.yaml mynetwork调整docker-compose.yaml:移除
secrets中的network_name配置,确保networks和services中的${network_name}能被环境变量正确解析:version: "3.3" services: database: image: mysql:8 command: --default-authentication-plugin=mysql_native_password environment: MYSQL_USER: ${mysql_user} MYSQL_PASSWORD: ${mysql_password} MYSQL_ROOT_PASSWORD: ${mysql_root_password} ports: - "6033:3306" networks: - ${network_name} volumes: - dbdata:/var/lib/mysql - "./.scripts/schema.sql:/docker-entrypoint-initdb.d/1.sql" - "./.scripts/data.sql:/docker-entrypoint-initdb.d/2.sql" secrets: - mysql_user - mysql_password - mysql_root_password secrets: mysql_user: file: /run/secrets/mysql_user mysql_password: file: /run/secrets/mysql_password mysql_root_password: file: /run/secrets/mysql_root_password networks: ${network_name}: driver: bridge验证部署:重新执行部署脚本,此时
network_name会被环境变量正确替换,Docker将创建名为mynetwork_template_network的合法网络(栈名+网络名)。
优化建议
- 区分配置层级:顶层配置(如网络、服务名称、卷名称)使用环境变量传递,容器运行时敏感数据(如密码、用户名)使用Docker Secrets。
- 避免冗余配置:无需在容器
secrets字段添加network_name,它不属于容器运行时需要的敏感数据。 - 添加状态检查:部署前可增加Swarm状态检查,避免重复执行
swarm init导致异常。
内容的提问来源于stack exchange,提问作者HopefulSplash

