Browse code

Merge branch 'dns_server_side'

+ Configure dns configuration host-wide with 'docker -d -dns'
+ Detect faulty DNS configuration and replace it with a public default

Solomon Hykes authored on 2013/06/15 06:39:05
Showing 6 changed files
... ...
@@ -434,17 +434,23 @@ func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http
434 434
 
435 435
 func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
436 436
 	config := &Config{}
437
+	out := &APIRun{}
438
+
437 439
 	if err := json.NewDecoder(r.Body).Decode(config); err != nil {
438 440
 		return err
439 441
 	}
442
+
443
+	if len(config.Dns) == 0 && len(srv.runtime.Dns) == 0 && utils.CheckLocalDns() {
444
+		out.Warnings = append(out.Warnings, fmt.Sprintf("WARNING: Docker detected local DNS server on resolv.conf. Using default external servers: %v", defaultDns))
445
+		config.Dns = defaultDns
446
+	}
447
+
440 448
 	id, err := srv.ContainerCreate(config)
441 449
 	if err != nil {
442 450
 		return err
443 451
 	}
452
+	out.ID = id
444 453
 
445
-	out := &APIRun{
446
-		ID: id,
447
-	}
448 454
 	if config.Memory > 0 && !srv.runtime.capabilities.MemoryLimit {
449 455
 		log.Println("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.")
450 456
 		out.Warnings = append(out.Warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.")
... ...
@@ -453,6 +459,7 @@ func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r
453 453
 		log.Println("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.")
454 454
 		out.Warnings = append(out.Warnings, "Your kernel does not support memory swap capabilities. Limitation discarded.")
455 455
 	}
456
+
456 457
 	b, err := json.Marshal(out)
457 458
 	if err != nil {
458 459
 		return err
... ...
@@ -2,11 +2,14 @@ package docker
2 2
 
3 3
 import (
4 4
 	"fmt"
5
+	"github.com/dotcloud/docker/utils"
5 6
 	"os"
6 7
 	"path"
7 8
 	"time"
8 9
 )
9 10
 
11
+var defaultDns = []string{"8.8.8.8", "8.8.4.4"}
12
+
10 13
 type Builder struct {
11 14
 	runtime      *Runtime
12 15
 	repositories *TagStore
... ...
@@ -66,15 +69,26 @@ func (builder *Builder) Create(config *Config) (*Container, error) {
66 66
 		return nil, err
67 67
 	}
68 68
 
69
+	if len(config.Dns) == 0 && len(builder.runtime.Dns) == 0 && utils.CheckLocalDns() {
70
+		//"WARNING: Docker detected local DNS server on resolv.conf. Using default external servers: %v", defaultDns
71
+		builder.runtime.Dns = defaultDns
72
+	}
73
+
69 74
 	// If custom dns exists, then create a resolv.conf for the container
70
-	if len(config.Dns) > 0 {
75
+	if len(config.Dns) > 0 || len(builder.runtime.Dns) > 0 {
76
+		var dns []string
77
+		if len(config.Dns) > 0 {
78
+			dns = config.Dns
79
+		} else {
80
+			dns = builder.runtime.Dns
81
+		}
71 82
 		container.ResolvConfPath = path.Join(container.root, "resolv.conf")
72 83
 		f, err := os.Create(container.ResolvConfPath)
73 84
 		if err != nil {
74 85
 			return nil, err
75 86
 		}
76 87
 		defer f.Close()
77
-		for _, dns := range config.Dns {
88
+		for _, dns := range dns {
78 89
 			if _, err := f.Write([]byte("nameserver " + dns + "\n")); err != nil {
79 90
 				return nil, err
80 91
 			}
... ...
@@ -34,6 +34,7 @@ func main() {
34 34
 	pidfile := flag.String("p", "/var/run/docker.pid", "File containing process PID")
35 35
 	flHost := flag.String("H", fmt.Sprintf("%s:%d", host, port), "Host:port to bind/connect to")
36 36
 	flEnableCors := flag.Bool("api-enable-cors", false, "Enable CORS requests in the remote api.")
37
+	flDns := flag.String("dns", "", "Set custom dns servers")
37 38
 	flag.Parse()
38 39
 	if *bridgeName != "" {
39 40
 		docker.NetworkBridgeIface = *bridgeName
... ...
@@ -66,7 +67,7 @@ func main() {
66 66
 			flag.Usage()
67 67
 			return
68 68
 		}
69
-		if err := daemon(*pidfile, host, port, *flAutoRestart, *flEnableCors); err != nil {
69
+		if err := daemon(*pidfile, host, port, *flAutoRestart, *flEnableCors, *flDns); err != nil {
70 70
 			log.Fatal(err)
71 71
 			os.Exit(-1)
72 72
 		}
... ...
@@ -105,7 +106,7 @@ func removePidFile(pidfile string) {
105 105
 	}
106 106
 }
107 107
 
108
-func daemon(pidfile, addr string, port int, autoRestart, enableCors bool) error {
108
+func daemon(pidfile, addr string, port int, autoRestart, enableCors bool, flDns string) error {
109 109
 	if addr != "127.0.0.1" {
110 110
 		log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
111 111
 	}
... ...
@@ -122,8 +123,11 @@ func daemon(pidfile, addr string, port int, autoRestart, enableCors bool) error
122 122
 		removePidFile(pidfile)
123 123
 		os.Exit(0)
124 124
 	}()
125
-
126
-	server, err := docker.NewServer(autoRestart, enableCors)
125
+	var dns []string
126
+	if flDns != "" {
127
+		dns = []string{flDns}
128
+	}
129
+	server, err := docker.NewServer(autoRestart, enableCors, dns)
127 130
 	if err != nil {
128 131
 		return err
129 132
 	}
... ...
@@ -32,6 +32,7 @@ type Runtime struct {
32 32
 	autoRestart    bool
33 33
 	volumes        *Graph
34 34
 	srv            *Server
35
+	Dns            []string
35 36
 }
36 37
 
37 38
 var sysInitPath string
... ...
@@ -245,11 +246,12 @@ func (runtime *Runtime) UpdateCapabilities(quiet bool) {
245 245
 }
246 246
 
247 247
 // FIXME: harmonize with NewGraph()
248
-func NewRuntime(autoRestart bool) (*Runtime, error) {
248
+func NewRuntime(autoRestart bool, dns []string) (*Runtime, error) {
249 249
 	runtime, err := NewRuntimeFromDirectory("/var/lib/docker", autoRestart)
250 250
 	if err != nil {
251 251
 		return nil, err
252 252
 	}
253
+	runtime.Dns = dns
253 254
 
254 255
 	if k, err := utils.GetKernelVersion(); err != nil {
255 256
 		log.Printf("WARNING: %s\n", err)
... ...
@@ -978,11 +978,11 @@ func (srv *Server) ImageInspect(name string) (*Image, error) {
978 978
 	return nil, fmt.Errorf("No such image: %s", name)
979 979
 }
980 980
 
981
-func NewServer(autoRestart, enableCors bool) (*Server, error) {
981
+func NewServer(autoRestart, enableCors bool, dns ListOpts) (*Server, error) {
982 982
 	if runtime.GOARCH != "amd64" {
983 983
 		log.Fatalf("The docker runtime currently only supports amd64 (not %s). This will change in the future. Aborting.", runtime.GOARCH)
984 984
 	}
985
-	runtime, err := NewRuntime(autoRestart)
985
+	runtime, err := NewRuntime(autoRestart, dns)
986 986
 	if err != nil {
987 987
 		return nil, err
988 988
 	}
... ...
@@ -70,7 +70,7 @@ type progressReader struct {
70 70
 	readProgress int           // How much has been read so far (bytes)
71 71
 	lastUpdate   int           // How many bytes read at least update
72 72
 	template     string        // Template to print. Default "%v/%v (%v)"
73
-	sf *StreamFormatter
73
+	sf           *StreamFormatter
74 74
 }
75 75
 
76 76
 func (r *progressReader) Read(p []byte) (n int, err error) {
... ...
@@ -103,7 +103,7 @@ func (r *progressReader) Close() error {
103 103
 	return io.ReadCloser(r.reader).Close()
104 104
 }
105 105
 func ProgressReader(r io.ReadCloser, size int, output io.Writer, template []byte, sf *StreamFormatter) *progressReader {
106
-      	tpl := string(template)
106
+	tpl := string(template)
107 107
 	if tpl == "" {
108 108
 		tpl = string(sf.FormatProgress("", "%v/%v (%v)"))
109 109
 	}
... ...
@@ -599,7 +599,7 @@ func (sf *StreamFormatter) FormatStatus(format string, a ...interface{}) []byte
599 599
 	sf.used = true
600 600
 	str := fmt.Sprintf(format, a...)
601 601
 	if sf.json {
602
-		b, err := json.Marshal(&JSONMessage{Status:str});
602
+		b, err := json.Marshal(&JSONMessage{Status: str})
603 603
 		if err != nil {
604 604
 			return sf.FormatError(err)
605 605
 		}
... ...
@@ -611,7 +611,7 @@ func (sf *StreamFormatter) FormatStatus(format string, a ...interface{}) []byte
611 611
 func (sf *StreamFormatter) FormatError(err error) []byte {
612 612
 	sf.used = true
613 613
 	if sf.json {
614
-		if b, err := json.Marshal(&JSONMessage{Error:err.Error()}); err == nil {
614
+		if b, err := json.Marshal(&JSONMessage{Error: err.Error()}); err == nil {
615 615
 			return b
616 616
 		}
617 617
 		return []byte("{\"error\":\"format error\"}")
... ...
@@ -622,10 +622,10 @@ func (sf *StreamFormatter) FormatError(err error) []byte {
622 622
 func (sf *StreamFormatter) FormatProgress(action, str string) []byte {
623 623
 	sf.used = true
624 624
 	if sf.json {
625
-		b, err := json.Marshal(&JSONMessage{Status: action, Progress:str})
625
+		b, err := json.Marshal(&JSONMessage{Status: action, Progress: str})
626 626
 		if err != nil {
627
-                        return nil
628
-                }
627
+			return nil
628
+		}
629 629
 		return b
630 630
 	}
631 631
 	return []byte(action + " " + str + "\r")
... ...
@@ -634,3 +634,20 @@ func (sf *StreamFormatter) FormatProgress(action, str string) []byte {
634 634
 func (sf *StreamFormatter) Used() bool {
635 635
 	return sf.used
636 636
 }
637
+
638
+func CheckLocalDns() bool {
639
+	resolv, err := ioutil.ReadFile("/etc/resolv.conf")
640
+	if err != nil {
641
+		Debugf("Error openning resolv.conf: %s", err)
642
+		return false
643
+	}
644
+	for _, ip := range []string{
645
+		"127.0.0.1",
646
+		"127.0.1.1",
647
+	} {
648
+		if strings.Contains(string(resolv), ip) {
649
+			return true
650
+		}
651
+	}
652
+	return false
653
+}