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
This commit is contained in:
commit
250e47e2eb
13
api.go
13
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 {
|
func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
config := &Config{}
|
config := &Config{}
|
||||||
|
out := &APIRun{}
|
||||||
|
|
||||||
if err := json.NewDecoder(r.Body).Decode(config); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(config); err != nil {
|
||||||
return err
|
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)
|
id, err := srv.ContainerCreate(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
out.ID = id
|
||||||
|
|
||||||
out := &APIRun{
|
|
||||||
ID: id,
|
|
||||||
}
|
|
||||||
if config.Memory > 0 && !srv.runtime.capabilities.MemoryLimit {
|
if config.Memory > 0 && !srv.runtime.capabilities.MemoryLimit {
|
||||||
log.Println("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.")
|
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.")
|
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.")
|
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.")
|
out.Warnings = append(out.Warnings, "Your kernel does not support memory swap capabilities. Limitation discarded.")
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := json.Marshal(out)
|
b, err := json.Marshal(out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
18
builder.go
18
builder.go
|
@ -2,11 +2,14 @@ package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/dotcloud/docker/utils"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var defaultDns = []string{"8.8.8.8", "8.8.4.4"}
|
||||||
|
|
||||||
type Builder struct {
|
type Builder struct {
|
||||||
runtime *Runtime
|
runtime *Runtime
|
||||||
repositories *TagStore
|
repositories *TagStore
|
||||||
|
@ -66,15 +69,26 @@ func (builder *Builder) Create(config *Config) (*Container, error) {
|
||||||
return nil, err
|
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 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")
|
container.ResolvConfPath = path.Join(container.root, "resolv.conf")
|
||||||
f, err := os.Create(container.ResolvConfPath)
|
f, err := os.Create(container.ResolvConfPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
for _, dns := range config.Dns {
|
for _, dns := range dns {
|
||||||
if _, err := f.Write([]byte("nameserver " + dns + "\n")); err != nil {
|
if _, err := f.Write([]byte("nameserver " + dns + "\n")); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ func main() {
|
||||||
pidfile := flag.String("p", "/var/run/docker.pid", "File containing process PID")
|
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")
|
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.")
|
flEnableCors := flag.Bool("api-enable-cors", false, "Enable CORS requests in the remote api.")
|
||||||
|
flDns := flag.String("dns", "", "Set custom dns servers")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if *bridgeName != "" {
|
if *bridgeName != "" {
|
||||||
docker.NetworkBridgeIface = *bridgeName
|
docker.NetworkBridgeIface = *bridgeName
|
||||||
|
@ -66,7 +67,7 @@ func main() {
|
||||||
flag.Usage()
|
flag.Usage()
|
||||||
return
|
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)
|
log.Fatal(err)
|
||||||
os.Exit(-1)
|
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" {
|
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 /!\\")
|
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)
|
removePidFile(pidfile)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}()
|
}()
|
||||||
|
var dns []string
|
||||||
server, err := docker.NewServer(autoRestart, enableCors)
|
if flDns != "" {
|
||||||
|
dns = []string{flDns}
|
||||||
|
}
|
||||||
|
server, err := docker.NewServer(autoRestart, enableCors, dns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ type Runtime struct {
|
||||||
autoRestart bool
|
autoRestart bool
|
||||||
volumes *Graph
|
volumes *Graph
|
||||||
srv *Server
|
srv *Server
|
||||||
|
Dns []string
|
||||||
}
|
}
|
||||||
|
|
||||||
var sysInitPath string
|
var sysInitPath string
|
||||||
|
@ -245,11 +246,12 @@ func (runtime *Runtime) UpdateCapabilities(quiet bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: harmonize with NewGraph()
|
// 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)
|
runtime, err := NewRuntimeFromDirectory("/var/lib/docker", autoRestart)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
runtime.Dns = dns
|
||||||
|
|
||||||
if k, err := utils.GetKernelVersion(); err != nil {
|
if k, err := utils.GetKernelVersion(); err != nil {
|
||||||
log.Printf("WARNING: %s\n", err)
|
log.Printf("WARNING: %s\n", err)
|
||||||
|
|
|
@ -978,11 +978,11 @@ func (srv *Server) ImageInspect(name string) (*Image, error) {
|
||||||
return nil, fmt.Errorf("No such image: %s", name)
|
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" {
|
if runtime.GOARCH != "amd64" {
|
||||||
log.Fatalf("The docker runtime currently only supports amd64 (not %s). This will change in the future. Aborting.", runtime.GOARCH)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ type progressReader struct {
|
||||||
readProgress int // How much has been read so far (bytes)
|
readProgress int // How much has been read so far (bytes)
|
||||||
lastUpdate int // How many bytes read at least update
|
lastUpdate int // How many bytes read at least update
|
||||||
template string // Template to print. Default "%v/%v (%v)"
|
template string // Template to print. Default "%v/%v (%v)"
|
||||||
sf *StreamFormatter
|
sf *StreamFormatter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *progressReader) Read(p []byte) (n int, err error) {
|
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()
|
return io.ReadCloser(r.reader).Close()
|
||||||
}
|
}
|
||||||
func ProgressReader(r io.ReadCloser, size int, output io.Writer, template []byte, sf *StreamFormatter) *progressReader {
|
func ProgressReader(r io.ReadCloser, size int, output io.Writer, template []byte, sf *StreamFormatter) *progressReader {
|
||||||
tpl := string(template)
|
tpl := string(template)
|
||||||
if tpl == "" {
|
if tpl == "" {
|
||||||
tpl = string(sf.FormatProgress("", "%v/%v (%v)"))
|
tpl = string(sf.FormatProgress("", "%v/%v (%v)"))
|
||||||
}
|
}
|
||||||
|
@ -599,7 +599,7 @@ func (sf *StreamFormatter) FormatStatus(format string, a ...interface{}) []byte
|
||||||
sf.used = true
|
sf.used = true
|
||||||
str := fmt.Sprintf(format, a...)
|
str := fmt.Sprintf(format, a...)
|
||||||
if sf.json {
|
if sf.json {
|
||||||
b, err := json.Marshal(&JSONMessage{Status:str});
|
b, err := json.Marshal(&JSONMessage{Status: str})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sf.FormatError(err)
|
return sf.FormatError(err)
|
||||||
}
|
}
|
||||||
|
@ -611,7 +611,7 @@ func (sf *StreamFormatter) FormatStatus(format string, a ...interface{}) []byte
|
||||||
func (sf *StreamFormatter) FormatError(err error) []byte {
|
func (sf *StreamFormatter) FormatError(err error) []byte {
|
||||||
sf.used = true
|
sf.used = true
|
||||||
if sf.json {
|
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 b
|
||||||
}
|
}
|
||||||
return []byte("{\"error\":\"format error\"}")
|
return []byte("{\"error\":\"format error\"}")
|
||||||
|
@ -622,10 +622,10 @@ func (sf *StreamFormatter) FormatError(err error) []byte {
|
||||||
func (sf *StreamFormatter) FormatProgress(action, str string) []byte {
|
func (sf *StreamFormatter) FormatProgress(action, str string) []byte {
|
||||||
sf.used = true
|
sf.used = true
|
||||||
if sf.json {
|
if sf.json {
|
||||||
b, err := json.Marshal(&JSONMessage{Status: action, Progress:str})
|
b, err := json.Marshal(&JSONMessage{Status: action, Progress: str})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
return []byte(action + " " + str + "\r")
|
return []byte(action + " " + str + "\r")
|
||||||
|
@ -634,3 +634,20 @@ func (sf *StreamFormatter) FormatProgress(action, str string) []byte {
|
||||||
func (sf *StreamFormatter) Used() bool {
|
func (sf *StreamFormatter) Used() bool {
|
||||||
return sf.used
|
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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue