Shell脚本如何配置容器resolv.conf

wen 实用脚本 2

Shell脚本如何配置容器resolv.conf:自动化DNS设置的完整指南

目录导读

  1. 容器DNS配置的核心原理

    Shell脚本如何配置容器resolv.conf

    • 为什么需要手动配置resolv.conf
    • Docker/Kubernetes中的DNS工作流
  2. Shell脚本配置的三种主流方法

    • 直接写入文件(基础版)
    • 通过容器启动参数传递(进阶版)
    • 动态DNS服务发现(高级版)
  3. 常见场景与脚本模板

    • 单容器DNS修改
    • 多容器批量配置
    • 与容器编排工具联动
  4. 常见问题与问答

    • Q1:为什么容器重启后resolv.conf会被重置?
    • Q2:如何保留自定义DNS不被覆盖?
  5. 最佳实践与安全注意事项


容器DNS配置的核心原理

为什么需要手动配置resolv.conf

容器默认继承宿主机的/etc/resolv.conf配置,但在以下场景必须自定义:

  • 企业内网: 需要公司内部DNS服务器(如168.1.100)解析内部域名
  • DevOps环境: 容器需要访问特定私有仓库(如registry.example.com
  • 多网卡路由: 容器在不同网络段需要不同DNS解析策略

Docker/Kubernetes中的DNS工作流

  • Docker默认行为: 每个容器启动时会从宿主机复制resolv.conf,并自动添加Docker的DNS转发规则。
  • Kubernetes Pod: 每个Pod的resolv.conf由kubelet通过--cluster-dns参数和dnsPolicy字段控制。
  • 关键点: 手动修改容器内的/etc/resolv.conf临时的——容器重启后会被宿主配置覆盖。

Shell脚本配置的三种主流方法

直接写入文件(基础版)

适用于已运行容器的临时修复。

#!/bin/bash
# 修改运行中的容器 resolv.conf
CONTAINER_ID="your_container_id"
NEW_DNS="8.8.8.8 1.1.1.1"
docker cp /dev/null $CONTAINER_ID:/etc/resolv.conf
docker exec $CONTAINER_ID sh -c "echo 'nameserver $NEW_DNS' > /etc/resolv.conf"

缺点: 容器重启后失效。

通过容器启动参数传递(进阶版)

永久生效: 在docker run时指定DNS。

#!/bin/bash
# 创建容器时自定义DNS
docker run -d \
  --dns 8.8.8.8 \
  --dns 1.1.1.1 \
  --dns-search example.com \
  --name mycontainer nginx

验证:

docker exec mycontainer cat /etc/resolv.conf
# 输出应为:
# nameserver 8.8.8.8
# nameserver 1.1.1.1
# search example.com

动态DNS服务发现(高级版)

结合环境变量动态生成配置:

#!/bin/bash
# 从环境变量读取DNS并写入容器
DNS_SERVERS=${CUSTOM_DNS:-"8.8.8.8,1.1.1.1"}
SEARCH_DOMAIN=${SEARCH_DOMAIN:-"internal.company.com"}
# 清理并写入新配置
echo "nameserver $(echo $DNS_SERVERS | tr ',' '\n')" > /tmp/new_resolv.conf
echo "search $SEARCH_DOMAIN" >> /tmp/new_resolv.conf
# 启动容器并挂载
docker run -d \
  -v /tmp/new_resolv.conf:/etc/resolv.conf:ro \
  --name dns_container nginx

常见场景与脚本模板

场景1:批量修改多个容器的DNS

#!/bin/bash
# 批量修改所有运行中容器的DNS
for container in $(docker ps -q); do
    docker exec $container sh -c \
    "cat > /etc/resolv.conf <<EOF
nameserver 192.168.1.100
nameserver 8.8.8.8
search svc.cluster.local
EOF"
done

场景2:Kubernetes Pod DNS定制(通过ConfigMap)

# k8s-pod-dns.yaml
apiVersion: v1
kind: Pod
metadata:
  name: custom-dns-pod
spec:
  dnsPolicy: "None"  # 完全自主控制
  dnsConfig:
    nameservers:
      - 10.0.0.10
      - 8.8.8.8
    searches:
      - ns1.svc.cluster.local
      - my.dns.search.suffix
  containers:
  - name: nginx
    image: nginx

常见问题与问答

Q1:为什么容器重启后resolv.conf会被重置?

答案:
容器镜像的/etc/resolv.conf本质是一个悬空链接(指向/proc/self/names...)。

  • Docker每次启动容器会自动从主机复制配置
  • Kubernetes的Pod重启后由kubelet重新生成
    解决方案: 使用docker run --dnskubectldnsConfig字段,而非手动修改文件。

Q2:如何保留自定义DNS不被覆盖?

答案:

  1. 永久方法: 通过启动参数或编排文件配置
  2. 临时方法: 挂载自定义文件(-v /custom_resolv:/etc/resolv.conf:ro
  3. 终极方案: 修改Docker守护进程配置(/etc/docker/daemon.json)全局覆盖:
    {
    "dns": ["192.168.1.100", "8.8.8.8"]
    }

最佳实践与安全注意事项

安全检查清单

  • 避免硬编码:将DNS服务器IP通过环境变量或外部配置文件传入
  • 回滚机制:每次修改前备份原文件
    cp /etc/resolv.conf /etc/resolv.conf.bak.$(date +%Y%m%d)
  • 权限控制:确保shell脚本以非root用户运行(使用sudo仅授予必要权限)

性能优化

  • 域名解析超时:在resolv.conf中添加options timeout:1 attempts:2减少等待
  • 多DNS冗余:至少配置两个nameserver,避免单点故障

跨平台兼容

  • Docker Desktop (Mac/Windows):DNS自动通过虚拟网络转发,不建议手动修改
  • Linux裸机容器:可直接操作/etc/resolv.conf,但需注意网络命名空间隔离

通过以上Shell脚本配置方法,你可以灵活管理容器的DNS解析行为,记住关键原则:启动时通过参数配置 > 运行时挂载覆盖 > 临时exec修改,实际生产环境中,优先使用Kubernetes的dnsConfig或Docker Compose的dns字段,避免直接操作文件系统。

抱歉,评论功能暂时关闭!