diff --git a/api.go b/api.go index 5e1a6d7011..d304b49a98 100644 --- a/api.go +++ b/api.go @@ -434,17 +434,23 @@ func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { config := &Config{} + out := &APIRun{} + if err := json.NewDecoder(r.Body).Decode(config); err != nil { return err } + + if len(config.Dns) == 0 && len(srv.runtime.Dns) == 0 && utils.CheckLocalDns() { + out.Warnings = append(out.Warnings, fmt.Sprintf("WARNING: Docker detected local DNS server on resolv.conf. Using default external servers: %v", defaultDns)) + config.Dns = defaultDns + } + id, err := srv.ContainerCreate(config) if err != nil { return err } + out.ID = id - out := &APIRun{ - ID: id, - } if config.Memory > 0 && !srv.runtime.capabilities.MemoryLimit { log.Println("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.") 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 log.Println("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.") out.Warnings = append(out.Warnings, "Your kernel does not support memory swap capabilities. Limitation discarded.") } + b, err := json.Marshal(out) if err != nil { return err diff --git a/builder.go b/builder.go index 808b7efcab..02c51fb557 100644 --- a/builder.go +++ b/builder.go @@ -2,11 +2,14 @@ package docker import ( "fmt" + "github.com/dotcloud/docker/utils" "os" "path" "time" ) +var defaultDns = []string{"8.8.8.8", "8.8.4.4"} + type Builder struct { runtime *Runtime repositories *TagStore @@ -66,15 +69,26 @@ func (builder *Builder) Create(config *Config) (*Container, error) { return nil, err } + if len(config.Dns) == 0 && len(builder.runtime.Dns) == 0 && utils.CheckLocalDns() { + //"WARNING: Docker detected local DNS server on resolv.conf. Using default external servers: %v", defaultDns + builder.runtime.Dns = defaultDns + } + // If custom dns exists, then create a resolv.conf for the container - if len(config.Dns) > 0 { + if len(config.Dns) > 0 || len(builder.runtime.Dns) > 0 { + var dns []string + if len(config.Dns) > 0 { + dns = config.Dns + } else { + dns = builder.runtime.Dns + } container.ResolvConfPath = path.Join(container.root, "resolv.conf") f, err := os.Create(container.ResolvConfPath) if err != nil { return nil, err } defer f.Close() - for _, dns := range config.Dns { + for _, dns := range dns { if _, err := f.Write([]byte("nameserver " + dns + "\n")); err != nil { return nil, err } diff --git a/docker/docker.go b/docker/docker.go index 74236613a7..2e23999ad8 100644 --- a/docker/docker.go +++ b/docker/docker.go @@ -34,6 +34,7 @@ func main() { pidfile := flag.String("p", "/var/run/docker.pid", "File containing process PID") flHost := flag.String("H", fmt.Sprintf("%s:%d", host, port), "Host:port to bind/connect to") flEnableCors := flag.Bool("api-enable-cors", false, "Enable CORS requests in the remote api.") + flDns := flag.String("dns", "", "Set custom dns servers") flag.Parse() if *bridgeName != "" { docker.NetworkBridgeIface = *bridgeName @@ -66,7 +67,7 @@ func main() { flag.Usage() return } - if err := daemon(*pidfile, host, port, *flAutoRestart, *flEnableCors); err != nil { + if err := daemon(*pidfile, host, port, *flAutoRestart, *flEnableCors, *flDns); err != nil { log.Fatal(err) os.Exit(-1) } @@ -105,7 +106,7 @@ func removePidFile(pidfile string) { } } -func daemon(pidfile, addr string, port int, autoRestart, enableCors bool) error { +func daemon(pidfile, addr string, port int, autoRestart, enableCors bool, flDns string) error { if addr != "127.0.0.1" { log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\") } @@ -122,8 +123,11 @@ func daemon(pidfile, addr string, port int, autoRestart, enableCors bool) error removePidFile(pidfile) os.Exit(0) }() - - server, err := docker.NewServer(autoRestart, enableCors) + var dns []string + if flDns != "" { + dns = []string{flDns} + } + server, err := docker.NewServer(autoRestart, enableCors, dns) if err != nil { return err } diff --git a/runtime.go b/runtime.go index 1c22bd085c..c37e292d22 100644 --- a/runtime.go +++ b/runtime.go @@ -32,6 +32,7 @@ type Runtime struct { autoRestart bool volumes *Graph srv *Server + Dns []string } var sysInitPath string @@ -245,11 +246,12 @@ func (runtime *Runtime) UpdateCapabilities(quiet bool) { } // FIXME: harmonize with NewGraph() -func NewRuntime(autoRestart bool) (*Runtime, error) { +func NewRuntime(autoRestart bool, dns []string) (*Runtime, error) { runtime, err := NewRuntimeFromDirectory("/var/lib/docker", autoRestart) if err != nil { return nil, err } + runtime.Dns = dns if k, err := utils.GetKernelVersion(); err != nil { log.Printf("WARNING: %s\n", err) diff --git a/server.go b/server.go index a678ffe460..31f002dd15 100644 --- a/server.go +++ b/server.go @@ -978,11 +978,11 @@ func (srv *Server) ImageInspect(name string) (*Image, error) { return nil, fmt.Errorf("No such image: %s", name) } -func NewServer(autoRestart, enableCors bool) (*Server, error) { +func NewServer(autoRestart, enableCors bool, dns ListOpts) (*Server, error) { if runtime.GOARCH != "amd64" { log.Fatalf("The docker runtime currently only supports amd64 (not %s). This will change in the future. Aborting.", runtime.GOARCH) } - runtime, err := NewRuntime(autoRestart) + runtime, err := NewRuntime(autoRestart, dns) if err != nil { return nil, err } diff --git a/utils/utils.go b/utils/utils.go index 307904e3ca..708c8bb19d 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -70,7 +70,7 @@ type progressReader struct { readProgress int // How much has been read so far (bytes) lastUpdate int // How many bytes read at least update template string // Template to print. Default "%v/%v (%v)" - sf *StreamFormatter + sf *StreamFormatter } func (r *progressReader) Read(p []byte) (n int, err error) { @@ -103,7 +103,7 @@ func (r *progressReader) Close() error { return io.ReadCloser(r.reader).Close() } func ProgressReader(r io.ReadCloser, size int, output io.Writer, template []byte, sf *StreamFormatter) *progressReader { - tpl := string(template) + tpl := string(template) if tpl == "" { tpl = string(sf.FormatProgress("", "%v/%v (%v)")) } @@ -599,7 +599,7 @@ func (sf *StreamFormatter) FormatStatus(format string, a ...interface{}) []byte sf.used = true str := fmt.Sprintf(format, a...) if sf.json { - b, err := json.Marshal(&JSONMessage{Status:str}); + b, err := json.Marshal(&JSONMessage{Status: str}) if err != nil { return sf.FormatError(err) } @@ -611,7 +611,7 @@ func (sf *StreamFormatter) FormatStatus(format string, a ...interface{}) []byte func (sf *StreamFormatter) FormatError(err error) []byte { sf.used = true if sf.json { - if b, err := json.Marshal(&JSONMessage{Error:err.Error()}); err == nil { + if b, err := json.Marshal(&JSONMessage{Error: err.Error()}); err == nil { return b } return []byte("{\"error\":\"format error\"}") @@ -622,10 +622,10 @@ func (sf *StreamFormatter) FormatError(err error) []byte { func (sf *StreamFormatter) FormatProgress(action, str string) []byte { sf.used = true if sf.json { - b, err := json.Marshal(&JSONMessage{Status: action, Progress:str}) + b, err := json.Marshal(&JSONMessage{Status: action, Progress: str}) if err != nil { - return nil - } + return nil + } return b } return []byte(action + " " + str + "\r") @@ -634,3 +634,20 @@ func (sf *StreamFormatter) FormatProgress(action, str string) []byte { func (sf *StreamFormatter) Used() bool { return sf.used } + +func CheckLocalDns() bool { + resolv, err := ioutil.ReadFile("/etc/resolv.conf") + if err != nil { + Debugf("Error openning resolv.conf: %s", err) + return false + } + for _, ip := range []string{ + "127.0.0.1", + "127.0.1.1", + } { + if strings.Contains(string(resolv), ip) { + return true + } + } + return false +}