Задать вопрос
@Clubber_77

Не резолвится доменное имя в контейнере Docker, как можно решить проблему?

У меня в докер поднят unbound в качестве DNS сервера, рядом с ним в той же сети крутится Nginx, для проксирования запросов на кучу сервисов, которые крутятся на нескольких машинах в локалке, иногда рядом. В конфиге Unbound настроена зона, чтобы можно было на сервисы ходить по домену вида *.example.lan. В локалке все хорошо, все работает.

Так же в докер поднята сетка и набор сервисов в ней, среди котррых Gitea, DroneCI и раннер для последнего. И все они видят друг друга и общаются, ровно до того момента, пока раннер, не пытается выполнить pipeline. Там все падает на моменте скачивания репозитория.

Для всего этого безобразия создана в Docker отдельная внешняя сеть, к которой подключены
1. Unbound и Nginx
2. Gitea, DroneCI и runners

Локальный IP машины на которой все это крутится 172.16.5.69.

docker-compose.yaml для DNS и Proxy
version: '3.8'

services:
  nginx:
    image: nginx:latest
    container_name: nginx
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - ./nginx_proxy:/etc/nginx/conf.d
    networks:
      - unbound

  unbound:
    image: mvance/unbound
    container_name: unbound
    privileged: true
    restart: unless-stopped
    ports:
      - "53:53/udp"
      - "53:53/tcp"
    volumes:
      - ./unbound_dns/conf/a-records.conf:/opt/unbound/etc/unbound/a-records.conf:ro
    networks:
      - unbound


networks:
  unbound:
    external: true


Вот так зона прописана в Unbound
local-zone: "lan." static
local-data: "example.lan. IN A 172.16.5.69"
local-data: "drone.example.lan. IN A 172.16.5.69"
local-data: "gitea.example.lan. IN A 172.16.5.69"


а это конфиг Nginx

server {
    listen 80;
    server_name gitea.example.lan;

    location / {
        proxy_pass http://172.16.5.69:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_http_version 1.1;
        proxy_set_header Connection '';

        client_max_body_size 100M;
    }
}

server {
    listen 80;
    server_name drone.example.lan;

    location / {
        proxy_pass http://172.16.5.69:8081;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_http_version 1.1;
        proxy_set_header Connection '';

        client_max_body_size 100M;
    }
}


docker-compose.yaml для Gitea и DroneCI
version: "3.9"

networks:
  unbound:
    external: true

services:
  server:
    image: gitea/gitea:1.22.4
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=
      - GITEA__database__HOST=
      - GITEA__database__NAME=
      - GITEA__database__USER=
      - GITEA__database__PASSWD=
    restart: always
    networks:
      - unbound
    volumes:
      - ./gitea:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "222:22"
    depends_on:
      - db
    extra_hosts:
      - "drone.example.lan:172.16.5.69"
    dns:
      - 172.16.5.69

  drone-server:
    image: drone/drone:latest
    container_name: drone-server
    restart: always
    environment:
      - DRONE_GITEA_SERVER=http://gitea.example.lan
      - DRONE_GITEA_CLIENT_ID=
      - DRONE_GITEA_CLIENT_SECRET=
      - DRONE_RPC_SECRET=
      - DRONE_SERVER_HOST=drone.example.lan
      - DRONE_SERVER_PROTO=http
    ports:
      - "8081:80"
    volumes:
      - ./drone-data:/data
    networks:
      - unbound
    dns:
      - 172.16.5.69
    extra_hosts:
    - "gitea.example.lan:172.16.5.69"

  db:
    image: postgres
    restart: always
    environment:
      POSTGRES_USER: 
      POSTGRES_PASSWORD: 
      POSTGRES_DB: 
    ports:
      - "5432:5432"
    networks:
      - unbound
    dns:
      - 172.16.5.69
    volumes:
      - ./postgres:/var/lib/postgresql/data

  drone-runner:
    image: drone/drone-runner-docker:latest
    container_name: drone-runner
    restart: always
    environment:
      - DRONE_RPC_SERVER=http://drone.example.lan
      - DRONE_RPC_HOST=drone.example.lan
      - DRONE_RPC_SECRET=
      - DRONE_RUNNER_CAPACITY=5
    volumes:
      - ./drone-data:/data
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - unbound
    dns:
      - 172.16.5.69
    extra_hosts:
      - "drone.example.lan:172.16.5.69"
      - "gitea.example.lan:172.16.5.69"


Репозиотрий в Gitea доступен и работает. Gitea и DroneCI связаны друг с другом через секреты выпущеные самой Gitea. Авторизация проходит, и репозиторий доступен из учетки в DroneCI .

Но при запуске задачи
Cloning with 0 retries
Initialized empty Git repository in /drone/src/.git/
+ git fetch origin +refs/heads/main:
fatal: unable to access 'http://gitea.example.lan/user/user_documentation.git/': Could not resolve host: gitea.example.lan


При этом, если залезть в контейнеры, и пингануть сервисы, видно, что до DNS каждый контейнер достучаться может, но резолвинг имени не работает, по какой-то причине.
sudo docker exec -it drone-server /bin/sh
/ # nslookup gitea.example.lan
Server:		127.0.0.11
Address:	127.0.0.11:53

;; connection timed out; no servers could be reached

/ # ping  gitea.example.lan
PING gitea.example.lan (172.16.5.69): 56 data bytes
64 bytes from 172.16.5.69: seq=0 ttl=64 time=0.123 ms
64 bytes from 172.16.5.69: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.16.5.69: seq=2 ttl=64 time=0.105 ms
--- gitea.example.lan ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.080/0.102/0.123 ms
/ #


sudo docker exec -it gitea /bin/sh
/ # nslookup drone.example.lan
Server:		127.0.0.11
Address:	127.0.0.11:53

;; connection timed out; no servers could be reached

/ # ping drone.example.lan
PING drone.example.lan (172.16.5.69): 56 data bytes
64 bytes from 172.16.5.69: seq=0 ttl=64 time=0.130 ms
64 bytes from 172.16.5.69: seq=1 ttl=64 time=0.082 ms
64 bytes from 172.16.5.69: seq=2 ttl=64 time=0.081 ms
^C
--- drone.example.lan ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.081/0.097/0.130 ms
/ #


sudo docker exec -it drone-runner /bin/sh

/ # nslookup drone.example.lan
Server:		127.0.0.11
Address:	127.0.0.11:53

;; connection timed out; no servers could be reached

/ # nslookup gitea.example.lan
Server:		127.0.0.11
Address:	127.0.0.11:53

;; connection timed out; no servers could be reached

/ # ping gitea.example.lan
PING gitea.example.lan (172.16.5.69): 56 data bytes
64 bytes from 172.16.5.69: seq=0 ttl=64 time=0.087 ms
64 bytes from 172.16.5.69: seq=1 ttl=64 time=0.081 ms
64 bytes from 172.16.5.69: seq=2 ttl=64 time=0.055 ms
--- gitea.example.lan ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.055/0.074/0.087 ms

/ # ping drone.example.lan
PING drone.example.lan (172.16.5.69): 56 data bytes
64 bytes from 172.16.5.69: seq=0 ttl=64 time=0.134 ms
64 bytes from 172.16.5.69: seq=1 ttl=64 time=0.077 ms
64 bytes from 172.16.5.69: seq=2 ttl=64 time=0.084 ms
--- drone.example.lan ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.077/0.098/0.134 ms
/ #


Видно, что в контейнерах не учитывается DNS который указан в docker-compose
sudo docker exec -it gitea /bin/sh
/ #  cat /etc/resolv.conf 
# Generated by Docker Engine.
# This file can be edited; Docker Engine will not make further changes once it
# has been modified.

nameserver 127.0.0.11
options ndots:0

# Based on host file: '/etc/resolv.conf' (internal resolver)
# ExtServers: [172.16.5.69]
# Overrides: [nameservers]
# Option ndots from: internal
/ # exit

sudo docker exec -it drone-server /bin/sh
/ # cat /etc/resolv.conf 
# Generated by Docker Engine.
# This file can be edited; Docker Engine will not make further changes once it
# has been modified.

nameserver 127.0.0.11
options ndots:0

# Based on host file: '/etc/resolv.conf' (internal resolver)
# ExtServers: [172.16.5.69]
# Overrides: [nameservers]
# Option ndots from: internal
/ # exit

sudo docker exec -it drone-runner /bin/sh
/ # cat /etc/resolv.conf 
# Generated by Docker Engine.
# This file can be edited; Docker Engine will not make further changes once it
# has been modified.

nameserver 127.0.0.11
options ndots:0

# Based on host file: '/etc/resolv.conf' (internal resolver)
# ExtServers: [172.16.5.69]
# Overrides: [nameservers]
# Option ndots from: internal
/ # exit


Я решительно не понимаю, как заставить их видеть друг друга, при том, что в локальной сети все норм. Буду очень признателен за помощь

UPD: на тейщий момент мне удалось решить проблему резолвинга сервисов внутри docker, для этого пришлось указать внутрениий ip адрес unbound в качестве dns. Во всех контейнерах все доменные именна начали резовится после этого. Но основной проблемы связанной с
fatal: unable to access 'http://gitea.example.lan/user/user_documentation.git/': Could not resolve host: gitea.example.lan

решить не ужалось
  • Вопрос задан
  • 294 просмотра
Подписаться 1 Сложный 2 комментария
Решения вопроса 1
@Clubber_77 Автор вопроса
На данный момент для меня остается не ясна причина, по которой Docker игнорирует внешний DNS, и как это исправить. Но я нашел решение для DroneCI, которое позволяет мне на данный момент решить текущую задачу.

1. Все контейнеры должны быть подключены к одной сети, в моем случае это одна внешняя сеть
2. Узнать ip адрес unbound внутри сети docker, и указать его для всех сервисов, как DNS
3. Для drone-runner установить переменную среды DRONE_RUNNER_NETWORKS, указывающую на вашу внешнюю сеть. Это предоставит возможность воркерам работать внутри вашей сети.
4. Устанавливать в пайплайнах адрес dns, чтобы можно было локальные имена резолвились внутри кнтейнера
5. Отключить операцию clone, которая по умолчанию включена в каждом пайплайне, и отвечает за скачивание репозитория в DroneCI. Потому что установить IP адрес DNS, для этой операции нельзя.

kind: pipeline
type: docker
name: default

clone:
  disable: true  

steps:
  - name: check-dns
    image: ubuntu:20.04  
    dns:
      - 172.22.0.3
    commands:
      - apt-get update && apt-get install -y dnsutils iputils-ping  
      - set -e  
      - echo "Проверка доступности DNS-сервера"
      - ping -c 4 172.16.5.69 || { echo "Ping failed for 172.16.5.69"; exit 1; }  
      - ping -c 4 172.22.0.3 || { echo "Ping failed for 172.22.0.3"; exit 1; }  
      - echo "Проверка разрешения имени через DNS"
      - nslookup gitea.example.lan || { echo "nslookup failed"; exit 1; }  
      - dig @172.22.0.3 gitea.example.lan || { echo "dig failed"; exit 1; }  
      - nslookup gitea.example.lan 172.22.0.3 || { echo "nslookup with DNS failed"; exit 1; }


Дополнение:

Чтобы починить Gitea Actions необходимо:
1. Раннеру добавить переменную окружения ACT_RUNNER_DOCKER_NETWORK, указывающую, на вашу внешнюю сеть. Это позволит запускать воркеры, как и в случае с DroneCI, в той же сети, в которой у вас настроен DNS.
2. Установить контейнеру опцию --dns

name: DNS Check Workflow
run-name: ${{ gitea.actor }} is running the DNS Check workflow 
permissions:
  actions: read
  checks: read
  pull-requests: read
  contents: read
  packages: read
on: [push]

jobs:
  Check-DNS:
    runs-on: ubuntu-latest
    container:
      image: ubuntu:latest
      options: --dns 172.22.0.3

    steps:
      - name: Install tools
        run: |
          echo " Installing tools"
          apt-get update
          apt-get install -y dnsutils iputils-ping curl git
          echo "✅ Installation completed: dnsutils, iputils-ping, curl"          

      - name: Install Node.js
        run: |
          echo " Installing Node"
          curl -fsSL https://deb.nodesource.com/setup_16.x | bash -
          apt-get install -y nodejs || { echo "❌ Node.js installation failed"; exit 1; }
          node --version
          echo "✅ Installation completed: nodejs"          

      - name: Check DNS Server Accessibility
        run: |
          echo " Checking DNS server accessibility"
          ping -c 4 172.16.5.69 || { echo "❌ Ping failed for 172.16.5.69"; exit 1; }
          ping -c 4 172.22.0.3 || { echo "❌ Ping failed for 172.22.0.3"; exit 1; }          

      - name: Test DNS Resolution
        run: |
          echo " Testing DNS resolution"
          nslookup gitea.oogis.lan || { echo "❌ nslookup failed"; exit 1; }
          dig @172.22.0.3 gitea.oogis.lan || { echo "❌ dig failed"; exit 1; }
          nslookup gitea.oogis.lan 172.22.0.3 || { echo "❌ nslookup with specified DNS failed"; exit 1; }          

      - run: echo " The job was automatically triggered by a ${{ gitea.event_name }} event."
      - run: echo " This job is now running on a ${{ runner.os }} server hosted by Gitea!"
      - run: echo " The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
      - name: Check out repository code
        uses: actions/checkout@v4
        with:
          token: ${{ secrets.GITEA_TOKEN }}
      - run: echo " The ${{ gitea.repository }} repository has been cloned to the runner."
      - run: echo "️ The workflow is now ready to test your code on the runner."
      - name: List files in the repository
        run: |
          ls ${{ gitea.workspace }}          
      - run: echo " This job's status is ${{ job.status }}."
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы