Advanced networking with Docker

This tutorial will guide you for advanced Docker network configuration using docker-compose.

Packet capture from a container with NET_RAW capability, Docker network DNS domain name, reverse-dns lookup from a container, container hostname discovery, are covered in this article.

Packet capture from a container

Application performance troubleshooting might require packet capture to understand low level failures such as TCP or TLS session establishment failure. Deploying packet capture tools on the docker host might be too intrusive for such a temporary troubleshooting session or require too much privileges on the docker host itself.

Docker provides the NET_RAW capability which allow use of RAW and PACKET sockets. Allow binding to any address for transparent proxying. This capability basically allow a container to capture trafic flowing on the docker network which it belongs to.

If the container is running in host networking mode, the NET_RAW capability makes packet capture on the host physical network interface possible, allowing capture of all packets transiting through the host. The following example show a docker-compose Addpynamics Network Visibility Agent deployment with host mode networking and NET_RAW capability :

version: '3'

services:
  netviz-agent:
    image: appdynamics/machine-agent-netviz:latest
    restart: unless-stopped 
    cap_add:
      - NET_RAW
      - NET_ADMIN
    network_mode: host
    ipc: host

DNS configuration

Default bridge network

By default, a container inherits the DNS settings of the host, as defined in the /etc/resolv.conf configuration file. Co ntainers that use the default bridge network get a copy of this file.

Custom docker network

Default behavior

Containers that use a custom network use Docker Engine embedded DNS server, which forwards external DNS lookups to the DNS servers configured on the host.

This embedded DNS server can be configured with various options impacting both forward and reverse DNS lookup q ueries.

In the following classical docker-compose networking configuration, the nginx container has the following DNS setti ngs in the reverselookup_netcustom docker network :

  • A record : nginx, which is the service name
  • A record : docker-network-tips_nginx_1 which is the name of the container automaticaly created by docker-compose (directory_service_id)
  • PTR record : docker-network-tips_nginx_1.docker-network-tips_reverselookup_net., which is constructed as contai ner-name.network-name
version: '3'

services:
 nginx:
   build:
     context: .
   image: docker-reverse-lookup:latest
   privileged: false
   networks:
     - reverselookup_net

networks:
 reverselookup_net:
   driver: bridge
   ipam:
     config:
       - subnet: 172.22.0.0/16

/ # dig nginx

; <<>> DiG 9.16.20 <<>> nginx
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45822
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;nginx.                         IN      A

;; ANSWER SECTION:
nginx.                  600     IN      A       172.22.0.2

;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Thu Jan 06 07:09:55 UTC 2022
;; MSG SIZE  rcvd: 44




/ # dig docker-network-tips_nginx_1

; <<>> DiG 9.16.20 <<>> docker-network-tips_nginx_1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53264
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;docker-network-tips_nginx_1.   IN      A

;; ANSWER SECTION:
docker-network-tips_nginx_1. 600 IN     A       172.22.0.2

;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Thu Jan 06 07:10:07 UTC 2022
;; MSG SIZE  rcvd: 88




/ # dig -x 172.22.0.2

; <<>> DiG 9.16.20 <<>> -x 172.22.0.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59505
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;2.0.22.172.in-addr.arpa.       IN      PTR

;; ANSWER SECTION:
2.0.22.172.in-addr.arpa. 600    IN      PTR     docker-network-tips_nginx_1.docker-network-tips_reverselookup_net.

;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Thu Jan 06 07:10:28 UTC 2022
;; MSG SIZE  rc

Customizing the docker network domain name

The domain name of the docker network can be configured using the name: example.local setting of the docker network co nfiguration.

networks:
  reverselookup_net:
    name: example.local
    driver: bridge
    ipam:
      config:
        - subnet: 172.22.0.0/16

The reverse DNS lookup answer gets changed :

  • PTR record : docker-network-tips_nginx_1.example.local., which is constructed as container-name.custom-network- name
/ # dig -x 172.22.0.2

; <<>> DiG 9.16.20 <<>> -x 172.22.0.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24436
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;2.0.22.172.in-addr.arpa.       IN      PTR

;; ANSWER SECTION:
2.0.22.172.in-addr.arpa. 600    IN      PTR     docker-network-tips_nginx_1.example.local.

;; Query time: 10 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Thu Jan 06 07:19:13 UTC 2022
;; MSG SIZE  rcvd: 119

Customizing the docker container DNS record

The Docker container A DNS record ans the container name can also be changed using the container_name: testlookup parameter of the service.

Warning : This setting only affects container name and Docker Engine DNS records, but does not change the value retu rned by the hostname -f command. To also affect the hostname -f command result, add the hostname: testlookup.exampl e.local additionnal setting.

version: '3'

services:
  nginx:
    build:
      context: .
    image: docker-reverse-lookup:latest
    container_name: testlookup
    privileged: false
    networks:
      - reverselookup_net

networks:
  reverselookup_net:
    name: example.local
    driver: bridge
    ipam:
      config:
        - subnet: 172.22.0.0/16

The forward and reverse DNS lookup answer gets changed :

  • A record : nginx, which is the service name
  • A record : testlookup which is the custom name defined as container_name parameter.
  • PTR record : testlookup.example.local., which is constructed as custom-container-name.custom-network-name
/ # dig nginx

; <<>> DiG 9.16.20 <<>> nginx
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27761
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;nginx.                         IN      A

;; ANSWER SECTION:
nginx.                  600     IN      A       172.22.0.2

;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Thu Jan 06 07:27:27 UTC 2022
;; MSG SIZE  rcvd: 44




/ # dig testlookup

; <<>> DiG 9.16.20 <<>> testlookup
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46156
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;testlookup.                    IN      A

;; ANSWER SECTION:
testlookup.             600     IN      A       172.22.0.2

;; Query time: 10 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Thu Jan 06 07:27:36 UTC 2022
;; MSG SIZE  rcvd: 54




/ # dig -x 172.22.0.2

; <<>> DiG 9.16.20 <<>> -x 172.22.0.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 52585
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;2.0.22.172.in-addr.arpa.       IN      PTR

;; ANSWER SECTION:
2.0.22.172.in-addr.arpa. 600    IN      PTR     testlookup.example.local.

;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Thu Jan 06 07:27:49 UTC 2022
;; MSG SIZE  rcvd: 102