+ Configure dns configuration host-wide with 'docker -d -dns'
+ Detect faulty DNS configuration and replace it with a public default
| ... | ... |
@@ -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 |
+} |