Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Сеть Docker: Основы

Любое сетевое приложение стартует на каком-то интерфейсе с указанием порта. Часто, по умолчанию, это 127.0.0.1:3000.

# Fastify по умолчанию стартует на 127.0.0.1
npx fastify start server/plugin.js -l info -P
[17:54:05.528] INFO (12575): Server listening at http://127.0.0.1:3000

По идее этого достаточно для разработки и такой адрес можно открыть в браузере, но с Docker этот фокус не пройдет. Сеть внутри контейнера полностью своя и localhost внутри контейнера, это не тоже самое что и localhost вне его. Поэтому сервер запущенный на localhost внутри контейнера, не будет доступен снаружи

curl localhost:3000
curl: (7) Failed to connect to localhost port 3000 after 5 ms: Couldn't connect to server

Эта ошибка одна из самых частых у людей, которые только начинают работать с Docker. Они стартуют приложение внутри контейнера и долго не могут понять, почему оно не доступно снаружи.

Для взаимодействия с внешним миром, запуск любых серверов внутри контейнера должен выполняться на адресе 0.0.0.0. Это специальная маска, которая указывает операционной системе подключиться к каждому доступному интерфейсу в системе. А работает это потому, что Docker создает специальный интерфейс со своим ip-адресом внутри каждого контейнера, именно через него реализуется выход наружу.

# -a 0.0.0.0 меняет адрес
npx fastify start server/plugin.js -l info -P -a 0.0.0.0
[17:57:08.680] INFO (16523): Server listening at http://0.0.0.0:3000

Но это только первая часть задачи, есть и вторая. Даже когда сервер слушает правильный интерфейс, Docker не дает к нему обратиться просто так. Он требует явного указания порта, который нужно открыть наружу. Это сделано не случайно, так как внутри контейнера может запускаться много всего, но это не значит, что мы хотим дать внешний доступ ко всем запущенным сервисам. Самый распространенный способ указывать порты выглядит так:

docker run -p 8080:3000 hexletcomponents/devops-example-app
# -p <external port>:<internal port>

Здесь мы говорим Docker, что внешний порт 8080, нужно связать с портом 3000 внутри контейнера. К каким ip-адресам привязаны эти порты? Внутренний это тот, который мы указали веб-серверу, когда запустили его на 0.0.0.0, для нашего приложения это 0.0.0.0:3000. Внешний автоматически подставляет 0.0.0.0, поэтому любой сервис запущенный в контейнере таким образом, будет автоматически доступен снаружи, если хотя бы один из интерфейсов машины доступен извне. Поэтому возможен запуск с явным указанием адреса:

docker run -p 127.0.0.1:8080:3000 hexletcomponents/devops-example-app

При таком запуске, веб-сервер станет доступным на хост-машине только для 127.0.0.1. Такое бывает нужно, если у хост-машины есть ip-адрес, который доступен снаружи, и мы не хотим случайно дать доступ до контейнера внешним клиентам.

В примере выше мы указали разные номера для внешнего и внутреннего портов для наглядности, но на практике порты могут быть одинаковыми и так делают часто:

docker run -p 3000:3000 hexletcomponents/devops-example-app

Docker позволяет пробрасывать столько портов, сколько нужно. Например, в случае nginx часто требуется использовать и 80 порт, и 443 для HTTPS. Сделать это можно так:

docker run -p 80:80 -p 443:443 nginx

Самостоятельная работа

В этой самостоятельной работе вам нужно будет запустить контейнер hexletcomponents/js-fastify-blog. Приложение запускается внутри контейнера на 3000 порту. Запустите его таким образом, чтобы блог был доступен снаружи по адресу: http://localhost:8080


Дополнительные материалы

  1. Docker Documentation: Container networking
  2. Как настроить маппинг между хостом и Docker-контейнером

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»