[ docker-ce源码分析系列 ] 修改resolv.conf文件被还原的原因

1 概述:

1.1 环境

版本信息如下:
a、操作系统: centos 7.6,amd64
b、服务器docker版本:v18.09.2


2 resolv.conf文件被还原的现象:

容器中的/etc/resolv.conf文件,是由宿主机/var/lib/docker/containers/xxxx/resolv.conf文件挂载。在docker restart容器之前,手动修改了/var/lib/docker/containers/xxxx/resolv.conf文件,却发现变更的内容并没有出现在容器中的/etc/resolv.conf文件中。原因是/var/lib/docker/containers/xxxx/resolv.conf文件的内容会被覆盖,而后挂载进容器中。
[ docker-ce源码分析系列 ] 修改resolv.conf文件被还原的原因_第1张图片


3 源码简析:

3.1 containerStart

initializeNetworking( )是本文章的重点,/var/lib/docker/containers/xxxx/resolv.conf文件的内容就是在此处被覆盖。

func (daemon *Daemon) containerStart(container *container.Container, checkpoint string, checkpointDir string, resetRestartManager bool) (err error) {
	/*
		其他代码
	*/

	// 初始化网络
	if err := daemon.initializeNetworking(container); err != nil {
		return err
	}

	/*
		其他代码
	*/

	// 创建容器
	err = daemon.containerd.Create(context.Background(), container.ID, spec, createOptions)

	// 启动容器
	pid, err := daemon.containerd.Start(context.Background(), container.ID, checkpointDir,
		container.StreamConfig.Stdin() != nil || container.Config.Tty,
		container.InitializeStdio)

	return nil

3.2 initializeNetworking

func (daemon *Daemon) initializeNetworking(container *container.Container) error {
	/*
		其他代码
	*/

	if err := daemon.allocateNetwork(container); err != nil {
		return err
	}

	return container.BuildHostnameFile()
}

3.3 allocateNetwork

func (daemon *Daemon) allocateNetwork(container *container.Container) error {
	/*
		其他代码
	*/
	defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName()
	if nConf, ok := container.NetworkSettings.Networks[defaultNetName]; ok {
		if err := daemon.connectToNetwork(container, defaultNetName, nConf.EndpointSettings, updateSettings); err != nil {
			return err
		}

	}
	
	/*
		其他代码
	*/
	
	return nil
}

3.4 connectToNetwork

func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (err error) {
	/*
		其他代码
	*/

	if sb == nil {
		
		// 创建sanbox
		sb, err = controller.NewSandbox(container.ID, options...)
		
		/*
			其他代码
		*/
	}
	/*
		其他代码
	*/
	return nil
}

3.5 NewSandbox

func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (Sandbox, error) {
	
	/*
		其他代码
	*/

	var sb *sandbox
	
	sb = &sandbox{
			id:                 sandboxID,
			containerID:        containerID,
			endpoints:          []*endpoint{},
			epPriority:         map[string]int{},
			populatedEndpoints: map[string]struct{}{},
			config:             containerConfig{},
			controller:         c,
			extDNS:             []extDNSEntry{},
		}
	
	// setupResolutionFiles(  )会初始化DNS相关的设置
	if err = sb.setupResolutionFiles(); err != nil {
		return nil, err
	}

	/*
		其他代码
	*/

	return sb, nil
}

3.6 setupResolutionFiles

func (sb *sandbox) setupResolutionFiles() error {
	/*
		其他代码
	*/

	return sb.setupDNS()
}

3.7 setupDNS

func (sb *sandbox) setupDNS() error {
	
	/*
		其他代码
	*/
	
	// newRC.Content是宿主机/etc/resolv.conf文件的内容(可能过滤部分内容)
	// 将newRC.Content写到/var/lib/docker/containers/xxxx/resolv.conf文件
	if err := ioutil.WriteFile(sb.config.resolvConfPath, newRC.Content, filePerm); err != nil {
	}

	/*
		其他代码
	*/

	return nil
}

4 总结:

修改/var/lib/docker/containers/xxxx/resolv.conf文件的内容后重启容器,并不能起到变更容器/etc/resolv.conf文件的目的,因为将其挂载进容器之前,内容会被覆盖。

你可能感兴趣的:(docker,docker)