Overlay-сеть — это виртуальная распределённая сеть (VXLAN), которая соединяет контейнеры между разными хостами Swarm. Как и в обычном Docker по умолчанию создаётся сеть ingress для Swarm, является сетью по умолчанию для всех сервисов. Также создаётся мост docker_gwbridge для Swarm.

docker network ls
60a8d3ab28a9   docker_gwbridge    bridge    local
kj4mqhyy9nji   ingress            overlay   swarm

swarm-network-01-default.svg

То есть контейнеры на хостах vm4, vm8 и vm9 могут видеть друг друга по внутренним IP,
как будто находятся в одной LAN.

Для детального рассмотрения overlay-сетей я создам два сервиса (backend и frontend), подключу их к разным overlay-сетям, и покажу, как между ними происходит взаимодействие.

1️⃣Создание двух overlay-сетей

Для этого используется уже знакомая команда docker network create, только с опцией –driver.

docker network create -d overlay frontend_net
docker network create -d overlay backend_net
docker network ls | grep net
85twu2uuvm3d   backend_net        overlay   swarm
qtgx23jd02zl   frontend_net       overlay   swarm

2️⃣Docker образ приложения api

Пример будет состоять из двух сервисов:

  • api — простой backend на Python Flask
  • web — Nginx, который обращается к backend_net через внутреннюю сеть

📜 api.py

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello from backend via overlay network!\n"

app.run(host="0.0.0.0", port=5000)

📜 Dockerfile.api

FROM python:3.11-slim
WORKDIR /app
COPY api.py .
RUN pip install flask
CMD ["python", "api.py"]

Теперь имея необходимые файлы для сервиса api нужно собрать образ, из которого в дальнейшем будут созданы контейнеры для сервиса. Если непонятно что за сборка образа почитайте это.

docker build -t myapi:1.0 -f Dockerfile.api .

3️⃣Docker образ web

📜 nginx.conf

events {}
http {
    server {
        listen 80;
        location / {
            proxy_pass http://api:5000;  # имя сервиса api  DNS в overlay
        }
    }
}

📜 Dockerfile.web

FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf

Теперь имея необходимые файлы для сервиса web нужно собрать образ, из которого в дальнейшем будут созданы контейнеры для сервиса. Если непонятно что за сборка образа почитайте это.

docker build -t mynginx:1.0 -f Dockerfile.web .

4️⃣Развёртывание сервиса api

Теперь разверну сервис api из образа myapi:1.0 с двумя репликами, где также укажу созданную ранее сеть backend_net.

docker service create --name api --network backend_net --replicas 2 myapi:1.0

Но тут я получу ошибку 2/2: No such image: myapi:1.0, потому что так как у меня три узла в кластере образ этот должен быть на всех узлах. Поэтому если вы используете в боевой среде Swarm, то заливайте свои образы в репозиторий и скачивайте их оттуда.

swarm-registry-01-problem.svg swarm-registry-02-solution.svg

docker service ps api
zre8g7r64glm   api.1     myapi:1.0   c-stream-9-vm9   Running         Running 23 seconds ago
pgloedqlhxoa   api.2     myapi:1.0   c-stream-9-vm8   Running         Running 25 seconds ago

4️⃣Развёртывание сервиса web

Теперь разверну сервис api из образа mynginx:1.0 с двумя репликами, где также укажу созданную ранее сеть backend_net и frontend_net. Почему сразу две сети? Потому что по умолчанию сеть frontend_net не имеет доступ к сети backend_net. Поэтому если я создам сервис только с сетью frontend_net он не получить доступ к контейнерам сервиса api.

swarm-multinetwork-01-problem.svg swarm-multinetwork-02-solution.svg

docker service create --name web --network frontend_net -p 8080:80 mynginx:1.0
docker service ps web
r669iabwy6b3   web.1     mynginx:1.0   c-stream-9-vm4   Running         Running 12 seconds ago
curl http://127.0.0.1:8080
Hello from backend via overlay network!

5️⃣Проверка DNS внутри сетей

Можно проверить что контейнер сервиса web имеет доступ к контейнеру сервиса api.

docker exec -it $(docker ps | grep web | head -1 | awk '{print $1}') ping api

Итог

Overlay-сети в Swarm позволяют изолировать и при этом соединять сервисы на разных нодах.
Один сервис может быть в нескольких overlay-сетях и выполнять роль “моста” между ними — как web в моём примере.

swarm-multinetwork-07-summary.svg