Golang program cannot find other containers in Docker

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Reading objects

Let's say readers understand docker,docker-compose and go syntax

Problem description

I have three applications called Mysql,goapp,javaapp, respectively. Their dependencies are as follows:


Image.png
    • Goapp completes the logic by invoking the Javaapp service.

    • Javaapp directly with MySQL database.

In order to make them three easy to run in the Docker container I used the docker-compose. The specific configuration file is as follows:

version: '2'services:  mysql:    container_name: mysql    image: mysql:5.7    restart: always    hostname: mysql    environment:       MYSQL_DATABASE: ${MYSQL_DATABASE}       MYSQL_USER: ${MYSQL_USER}       MYSQL_PASSWORD: ${MYSQL_PASSWORD}       MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}  goApp:    container_name: goApp    image: goApp:0.1    hostname: goApp    ports:      - "8080:8080"    javaApp:    container_name: javaApp    image: javaApp:0.1    hostname: javaApp    ports:      - "6031:6031"  

The structure runs smoothly, and it's always stable. Suddenly one day, I gave my server modified a hostname modified to app.crop.cn, and then ran away. The specific phenomenon is as follows:

    • The Javaapp program can be accessed normally. Be able to access the MySQL database.

    • Goapp cannot access the Javaapp application through Javaapp.

    • Enter Javaapp and Goapp this container, can ping each other through.

Problem analysis

There are two key points in the phenomenon:

    • In a container, all pings can be interconnected. Explains that the DNS inside Docker is working.

    • Only the Go program cannot find the corresponding container based on the hostname.

According to the second doubtful guess: The DNS parsing mechanism of the go language is different from that of Java. I found it along this road, and finally found the following in the official documentation.

On Unix systems, the resolver has two options for resolving names. It can use a pure Go resolver that sends DNS requests directly to the servers listed in /etc/resolv.conf, or it can use a cgo-based resolver that calls C library routines such as getaddrinfo and getnameinfo.

This means that go has implemented a set of methods to request DNS resolution. Other programs should use the base C standard library getaddrinfo. So they do not behave the same. What else to say, go and see the code. The implementation was found in the Dnsconfig_unix.go file.

func dnsDefaultSearch() []string {    hn, err := getHostname()    if err != nil {        // best effort        return nil    }    if i := byteIndex(hn, '.'); i >= 0 && i < len(hn)-1 {        return []string{ensureRooted(hn[i+1:])}    }    return nil}func ensureRooted(s string) string {    if len(s) > 0 && s[len(s)-1] == '.' {        return s    }    return s + "."}

As you can see from the code, the default Search is to get the contents of the current host's hostname, the first point (".") later in the section. For example, I have changed the hostname to app.crop.cn, then the default search he gets is crop.cn. The So when I asked for Javaapp, he would javaApp.crop.cn the domain like a docker built-in DNS request. Of course, the request is not.

Problem Solving Solutions

After finding the reason, the following is relatively simple. It is only necessary to set the Dns-search parameter to "." When starting the container. You can do it.

Last modified docker-compose.yml to:

version: '2'services:  mysql:    container_name: mysql    image: mysql:5.7    restart: always    hostname: mysql    environment:       MYSQL_DATABASE: ${MYSQL_DATABASE}       MYSQL_USER: ${MYSQL_USER}       MYSQL_PASSWORD: ${MYSQL_PASSWORD}       MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}  goApp:    container_name: goApp    image: goApp:0.1    dns-search: .    hostname: goApp    ports:      - "8080:8080"        javaApp:    container_name: javaApp    image: javaApp:0.1    hostname: javaApp    ports:      

In this way, this seemingly wonderful problem has been taken care of.

Resources

    1. NAMERESOLVER-GLIBC Wiki

    2. https://golang.org/pkg/net/#hdr-name_resolution

    3. https://docs.docker.com/engine/userguide/networking/default_network/configure-dns/

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.