Browse code

Move DNS options to hostconfig

The local resolver warning needed to be moved at daemon start because it
was only show for the first container started anyways before having a
default value set.
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)

Michael Crosby authored on 2014/04/08 11:12:22
Showing 9 changed files
... ...
@@ -19,8 +19,6 @@ func Compare(a, b *Config) bool {
19 19
 		return false
20 20
 	}
21 21
 	if len(a.Cmd) != len(b.Cmd) ||
22
-		len(a.Dns) != len(b.Dns) ||
23
-		len(a.DnsSearch) != len(b.DnsSearch) ||
24 22
 		len(a.Env) != len(b.Env) ||
25 23
 		len(a.PortSpecs) != len(b.PortSpecs) ||
26 24
 		len(a.ExposedPorts) != len(b.ExposedPorts) ||
... ...
@@ -34,16 +32,6 @@ func Compare(a, b *Config) bool {
34 34
 			return false
35 35
 		}
36 36
 	}
37
-	for i := 0; i < len(a.Dns); i++ {
38
-		if a.Dns[i] != b.Dns[i] {
39
-			return false
40
-		}
41
-	}
42
-	for i := 0; i < len(a.DnsSearch); i++ {
43
-		if a.DnsSearch[i] != b.DnsSearch[i] {
44
-			return false
45
-		}
46
-	}
47 37
 	for i := 0; i < len(a.Env); i++ {
48 38
 		if a.Env[i] != b.Env[i] {
49 39
 			return false
... ...
@@ -25,8 +25,6 @@ type Config struct {
25 25
 	StdinOnce       bool // If true, close stdin after the 1 attached client disconnects.
26 26
 	Env             []string
27 27
 	Cmd             []string
28
-	Dns             []string
29
-	DnsSearch       []string
30 28
 	Image           string // Name of the image as it was passed by the operator (eg. could be symbolic)
31 29
 	Volumes         map[string]struct{}
32 30
 	VolumesFrom     string
... ...
@@ -66,12 +64,6 @@ func ContainerConfigFromJob(job *engine.Job) *Config {
66 66
 	if Cmd := job.GetenvList("Cmd"); Cmd != nil {
67 67
 		config.Cmd = Cmd
68 68
 	}
69
-	if Dns := job.GetenvList("Dns"); Dns != nil {
70
-		config.Dns = Dns
71
-	}
72
-	if DnsSearch := job.GetenvList("DnsSearch"); DnsSearch != nil {
73
-		config.DnsSearch = DnsSearch
74
-	}
75 69
 	if Entrypoint := job.GetenvList("Entrypoint"); Entrypoint != nil {
76 70
 		config.Entrypoint = Entrypoint
77 71
 	}
... ...
@@ -163,32 +163,18 @@ func TestCompare(t *testing.T) {
163 163
 	volumes1 := make(map[string]struct{})
164 164
 	volumes1["/test1"] = struct{}{}
165 165
 	config1 := Config{
166
-		Dns:         []string{"1.1.1.1", "2.2.2.2"},
167
-		DnsSearch:   []string{"foo", "bar"},
168
-		PortSpecs:   []string{"1111:1111", "2222:2222"},
169
-		Env:         []string{"VAR1=1", "VAR2=2"},
170
-		VolumesFrom: "11111111",
171
-		Volumes:     volumes1,
172
-	}
173
-	config2 := Config{
174
-		Dns:         []string{"0.0.0.0", "2.2.2.2"},
175
-		DnsSearch:   []string{"foo", "bar"},
176 166
 		PortSpecs:   []string{"1111:1111", "2222:2222"},
177 167
 		Env:         []string{"VAR1=1", "VAR2=2"},
178 168
 		VolumesFrom: "11111111",
179 169
 		Volumes:     volumes1,
180 170
 	}
181 171
 	config3 := Config{
182
-		Dns:         []string{"1.1.1.1", "2.2.2.2"},
183
-		DnsSearch:   []string{"foo", "bar"},
184 172
 		PortSpecs:   []string{"0000:0000", "2222:2222"},
185 173
 		Env:         []string{"VAR1=1", "VAR2=2"},
186 174
 		VolumesFrom: "11111111",
187 175
 		Volumes:     volumes1,
188 176
 	}
189 177
 	config4 := Config{
190
-		Dns:         []string{"1.1.1.1", "2.2.2.2"},
191
-		DnsSearch:   []string{"foo", "bar"},
192 178
 		PortSpecs:   []string{"0000:0000", "2222:2222"},
193 179
 		Env:         []string{"VAR1=1", "VAR2=2"},
194 180
 		VolumesFrom: "22222222",
... ...
@@ -197,24 +183,11 @@ func TestCompare(t *testing.T) {
197 197
 	volumes2 := make(map[string]struct{})
198 198
 	volumes2["/test2"] = struct{}{}
199 199
 	config5 := Config{
200
-		Dns:         []string{"1.1.1.1", "2.2.2.2"},
201
-		DnsSearch:   []string{"foo", "bar"},
202 200
 		PortSpecs:   []string{"0000:0000", "2222:2222"},
203 201
 		Env:         []string{"VAR1=1", "VAR2=2"},
204 202
 		VolumesFrom: "11111111",
205 203
 		Volumes:     volumes2,
206 204
 	}
207
-	config6 := Config{
208
-		Dns:         []string{"1.1.1.1", "2.2.2.2"},
209
-		DnsSearch:   []string{"foos", "bars"},
210
-		PortSpecs:   []string{"1111:1111", "2222:2222"},
211
-		Env:         []string{"VAR1=1", "VAR2=2"},
212
-		VolumesFrom: "11111111",
213
-		Volumes:     volumes1,
214
-	}
215
-	if Compare(&config1, &config2) {
216
-		t.Fatalf("Compare should return false, Dns are different")
217
-	}
218 205
 	if Compare(&config1, &config3) {
219 206
 		t.Fatalf("Compare should return false, PortSpecs are different")
220 207
 	}
... ...
@@ -224,9 +197,6 @@ func TestCompare(t *testing.T) {
224 224
 	if Compare(&config1, &config5) {
225 225
 		t.Fatalf("Compare should return false, Volumes are different")
226 226
 	}
227
-	if Compare(&config1, &config6) {
228
-		t.Fatalf("Compare should return false, DnsSearch are different")
229
-	}
230 227
 	if !Compare(&config1, &config1) {
231 228
 		t.Fatalf("Compare should return true")
232 229
 	}
... ...
@@ -237,7 +207,6 @@ func TestMerge(t *testing.T) {
237 237
 	volumesImage["/test1"] = struct{}{}
238 238
 	volumesImage["/test2"] = struct{}{}
239 239
 	configImage := &Config{
240
-		Dns:         []string{"1.1.1.1", "2.2.2.2"},
241 240
 		PortSpecs:   []string{"1111:1111", "2222:2222"},
242 241
 		Env:         []string{"VAR1=1", "VAR2=2"},
243 242
 		VolumesFrom: "1111",
... ...
@@ -247,7 +216,6 @@ func TestMerge(t *testing.T) {
247 247
 	volumesUser := make(map[string]struct{})
248 248
 	volumesUser["/test3"] = struct{}{}
249 249
 	configUser := &Config{
250
-		Dns:       []string{"2.2.2.2", "3.3.3.3"},
251 250
 		PortSpecs: []string{"3333:2222", "3333:3333"},
252 251
 		Env:       []string{"VAR2=3", "VAR3=3"},
253 252
 		Volumes:   volumesUser,
... ...
@@ -257,15 +225,6 @@ func TestMerge(t *testing.T) {
257 257
 		t.Error(err)
258 258
 	}
259 259
 
260
-	if len(configUser.Dns) != 3 {
261
-		t.Fatalf("Expected 3 dns, 1.1.1.1, 2.2.2.2 and 3.3.3.3, found %d", len(configUser.Dns))
262
-	}
263
-	for _, dns := range configUser.Dns {
264
-		if dns != "1.1.1.1" && dns != "2.2.2.2" && dns != "3.3.3.3" {
265
-			t.Fatalf("Expected 1.1.1.1 or 2.2.2.2 or 3.3.3.3, found %s", dns)
266
-		}
267
-	}
268
-
269 260
 	if len(configUser.ExposedPorts) != 3 {
270 261
 		t.Fatalf("Expected 3 ExposedPorts, 1111, 2222 and 3333, found %d", len(configUser.ExposedPorts))
271 262
 	}
... ...
@@ -14,6 +14,8 @@ type HostConfig struct {
14 14
 	PortBindings    nat.PortMap
15 15
 	Links           []string
16 16
 	PublishAllPorts bool
17
+	Dns             []string
18
+	DnsSearch       []string
17 19
 }
18 20
 
19 21
 func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
... ...
@@ -30,6 +32,11 @@ func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
30 30
 	if Links := job.GetenvList("Links"); Links != nil {
31 31
 		hostConfig.Links = Links
32 32
 	}
33
-
33
+	if Dns := job.GetenvList("Dns"); Dns != nil {
34
+		hostConfig.Dns = Dns
35
+	}
36
+	if DnsSearch := job.GetenvList("DnsSearch"); DnsSearch != nil {
37
+		hostConfig.DnsSearch = DnsSearch
38
+	}
34 39
 	return hostConfig
35 40
 }
... ...
@@ -94,25 +94,6 @@ func Merge(userConf, imageConf *Config) error {
94 94
 	if userConf.Cmd == nil || len(userConf.Cmd) == 0 {
95 95
 		userConf.Cmd = imageConf.Cmd
96 96
 	}
97
-	if userConf.Dns == nil || len(userConf.Dns) == 0 {
98
-		userConf.Dns = imageConf.Dns
99
-	} else {
100
-		dnsSet := make(map[string]struct{}, len(userConf.Dns))
101
-		for _, dns := range userConf.Dns {
102
-			dnsSet[dns] = struct{}{}
103
-		}
104
-		for _, dns := range imageConf.Dns {
105
-			if _, exists := dnsSet[dns]; !exists {
106
-				userConf.Dns = append(userConf.Dns, dns)
107
-			}
108
-		}
109
-	}
110
-	if userConf.DnsSearch == nil || len(userConf.DnsSearch) == 0 {
111
-		userConf.DnsSearch = imageConf.DnsSearch
112
-	} else {
113
-		//duplicates aren't an issue here
114
-		userConf.DnsSearch = append(userConf.DnsSearch, imageConf.DnsSearch...)
115
-	}
116 97
 	if userConf.Entrypoint == nil || len(userConf.Entrypoint) == 0 {
117 98
 		userConf.Entrypoint = imageConf.Entrypoint
118 99
 	}
... ...
@@ -213,8 +213,6 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
213 213
 		AttachStderr:    flAttach.Get("stderr"),
214 214
 		Env:             envVariables,
215 215
 		Cmd:             runCmd,
216
-		Dns:             flDns.GetAll(),
217
-		DnsSearch:       flDnsSearch.GetAll(),
218 216
 		Image:           image,
219 217
 		Volumes:         flVolumes.GetMap(),
220 218
 		VolumesFrom:     strings.Join(flVolumesFrom.GetAll(), ","),
... ...
@@ -230,6 +228,8 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
230 230
 		PortBindings:    portBindings,
231 231
 		Links:           flLinks.GetAll(),
232 232
 		PublishAllPorts: *flPublishAll,
233
+		Dns:             flDns.GetAll(),
234
+		DnsSearch:       flDnsSearch.GetAll(),
233 235
 	}
234 236
 
235 237
 	if sysInfo != nil && flMemory > 0 && !sysInfo.SwapLimit {
... ...
@@ -430,6 +430,12 @@ func (container *Container) Start() (err error) {
430 430
 		}
431 431
 	}()
432 432
 
433
+	if container.ResolvConfPath == "" {
434
+		if err := container.setupContainerDns(); err != nil {
435
+			return err
436
+		}
437
+	}
438
+
433 439
 	if err := container.Mount(); err != nil {
434 440
 		return err
435 441
 	}
... ...
@@ -1174,3 +1180,50 @@ func (container *Container) DisableLink(name string) {
1174 1174
 		}
1175 1175
 	}
1176 1176
 }
1177
+
1178
+func (container *Container) setupContainerDns() error {
1179
+	var (
1180
+		config  = container.hostConfig
1181
+		runtime = container.runtime
1182
+	)
1183
+	resolvConf, err := utils.GetResolvConf()
1184
+	if err != nil {
1185
+		return err
1186
+	}
1187
+	// If custom dns exists, then create a resolv.conf for the container
1188
+	if len(config.Dns) > 0 || len(runtime.config.Dns) > 0 || len(config.DnsSearch) > 0 || len(runtime.config.DnsSearch) > 0 {
1189
+		var (
1190
+			dns       = utils.GetNameservers(resolvConf)
1191
+			dnsSearch = utils.GetSearchDomains(resolvConf)
1192
+		)
1193
+		if len(config.Dns) > 0 {
1194
+			dns = config.Dns
1195
+		} else if len(runtime.config.Dns) > 0 {
1196
+			dns = runtime.config.Dns
1197
+		}
1198
+		if len(config.DnsSearch) > 0 {
1199
+			dnsSearch = config.DnsSearch
1200
+		} else if len(runtime.config.DnsSearch) > 0 {
1201
+			dnsSearch = runtime.config.DnsSearch
1202
+		}
1203
+		container.ResolvConfPath = path.Join(container.root, "resolv.conf")
1204
+		f, err := os.Create(container.ResolvConfPath)
1205
+		if err != nil {
1206
+			return err
1207
+		}
1208
+		defer f.Close()
1209
+		for _, dns := range dns {
1210
+			if _, err := f.Write([]byte("nameserver " + dns + "\n")); err != nil {
1211
+				return err
1212
+			}
1213
+		}
1214
+		if len(dnsSearch) > 0 {
1215
+			if _, err := f.Write([]byte("search " + strings.Join(dnsSearch, " ") + "\n")); err != nil {
1216
+				return err
1217
+			}
1218
+		}
1219
+	} else {
1220
+		container.ResolvConfPath = "/etc/resolv.conf"
1221
+	}
1222
+	return nil
1223
+}
... ...
@@ -24,6 +24,7 @@ import (
24 24
 	"github.com/dotcloud/docker/utils"
25 25
 	"io"
26 26
 	"io/ioutil"
27
+	"log"
27 28
 	"os"
28 29
 	"path"
29 30
 	"regexp"
... ...
@@ -393,9 +394,6 @@ func (runtime *Runtime) Create(config *runconfig.Config, name string) (*Containe
393 393
 	if err := runtime.createRootfs(container, img); err != nil {
394 394
 		return nil, nil, err
395 395
 	}
396
-	if err := runtime.setupContainerDns(container, config); err != nil {
397
-		return nil, nil, err
398
-	}
399 396
 	if err := container.ToDisk(); err != nil {
400 397
 		return nil, nil, err
401 398
 	}
... ...
@@ -572,53 +570,6 @@ func (runtime *Runtime) createRootfs(container *Container, img *image.Image) err
572 572
 	return nil
573 573
 }
574 574
 
575
-func (runtime *Runtime) setupContainerDns(container *Container, config *runconfig.Config) error {
576
-	resolvConf, err := utils.GetResolvConf()
577
-	if err != nil {
578
-		return err
579
-	}
580
-	if len(config.Dns) == 0 && len(runtime.config.Dns) == 0 && utils.CheckLocalDns(resolvConf) {
581
-		runtime.config.Dns = DefaultDns
582
-	}
583
-
584
-	// If custom dns exists, then create a resolv.conf for the container
585
-	if len(config.Dns) > 0 || len(runtime.config.Dns) > 0 || len(config.DnsSearch) > 0 || len(runtime.config.DnsSearch) > 0 {
586
-		var (
587
-			dns       = utils.GetNameservers(resolvConf)
588
-			dnsSearch = utils.GetSearchDomains(resolvConf)
589
-		)
590
-		if len(config.Dns) > 0 {
591
-			dns = config.Dns
592
-		} else if len(runtime.config.Dns) > 0 {
593
-			dns = runtime.config.Dns
594
-		}
595
-		if len(config.DnsSearch) > 0 {
596
-			dnsSearch = config.DnsSearch
597
-		} else if len(runtime.config.DnsSearch) > 0 {
598
-			dnsSearch = runtime.config.DnsSearch
599
-		}
600
-		container.ResolvConfPath = path.Join(container.root, "resolv.conf")
601
-		f, err := os.Create(container.ResolvConfPath)
602
-		if err != nil {
603
-			return err
604
-		}
605
-		defer f.Close()
606
-		for _, dns := range dns {
607
-			if _, err := f.Write([]byte("nameserver " + dns + "\n")); err != nil {
608
-				return err
609
-			}
610
-		}
611
-		if len(dnsSearch) > 0 {
612
-			if _, err := f.Write([]byte("search " + strings.Join(dnsSearch, " ") + "\n")); err != nil {
613
-				return err
614
-			}
615
-		}
616
-	} else {
617
-		container.ResolvConfPath = "/etc/resolv.conf"
618
-	}
619
-	return nil
620
-}
621
-
622 575
 // Commit creates a new filesystem image from the current state of a container.
623 576
 // The image can optionally be tagged into a repository
624 577
 func (runtime *Runtime) Commit(container *Container, repository, tag, comment, author string, config *runconfig.Config) (*image.Image, error) {
... ...
@@ -839,6 +790,9 @@ func NewRuntimeFromDirectory(config *daemonconfig.Config, eng *engine.Engine) (*
839 839
 		eng:            eng,
840 840
 	}
841 841
 
842
+	if err := runtime.checkLocaldns(); err != nil {
843
+		return nil, err
844
+	}
842 845
 	if err := runtime.restore(); err != nil {
843 846
 		return nil, err
844 847
 	}
... ...
@@ -1025,3 +979,15 @@ func (runtime *Runtime) ContainerGraph() *graphdb.Database {
1025 1025
 func (runtime *Runtime) SetServer(server Server) {
1026 1026
 	runtime.srv = server
1027 1027
 }
1028
+
1029
+func (runtime *Runtime) checkLocaldns() error {
1030
+	resolvConf, err := utils.GetResolvConf()
1031
+	if err != nil {
1032
+		return err
1033
+	}
1034
+	if len(runtime.config.Dns) == 0 && utils.CheckLocalDns(resolvConf) {
1035
+		log.Printf("Local (127.0.0.1) DNS resolver found in resolv.conf and containers can't use it. Using default external servers : %v\n", DefaultDns)
1036
+		runtime.config.Dns = DefaultDns
1037
+	}
1038
+	return nil
1039
+}
... ...
@@ -1731,15 +1731,6 @@ func (srv *Server) ContainerCreate(job *engine.Job) engine.Status {
1731 1731
 		job.Errorf("Your kernel does not support swap limit capabilities. Limitation discarded.\n")
1732 1732
 		config.MemorySwap = -1
1733 1733
 	}
1734
-	resolvConf, err := utils.GetResolvConf()
1735
-	if err != nil {
1736
-		return job.Error(err)
1737
-	}
1738
-	if !config.NetworkDisabled && len(config.Dns) == 0 && len(srv.runtime.Config().Dns) == 0 && utils.CheckLocalDns(resolvConf) {
1739
-		job.Errorf("Local (127.0.0.1) DNS resolver found in resolv.conf and containers can't use it. Using default external servers : %v\n", runtime.DefaultDns)
1740
-		config.Dns = runtime.DefaultDns
1741
-	}
1742
-
1743 1734
 	container, buildWarnings, err := srv.runtime.Create(config, name)
1744 1735
 	if err != nil {
1745 1736
 		if srv.runtime.Graph().IsNotExist(err) {