When using olivere/elastic to connect to elasticsearch, I found that although I entered a public network address when connecting, it automatically converted to an internal network address or an ip address in docker during connection, causing the service to fail to connect.

// Auto converted to IP in docker, causing connection failure
time="2019-02-15T20:04:26+08:00" level=error msg="Head http://172.17.0.2:9200: context deadline exceeded"

Solution

client, _ := elastic.NewClient(
  // ...
  // After setting sniff to false, the address will not be automatically converted
   elastic.SetSniff(false),
)

Source Code Analysis

// sniff uses the http://ip:port/_nodes/http request and uses the returned url list as the new url list.
// If snifferEnabled is set to false, then this feature is not enabled.
func (c *Client) sniff(parentCtx context.Context, timeout time.Duration) error {
 c.mu.RLock()
 if !c.snifferEnabled {
  c.mu.RUnlock()
  return nil
 }

 // Use all available URLs provided to sniff the cluster.
 var urls []string
 urlsMap := make(map[string]bool)

 // Add all URLs provided on startup
 for _, url := range c.urls {
  urlsMap[url] = true
  urls = append(urls, url)
 }
 c.mu.RUnlock()

 // Add all URLs found by sniffing
 c.connsMu.RLock()
 for _, conn := range c.conns {
  if !conn.IsDead() {
   url := conn.URL()
   if _, found := urlsMap[url]; !found {
    urls = append(urls, url)
   }
  }
 }
 c.connsMu.RUnlock()

 if len(urls) == 0 {
  return errors.Wrap(ErrNoClient, "no URLs found")
 }

 // Start sniffing on all found URLs
 ch := make(chan []*conn, len(urls))

 ctx, cancel := context.WithTimeout(parentCtx, timeout)
 defer cancel()

 for _, url := range urls {
        // The sniffNode method uses http to request the corresponding url, and returns the result after encapsulation
  go func(url string) { ch <- c.sniffNode(ctx, url) }(url)
 }

 // Wait for the results to come back, or the process times out.
 for {
  select {
  case conns := <-ch:
   if len(conns) > 0 {
    c.updateConns(conns)
    return nil
   }
  case <-ctx.Done():
   if err := ctx.Err(); err != nil {
    switch {
    case IsContextErr(err):
     return err
    }
    return errors.Wrapf(ErrNoClient, "sniff timeout: %v", err)
   }
   // We get here if no cluster responds in time
   return errors.Wrap(ErrNoClient, "sniff timeout")
  }
 }
}