1. Обзор
Как мы знаем, Docker Compose — это инструмент для определения и управления несколькими контейнерами одновременно. По умолчанию Docker Compose настраивает выделенную сеть для определенных контейнеров, обеспечивая связь между ними. В результате мы можем создавать и запускать службы с заданным файлом конфигурации с помощью одной команды.
В этом руководстве мы увидим два свойства YAML, которые позволяют нам настраивать сеть между контейнерами — expose
и ports
. Мы подробно опишем их, покажем основные варианты использования и выделим их ключевые отличия.
2. открыть
раздел
Во-первых, давайте посмотрим на конфигурацию expose
. Это свойство определяет порты, которые Docker Compose предоставляет из контейнера.
Эти порты будут доступны другим службам, подключенным к той же сети, но не будут опубликованы на хост-компьютере .
Мы можем выставить порт, указав его номер в разделе services
:
services:
myapp1:
...
expose:
- "3000"
- "8000"
myapp2:
...
expose:
- "5000"
Как мы видим, мы можем указать несколько значений для каждой службы. Мы только что открыли порты 3000
и 8000
из контейнера myapp1
и порт 5000
из контейнера myapp2
. Службы теперь доступны на этих портах для других контейнеров в той же сети.
Давайте теперь проверим открытые порты:
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8673c14f18d1 ... ... ... ... 3000/tcp, 8000/tcp bael_myapp1
bc044e180131 ... ... ... ... 5000/tcp bael_myapp2
В выводе команды docker ps
мы можем найти открытые порты в столбце PORTS
.
Наконец, давайте проверим связь между контейнерами:
> docker exec -it bc044e180131 /bin/bash
bash-5.1$ nc -vz myapp1 3000
myapp1 (172.18.0.1:3000) open
bash-5.1$ nc -vz myapp1 8000
myapp1 (172.18.0.1:8000) open
Мы только что подключились к интерфейсу командной строки myapp2
. С помощью команды netcat
мы проверили доступность обоих портов, предоставленных myapp1
.
3. Порты
Раздел
Теперь давайте проверим раздел портов .
Как и прежде, это свойство определяет порты, которые мы хотим открыть из контейнера. Но в отличие от открытой
конфигурации, эти порты будут доступны внутри и опубликованы на хост-компьютере .
Как и раньше, мы можем определить порты для каждой службы в выделенном разделе, но конфигурация может быть более сложной. Во-первых, мы должны выбрать один из двух синтаксисов (короткий и длинный), чтобы определить конфигурацию.
3.1. Краткий синтаксис
Начнем с анализа короткого. Краткий синтаксис представляет собой строку, разделенную двоеточием, для установки IP-адреса хоста, порта хоста и порта контейнера :
[HOST:]CONTAINER[/PROTOCOL]
Здесь HOST
— это номер порта хоста или диапазон номеров портов, которым может предшествовать IP-адрес. Если мы не указываем IP-адрес, Docker Compose привязывает порт ко всем сетевым интерфейсам.
C ONTAINER
определяет номер порта контейнера или диапазон номеров портов.
PROTOCOL
ограничивает порты контейнера указанным протоколом или устанавливает для них TCP
, если он пуст. Только часть CONTAINER
является обязательной.
Теперь, когда мы знаем синтаксис, давайте определим порты в нашем файле Docker Compose:
services:
myapp1:
...
ports:
- "3000" # container port (3000), assigned to random host port
- "3001-3005" # container port range (3001-3005), assigned to random host ports
- "8000:8000" # container port (8000), assigned to given host port (8000)
- "9090-9091:8080-8081" # container port range (8080-8081), assigned to given host port range (9090-9091)
- "127.0.0.1:8002:8002" # container port (8002), assigned to given host port (8002) and bind to 127.0.0.1
- "6060:6060/udp" # container port (6060) restricted to UDP protocol, assigned to given host (6060)
Как показано выше, мы также можем опубликовать несколько портов контейнера одновременно, используя различные варианты короткого синтаксиса и более точно настроив его. Docker Compose предоставляет все указанные порты контейнера, делая их доступными как внутри, так и снаружи локального компьютера.
Как и раньше, давайте проверим открытые порты с помощью команды docker ps
:
> docker ps -a
CONTAINER ID ... PORTS NAMES
e8c65b9eec91 ... 0.0.0.0:51060->3000/tcp, 0.0.0.0:51063->3001/tcp, 0.0.0.0:51064->3002/tcp, bael_myapp1
0.0.0.0:51065->3003/tcp, 0.0.0.0:51061->3004/tcp, 0.0.0.0:51062->3005/tcp,
0.0.0.0:8000->8000/tcp, 0.0.0.0:9090->8080/tcp, 0.0.0.0:9091->8081/tcp
127.0.0.1:8002->8002/tcp, 0.0.0.0:6060->6060/udp
Еще раз, в столбце PORTS
мы можем найти все открытые порты. Значение слева от стрелки показывает адрес хоста, по которому мы можем получить доступ к контейнеру извне.
3.2. Длинный синтаксис
Используя длинный синтаксис, мы можем настроить порты таким же образом. Однако вместо использования строки, разделенной двоеточием, мы определяем каждое свойство отдельно :
services:
myapp1:
...
ports:
# - "127.0.0.1:6060:6060/udp"
- target: 6060
host_ip: 127.0.0.1
published: 6060
protocol: udp
mode: host
Здесь цель
является обязательной и указывает порт контейнера (или диапазон портов), который будет предоставлен, что эквивалентно CONTAINER
в кратком синтаксисе.
Host_ip и publish
являются частями HOST
в коротком, где мы можем определить IP-адрес и порт хоста .
Протокол ,
такой же, как PROTOCOL
в кратком синтаксисе, ограничивает порт контейнера указанным протоколом (или TCP
, если он пуст).
Режим — это перечисление с двумя значениями, указывающее правила публикации порта .
Мы должны использовать значение хоста
для локальной публикации порта. Второе значение — ingress
— зарезервировано для более сложных контейнерных сред и означает, что порт будет сбалансирован по нагрузке.
В заключение, любая короткая синтаксическая строка может быть легко представлена длинной структурой. Однако не все конфигурации с длинным синтаксисом могут быть перемещены в короткий из-за отсутствия свойства режима .
4. Вывод
В этой статье мы только что рассмотрели часть сетевых конфигураций в Docker Compose. Мы проанализировали и сравнили конфигурацию портов, используя разделы expose
и ports .
Раздел expose
позволяет нам открывать определенные порты из нашего контейнера только для других служб в той же сети . Мы можем сделать это, просто указав порты контейнера.
Раздел портов
также предоставляет указанные порты из контейнеров . В отличие от предыдущего ,
порты открыты не только для других служб в той же сети, но и для хоста . Конфигурация немного сложнее, где мы можем настроить открытый порт, локальный адрес привязки и ограниченный протокол. В зависимости от наших предпочтений, мы можем выбирать между двумя разными синтаксисами.