mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
Merge pull request #51507 from zhangguanzhang/fix-pause-restart
libnet: setupDNS: don't overwrite user-modified resolv.conf
This commit is contained in:
@@ -264,8 +264,17 @@ func (sb *Sandbox) loadResolvConf(path string) (*resolvconf.ResolvConf, error) {
|
||||
// be a copy of the host's file, with overrides for nameservers, options and search
|
||||
// domains applied.
|
||||
func (sb *Sandbox) setupDNS() error {
|
||||
// Make sure the directory exists.
|
||||
sb.restoreResolvConfPath()
|
||||
|
||||
// When the container is restarted, a new Sandbox is created but the same resolv.conf is re-used. If it was
|
||||
// user-modified, do not attempt to overwrite it.
|
||||
if !sb.config.useDefaultSandBox {
|
||||
if mod, err := resolvconf.UserModified(sb.config.resolvConfPath, sb.config.resolvConfHashFile); err != nil || mod {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the directory exists.
|
||||
dir, _ := filepath.Split(sb.config.resolvConfPath)
|
||||
if err := createBasePath(dir); err != nil {
|
||||
return err
|
||||
@@ -329,15 +338,7 @@ func (sb *Sandbox) rebuildDNS() error {
|
||||
// upstream nameservers.
|
||||
sb.setExternalResolvers(extNameServers)
|
||||
|
||||
// Write the file for the container - preserving old behaviour, not updating the
|
||||
// hash file (so, no further updates will be made).
|
||||
// TODO(robmry) - I think that's probably accidental, I can't find a reason for it,
|
||||
// and the old resolvconf.Build() function wrote the file but not the hash, which
|
||||
// is surprising. But, before fixing it, a guard/flag needs to be added to
|
||||
// sb.updateDNS() to make sure that when an endpoint joins a sandbox that already
|
||||
// has an internal resolver, the container's resolv.conf is still (re)configured
|
||||
// for an internal resolver.
|
||||
return rc.WriteFile(sb.config.resolvConfPath, "", filePerm)
|
||||
return rc.WriteFile(sb.config.resolvConfPath, sb.config.resolvConfHashFile, filePerm)
|
||||
}
|
||||
|
||||
func createBasePath(dir string) error {
|
||||
|
||||
@@ -14,12 +14,17 @@ import (
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func getResolvConfOptions(t *testing.T, rcPath string) []string {
|
||||
func getResolvConf(t *testing.T, rcPath string) resolvconf.ResolvConf {
|
||||
t.Helper()
|
||||
resolv, err := os.ReadFile(rcPath)
|
||||
assert.NilError(t, err)
|
||||
rc, err := resolvconf.Parse(bytes.NewBuffer(resolv), "")
|
||||
assert.NilError(t, err)
|
||||
return rc
|
||||
}
|
||||
|
||||
func getResolvConfOptions(t *testing.T, rcPath string) []string {
|
||||
rc := getResolvConf(t, rcPath)
|
||||
return rc.Options()
|
||||
}
|
||||
|
||||
@@ -90,3 +95,60 @@ func TestDNSOptions(t *testing.T) {
|
||||
dnsOptionsList = getResolvConfOptions(t, sb2.config.resolvConfPath)
|
||||
assert.Check(t, is.DeepEqual([]string{"ndots:0"}, dnsOptionsList))
|
||||
}
|
||||
|
||||
func TestNonHostNetDNSRestart(t *testing.T) {
|
||||
c, err := New(context.Background(), config.OptionDataDir(t.TempDir()))
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Step 1: Create initial sandbox (simulating first container start)
|
||||
sb, err := c.NewSandbox(context.Background(), "cnt1")
|
||||
assert.NilError(t, err)
|
||||
|
||||
defer func() {
|
||||
_ = sb.Delete(context.Background())
|
||||
}()
|
||||
|
||||
sb.startResolver(false)
|
||||
|
||||
err = sb.setupDNS()
|
||||
assert.NilError(t, err)
|
||||
err = sb.rebuildDNS()
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Step 2: Simulate user manually overwriting the container's resolv.conf
|
||||
resolvConfPath := sb.config.resolvConfPath
|
||||
modifiedContent := []byte(`nameserver 1.1.1.1`)
|
||||
err = os.WriteFile(resolvConfPath, modifiedContent, 0644)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Step 3: Delete the sandbox (simulating container stop)
|
||||
err = sb.Delete(context.Background())
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Step 4: Create a new sandbox (simulating container restart)
|
||||
sbRestart, err := c.NewSandbox(context.Background(), "cnt1",
|
||||
OptionResolvConfPath(resolvConfPath),
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
defer func() {
|
||||
if err := sbRestart.Delete(context.Background()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
sbRestart.startResolver(false)
|
||||
|
||||
// Step 5: Call setupDNS on restart - should preserve user modifications
|
||||
err = sbRestart.setupDNS()
|
||||
assert.NilError(t, err)
|
||||
|
||||
rc := getResolvConf(t, sbRestart.config.resolvConfPath)
|
||||
assert.Check(t, is.Equal("1.1.1.1", rc.NameServers()[0].String()))
|
||||
|
||||
// Step 6: Call rebuildDNS on restart - should preserve user modifications
|
||||
err = sbRestart.rebuildDNS()
|
||||
assert.NilError(t, err)
|
||||
|
||||
rc = getResolvConf(t, sbRestart.config.resolvConfPath)
|
||||
assert.Check(t, is.Equal("1.1.1.1", rc.NameServers()[0].String()))
|
||||
}
|
||||
|
||||
@@ -366,6 +366,11 @@ func (sb *Sandbox) populateNetworkResourcesOS(ctx context.Context, ep *Endpoint)
|
||||
|
||||
if ep.needResolver() {
|
||||
sb.startResolver(false)
|
||||
} else {
|
||||
// Make sure /etc/resolv.conf is set up.
|
||||
if err := sb.updateDNS(ep.getNetwork().enableIPv6); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if i != nil && i.srcName != "" {
|
||||
@@ -448,10 +453,6 @@ func (sb *Sandbox) populateNetworkResourcesOS(ctx context.Context, ep *Endpoint)
|
||||
}
|
||||
|
||||
sb.addHostsEntries(ctx, ep.getEtcHostsAddrs())
|
||||
// Make sure /etc/resolv.conf is set up.
|
||||
if err := sb.updateDNS(ep.getNetwork().enableIPv6); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Populate load balancer only after updating all the other
|
||||
// information including gateway and other routes so that
|
||||
|
||||
Reference in New Issue
Block a user