diff --git a/proxy/start_container_interceptor.go b/proxy/start_container_interceptor.go index 89d0ebc4..1d0d17df 100644 --- a/proxy/start_container_interceptor.go +++ b/proxy/start_container_interceptor.go @@ -15,11 +15,22 @@ func (i *startContainerInterceptor) InterceptRequest(r *http.Request) error { // If the client has sent some JSON which might be a HostConfig, add our // parameters back into it, otherwise Docker will consider them overwritten if containerShouldAttach(container) && r.Header.Get("Content-Type") == "application/json" { - hostConfig := map[string]interface{}{} - if err := unmarshalRequestBody(r, &hostConfig); err != nil { + params := map[string]interface{}{} + if err := unmarshalRequestBody(r, ¶ms); err != nil { return err } - if len(hostConfig) > 0 { + // HostConfig can be sent either as a struct named HostConfig, or unnamed at top level + var hostConfig map[string]interface{} + if subParam, found := params["HostConfig"]; found { + if typecast, ok := subParam.(map[string]interface{}); ok { + hostConfig = typecast + } + // We can't reliably detect what Docker will see as a top-level HostConfig, + // so just assume any parameter at top level indicates there is one. + } else if len(params) > 0 { + hostConfig = params + } + if hostConfig != nil { i.proxy.addWeaveWaitVolume(hostConfig) if dnsDomain := i.proxy.getDNSDomain(); dnsDomain != "" { if err := i.proxy.setWeaveDNS(hostConfig, container.Config.Hostname, dnsDomain); err != nil { @@ -27,7 +38,8 @@ func (i *startContainerInterceptor) InterceptRequest(r *http.Request) error { } } - if err := marshalRequestBody(r, hostConfig); err != nil { + // Note we marshal the original top-level dictionary to avoid disturbing anything else + if err := marshalRequestBody(r, params); err != nil { return err } }