1. Обзор
В Docker важно знать, какие порты прослушивает контейнерное приложение. Нам также нужен способ доступа к приложению из-за пределов контейнера.
Чтобы решить эти проблемы, Docker позволяет нам открывать и публиковать порты.
В этой статье мы узнаем как об открытии, так и о публикации портов. В качестве примера мы будем использовать простой контейнер веб-сервера Nginx.
2. Открытие портов
Открытый порт — это часть метаданных о контейнерном приложении. В большинстве случаев это показывает, какие порты прослушивает приложение. Сам Docker ничего не делает с открытым портом . Однако когда мы запускаем контейнер, мы можем использовать эти метаданные при публикации порта.
2.1. Разоблачение с помощью Nginx
Давайте воспользуемся веб-сервером Nginx, чтобы попробовать это.
Если мы посмотрим на официальный Dockerfile Nginx , мы увидим, что порт 80 открыт с помощью следующей команды:
EXPOSE 80
Здесь показан порт 80, потому что это порт по умолчанию для протокола http .
Давайте запустим контейнер Nginx на нашей локальной машине и посмотрим, сможем ли мы получить к нему доступ через порт 80:
$ docker run -d nginx
Приведенная выше команда будет использовать последний образ Nginx и запускать контейнер. Мы можем перепроверить, что контейнер Nginx работает, с помощью команды:
$ docker container ls
Эта команда выведет некоторую информацию обо всех запущенных контейнерах, включая Nginx:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cbc2f10f787f nginx "/docker-entrypoint..." 15 seconds ago Up 15 seconds 80/tcp dazzling_mclean
Здесь мы видим 80 под разделом порта. Поскольку порт 80 открыт, мы можем подумать, что доступ к localhost:80
(или просто localhost
) отобразит страницу Nginx по умолчанию, но это не так:
$ curl http://localhost:8080
... no web page appears
Хотя порт открыт, Docker не открыл его для хоста.
2.2. Способы раскрытия портов
Есть два основных способа открыть порты в Docker. Мы можем сделать это в Dockerfile
с помощью команды EXPOSE
:
EXPOSE 8765
Кроме того, мы также можем открыть порт с параметром –expose
при запуске контейнера :
$ docker run --expose 8765 nginx
3. Публикация портов
Чтобы порт контейнера был доступен через узел докера, нам нужно его опубликовать.
3.1. Публикация с помощью Nginx
Давайте запустим Nginx с маппированным портом:
$ docker run -d -p 8080:80 nginx
Приведенная выше команда сопоставит порт 8080 хоста с портом 80 контейнера. Общий синтаксис опции:
-p <hostport>:<container port>
Если мы перейдем к localhost:8080
, мы должны получить страницу приветствия Nginx по умолчанию:
$ curl http://localhost:8080
StatusCode : 200
StatusDescription : OK
Content : <!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
... more HTML
Перечислим все запущенные контейнеры:
$ docker container ls
Теперь мы должны увидеть, что у контейнера есть сопоставление портов:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
38cfed3c61ea nginx "/docker-entrypoint..." 31 seconds ago Up 30 seconds 0.0.0.0:8080->80/tcp dazzling_kowalevski
В разделе портов
у нас есть сопоставление 0.0.0.0:8080->80/tcp
.
Docker по умолчанию добавил немаршрутизируемый
метаадрес 0.0.0.0 для хоста .
Это означает, что сопоставление действительно для всех адресов/интерфейсов хоста.
3.2. Ограничение доступа к контейнеру
Мы можем ограничить доступ к контейнеру на основе IP-адреса хоста. Вместо того, чтобы разрешать доступ к контейнеру со всех интерфейсов (что делает 0.0.0.0
), мы можем указать IP-адрес хоста в сопоставлении.
Ограничим доступ к контейнеру трафиком только с loopback-адреса 127.0.0.1 :
$ docker run -d -p 127.0.0.1:8081:80 nginx
В этом случае контейнер доступен только с самого хоста. Это использует расширенный синтаксис для публикации, который включает привязку адреса:
-p <binding address>:<hostport>:<container port>
4. Опубликуйте все открытые порты
Открытые метаданные порта могут быть полезны для запуска контейнера, поскольку Docker дает нам возможность публиковать все открытые порты:
$ docker run -d --publish-all nginx
Здесь Docker привязывает все открытые порты в контейнере к свободным случайным портам на хосте.
Давайте посмотрим на контейнеры, которые запускает эта команда:
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0a23e78732ce nginx "/docker-entrypoint..." 6 minutes ago Up 6 minutes 0.0.0.0:32768->80/tcp pedantic_curran
Как мы и ожидали, Docker выбрал случайный порт (в данном случае 32768) с хоста и сопоставил его с открытым портом .
5. Вывод
В этой статье мы узнали об открытии и публикации портов в Docker.
Мы также обсудили, что открытый порт — это метаданные о контейнерном приложении, тогда как публикация порта — это способ доступа к приложению с хоста.