Docker — Керування портами

У Docker самі контейнери можуть мати програми, що працюють на портах. Коли ви запускаєте контейнер, якщо ви хочете отримати доступ до програми в контейнері через номер порту, вам необхідно зіставити номер порту контейнера з номером порту хоста Docker. Погляньмо на приклад того, як цього можна досягти.

У нашому прикладі ми збираємося завантажити контейнер Jenkins із Docker Hub. Потім ми порівняємо номер порту Jenkins із номером порту на хості Docker.

Крок 1 — По-перше, вам потрібно виконати просту реєстрацію у Docker Hub.

Крок 2 — Як тільки ви зареєструєтеся, ви увійдете до Docker Hub.

Крок 3 – Далі, давайте подивимося і знайдемо зображення Дженкінса.

Крок 4 — Якщо ви прокрутите вниз на тій самій сторінці, ви побачите команду Docker pull . Це використовуватиметься для завантаження образу Jenkins на локальний сервер Ubuntu.

Крок 5 — Тепер перейдіть на сервер Ubuntu та виконайте команду —

sudo docker pull jenkins

Крок 6 — Щоб зрозуміти, які порти відкриваються контейнером, ви повинні використовувати команду Docker inspect для перевірки образу.

Давайте тепер дізнаємось більше про цю команду огляду .

докер перевіряє

Цей метод дозволяє повертати низькорівневу інформацію про контейнер або зображення.

Синтаксис

docker inspect Container/Image

Опції

  • Контейнер / Зображення — Контейнер або зображення для перевірки

Контейнер / Зображення — Контейнер або зображення для перевірки

Значення, що повертається

Низькорівнева інформація про зображення або контейнер у форматі JSON.

приклад

sudo docker inspect jenkins 

Вихід

Виведення команди inspect дає висновок JSON. Якщо ми спостерігаємо висновок, ми бачимо, що є розділ ExposedPorts і бачимо, що згадуються два порти. Один – це порт даних 8080, а інший – порт управління 50000.

Щоб запустити Jenkins та відобразити порти, вам потрібно змінити команду запуску Docker і додати опцію p, яка визначає відображення портів. Отже, вам потрібно виконати наступну команду.

sudo docker run -p 8080:8080 -p 50000:50000 jenkins

Ліва частина зіставлення номерів портів – це порт хоста Docker для зіставлення, а права частина – номер порту контейнера Docker.

Коли ви відкриєте браузер і перейдете до Docker хоста через порт 8080, ви побачите, що Jenkins запущений і працює.

Docker — Керування портами - Mriya.v.ua

Для взаємодії з Docker-контейнером із хоста потрібно налаштувати мапінг портів. Розберемося, чому це важливо, і розглянемо кілька способів додавання нового карту після запуску Docker-контейнера.

Це адаптований переклад статті Assigning a Port Mapping to Running Docker Container з блогу освітнього проекту Baeldung.

Ця стаття призначена для розробників, які знають Docker хоч би на базовому рівні. Якщо ви ще не знайомі з цією технологією і вам цікаво з нею розібратися, пройдіть курс з Docker на Хекслеті.

Навіщо потрібний мапінг

За замовчуванням Docker запускає сервіс ізольовано, тобто всі порти між хостом та Docker-контейнером закриті. Для того, щоб отримати доступ до сервісу з хоста або зовнішньої мережі, потрібно використовувати зіставлення портів або мапінг.

Мапінг потрібний для того, щоб усі запити, що проходять через порт хоста, перенаправлялися в Docker-контейнер. Іншими словами, зіставлення портів робить процеси всередині контейнера доступними ззовні.

При запуску нового Docker-контейнера за допомогою команди docker run можна зіставити порти опцією –publish або -p:

-d -p 81:80 --name httpd-container httpd 

Ця команда запускає Docker-контейнер httpd (HTTP-сервер Apache) та мапінг 81 порту хоста з 80 портом усередині Docker-контейнера.За промовчанням сервер httpd прослуховує порт 80.

Тепер доступ до програми можна отримати, використовуючи порт 81 на хості:

Важливо відзначити, що виконувати мапінг для всіх Docker-контейнерів необов'язково. Наприклад, у випадках, коли потрібно зберегти служби Docker-контейнера закритими або видимими лише спорідненим контейнерам у тій самій мережі Docker.

  • Освойте ази сучасних мов програмування
  • Вивчіть роботу з Git та командним рядком
  • Виберіть собі професію або покращіть навички

Як призначити мапінг працюючому Docker-контейнеру

Розглянемо ситуацію, в якій мапінг не був заданий при запуску Docker-контейнера або був поставлений з помилкою. Отримати доступ до сервісу через TCP/IP-з'єднання на хості не вдасться, але є три способи вирішити цю проблему:

  • Зупинити працюючий Dockerконтейнер, а потім створити і запустити новий з оригінальним docker images
  • Зробити docker commit працюючого Docker-контейнера, створити новий та запустіть його через docker images , зберігши стан
  • Додати новий мапінг, використовуючи конфігураційні файли Docker

Розберемо кожен спосіб докладніше.

Освойте DevOps на інтенсивності Хекслета Навчіться автоматизувати оточення, деплоїти програми однією кнопкою одночасно на будь-яку кількість машин і розгортати кластер хмар на Digital Ocean або Yandex Cloud.

Перезапуск Docker-контейнера

Це найтехнічніше рішення: працюючий Docker-контейнер видаляється, а замість нього створюється новий, запущений з образу. Під час створення Docker-контейнера зіставляються порти.

Хоча це найпростіший спосіб, він підходить не у всіх ситуаціях. Наприклад, рішення не підійде в ситуації, коли всередині Docker-контейнера вже виконано деякі операції: встановилися залежності, запустилися процеси або оновилися файли. Якщо відновити такий Docker-контейнер із образу, всі ці зміни будуть втрачені.

Варто відзначити, що важливі дані краще зберігати в Docker volumes, щоб спростити заміну Docker-контейнерів.

Повторний запуск із docker commit

Цей підхід передбачає створення нового образу з урахуванням існуючого Docker-контейнера. Потім можна використовувати образ для запуску нового Docker-контейнера з відкритими потрібними портами.

Оскільки ми фіксуємо стан існуючого Docker-контейнера, воно стає доступним у новому образі.

Спробуймо реалізувати цей спосіб. Спочатку зупинимо Docker-контейнер і створимо його образ за допомогою команди docker commit:

# Зупиняємо контейнер docker stop httpd-container # Команда надрукує на екрані назву зупиненого контейнера httpd-container # Створюємо образ на основі існуючого контейнера docker commit httpd-container httpd-image # Хеш образу sha256:33da33fcad051c90ac9b7dea9b2dbda442767e05ddebd8d6db8ac6893ef4ef40 

Потім видалімо Docker-контейнер і знову запустимо його з образу. На цьому етапі важливо переконатися, що мапінг налаштований правильно:

# Видаляємо контейнер docker rm httpd-container # Команда надрукує на екрані назву віддаленого контейнера httpd-container # Запускаємо контейнер docker run -d -p 83:80 --name httpd-container httpd-image # На екрані виведеться хеш запущеного контейнера dd2535c477ad74e80b3642abca9055efacb89eaf14572b91f91bf20cd3f0cbf3 

Перенастроювання Docker-контейнера без його видалення

У підходах, які обговорювалися вище, йшлося про видалення існуючого Docker-контейнера та створення нового. Хоча новий Docker-контейнер працює також, його метадані повністю відрізняються.

Розглянемо спосіб, як налаштувати мапінг у вже існуючому Docker-контейнері. Спочатку запустимо новий без порівняння портів:

-d --name httpd-container httpd a0ed1c9fc60c358d53400dc244e94ef0db4d1347e70bd4be725a890b062ebbe7 # Команда виведе запущені контейнери docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a0ed1c9fc60c httpd "httpd-foreground" 1 second ago Up 1 second 80/tcp httpd-container 

Docker run повертає повний ідентифікатор Docker довжиною 64 символи. Інший спосіб отримати його – команда docker inspect:

$ docker inspect --format=">" httpd-container a0ed1c9fc60c358d53400dc244e94ef0db4d1347e70bd4be725a890b062ebbe7 

Ідентифікатор стане в нагоді для пошуку файлу конфігурації Docker.

Зупинка Docker-контейнера та служби Docker

Перший крок з переналаштування працюючого Docker-контейнера – його зупинка. Виконати її можна командою docker stop:

Для оновлення конфігураційних файлів Docker-контейнера потрібно зупинити службу Docker. Варто зазначити, що ця дія призведе до відключення всіх Docker-контейнерів, поки процес налаштування не закінчиться.

# Зупиняємо службу Docker systemctl stop docker 

Читайте також: Як зберігати фокус протягом усього навчання: поради від Хекслета

Як знайти конфігураційні файли

Усі конфігураційні файли, які відносяться до Docker-контейнерів, образів, томів та мереж Docker, можна знайти в каталозі /var/lib/docker . Варто зазначити, що на Windows та MacOS шлях до каталогу відрізняється.

У цьому випадку інтерес представляють два файли: hostconfig.json і config.v2.json. Знайти їх можна в наступному каталозі:

У цьому випадку ID - повний ідентифікатор Docker-контейнера, який ми отримали:
Конфігураційні файли можна знайти в наступному каталозі:
$ ls /var/lib/docker/containers/a0ed1c9fc60c358d53400dc244e94ef0db4d1347e70bd4be725a890b062ebbe7/ a0ed1c9fc60c358d53400dc44 b062ebbe7-json.log checkpoints config.v2.json hostconfig.json hostname hosts mounts resolv.conf resolv.conf.hash 

Оновлення конфігураційних файлів

В першу чергу варто оновити файл hostconfig.json. Для цього знайдемо ключ прив'язки портів у цьому файлі. Оскільки при запуску Docker-контейнера мапінг не був налаштований, поле ключа PortBindings Docker-контейнера буде порожнім.

Наступним кроком є ​​призначення 82 порту хоста 80 порту Docker-контейнера httpd-container . Для цього оновимо прив'язки портів у файлі JSON:

 . . "PortBindings": "80/tcp":["HostIp":"","HostPort":"82">]>, . . > 

Як тільки мапінг виконаний, потрібно відкрити порт 80 Docker-контейнер у файлі config.v2.json . Для цього додамо поле відкритих портів (якщо ще немає) в ключ конфігурації:

 . "Config":  . "ExposedPorts":  "80/tcp":<> >, . > > 

Таким чином ми повідомляємо демону Docker, що Docker-контейнер прослуховує 80 порт у цьому мережному інтерфейсі.

Можна відкрити кілька портів, передавши значення у вигляді пар ключ-значення, розділених комами:

 . "Config":  . "ExposedPorts":  "80/tcp":<>, "82/tcp":<>, "8080/tcp":<> >, . > > 

Перевірка змін

Перевірка змін складається з кількох кроків. Спочатку запустимо службу Docker:

Тепер запустимо httpd-контейнер і перевіримо мапінг портів за допомогою команди docker ps:

"httpd-foreground" 1 годину тому Up 1 seconds 0.0.0.0:82->80/tcp, . 82->80/tcp httpd-container 

З результату виконання команди видно, що порти Docker-контейнера тепер зіставлені портами хоста. Після цього доступ до служби httpd Docker-контейнера можна отримати ззовні через 82 порт:

При такому підході ідентифікатор Docker-контейнера та всі виконані в ньому налаштування зберігаються, оскільки вихідний контейнер не замінюється новим.

Змінити існуючі картки будь-якого Docker-контейнера можна за допомогою процедури, описаної вище. Єдина відмінність полягає в тому, що ключ прив'язки портів у файлі hostconfig.json не буде пустим. У цьому випадку досить просто оновити номер порту, що використовується.

При оновленні TCP-порту Docker-контейнера в карті необхідно вказати той же порт у файлі config.v2.json .

Тепер усі перевірки пройшли — можна запустити службу Docker та Docker-контейнер, щоб зміни набули чинності.

  • Освойте ази сучасних мов програмування
  • Вивчіть роботу з Git та командним рядком
  • Виберіть собі професію або покращіть навички

Docker — Керування портами - Mriya.v.ua

У конфігурації з кількома контейнерами служби, що працюють у контейнерах, взаємодіють один з одним через спільну мережу. У тому ж налаштуванні деякі контейнери також взаємодіють із зовнішнім світом.

Цей внутрішній та зовнішній зв'язок здійснюється за допомогою відкритих та опублікованих портів у Docker відповідно.

У цьому уроці я розповім про роботу з портами Docker. Я перейду до різниці між розкриттям та публікацією портів, чому вони використовуються та як їх використовувати.

Викриття та публікація порту в Docker

Є два способи обробки портів у Docker: надання доступу до портів та публікація портів.

Розкриття порту просто означає, що інші знають, який порт контейнерний додаток буде прослуховувати або приймати з'єднання. Це для зв'язку з іншими контейнерами, а не із зовнішнім світом.

Публікація порту більше схожа зіставлення портів контейнера з портами хоста. Таким чином, контейнер зможе взаємодіяти із зовнішніми системами, реальним світом та Інтернетом.

Ця графіка допоможе вам зрозуміти.

Бачите, як порт 80 контейнер SERVER зіставляється з портом 80 хост-системи? Таким чином, контейнер може взаємодіяти із зовнішнім світом, використовуючи загальнодоступну IP-адресу хост-системи.

З іншого боку, до відкритих портів не можна отримати прямий доступ з-за меж світу контейнерів.

  • Відкриті порти використовуються для внутрішнього зв'язку контейнерів усередині світу контейнерів.
  • Опубліковані порти використовуються для зв'язку із системами за межами світу контейнерів.

Відкриття портів у Docker

Насамперед, розкриття порту перестав бути суворо обов'язковим. Чому? Тому що більшість образів докерів, які ви використовуєте у своєму налаштуванні, вже мають стандартний порт, вказаний в їх конфігурації.

Наприклад, зовнішня контейнерна програма може взаємодіяти з базою даних MariaDB, просто вказавши IP-адресу контейнера і порт, через який MariaDB приймає з'єднання (за замовчуванням 3306).

Відкриття допомагає в ситуації, коли значення за замовчуванням не використовуються, наприклад, якщо MariaDB не буде приймати з'єднання через порт 3306, слід вказати альтернативний порт, розкриваючи його.

Відкрити порт можна двома способами:

  1. Використовуючи вказівку EXPOSE Dockerfile.
  2. Використання –expose за допомогою Docker CLI або ключа expose у docker-compose.

Настав час поринути глибше в обидва.

Спосіб 1: надання портів через Dockerfile

Ви можете додати просту інструкцію до свого Dockerfile, щоб повідомити іншим, через який порт ваш додаток буде приймати з'єднання.

Про цю інструкцію вам необхідно знати наступне:

  • EXPOSE не додає додаткові шари у отримане зображення Docker. Він просто додає метадані.
  • EXPOSE – це спосіб документування порту вашої програми. Єдиний ефект, який він надає, – це легкочитання або розуміння програми.

Ви можете побачити, як працює Exposure на простому образі контейнера, який я створив спеціально для цієї мети. Це зображення нічого не робить.

docker pull debdutdeb/expose-demo:v1

На цьому зображенні представлено всього чотири порти. Список зображень можна отримати за допомогою наступної команди.

docker image ls --filter=reference=debdutdeb/expose-demo:v1

Подивіться на стовпець SIZE, там буде вказано 0 байт.

➟ docker image ls --filter=reference=debdutdeb/expose-demo:v1

Причина проста: у цьому зображенні немає шарів, всі додані інструкції експонування були метаданими, а не реальними шарами.

Ви також можете отримати кількість доступних шарів, використовуючи наступну команду:

docker image inspect -f '>' debdutdeb/expose-demo:v1

Ви маєте побачити такий висновок: –

➟ docker image inspect -f '>' debdutdeb/expose-demo:v1 0

Як я вже говорив раніше, відкриті порти додаються як метадані зображення, щоб ми знали, які порти використовує програму.

Як переглянути цю інформацію, не заглядаючи в Dockerfile? Вам потрібно оглянути зображення. Щоб бути більш конкретним, див. нижче. Ви можете використовувати аналогічну команду для будь-якого зображення, щоб отримати список відкритих портів.

Для демонстрації використовую зразок зображення.

docker image inspect -f \ '>>>' \ debdutdeb/expose-demo:v1
➟ docker image inspect -f '>>>' debdutdeb/expose-demo:v1 443/tcp 80/tcp 8080/tcp 9090/tcp

Ви також можете порівняти цей образ, в якому відкрито кілька портів, із зображенням debdutdeb/noexpose-demo:v1 , в якому не показано жодних портів. Запустіть той же набір команд і для цього зображення та зверніть увагу на різницю.

Спосіб 2: надання доступу до портів через CLI або docker-compose

Іноді розробники програм ухиляються від включення додаткової інструкції EXPOSE до файлу Dockerfile.

У такому випадку, щоб інші контейнери (через API-інтерфейс Docker) могли легко виявити порт, який ви використовуєте, ви можете надати кілька портів після складання в рамках процесу розгортання.

Або виберіть імперативний метод, тобто CLI, або декларативний метод, тобто створення файлів.

Метод командного рядка

У цьому методі при створенні контейнера все, що потрібно зробити, це використовувати параметр –expose (стільки разів, скільки необхідно) з номером порту і, при необхідності, протокол з / . Ось один приклад: –

docker container run \ --expose 80 \ --expose 90 \ --expose 70/udp \ -d --name port-expose busybox:latest sleep 1d

Я використовую образ busybox, який за умовчанням не надає жодних портів.

Метод створення файлу

Якщо ви використовуєте файл компонування, ви можете додати масив expose до визначення сервісу. Ви можете перетворити попереднє розгортання у файл компонування таким чином:

version: "3.7" services: PortExpose: image: busybox command: sleep 1d container_name: port-expose expose: - 80 - 90 - 70/udp 

Як тільки контейнер почне працювати, ви, як і раніше, зможете перевірити його, щоб дізнатися, які порти відкриті. Команда виглядає аналогічно.

docker container inspect -f \ '> >>' \ port-expose
➟ docker container inspect -f '>>>' port-expose 70/udp 80/tcp 90/tcp

Публікація порту в Docker

Публікація портів — це синонім переадресації портів, коли запити від вхідного з'єднання через загальнодоступний порт пересилаються на порт контейнера.

Аналогічно, відповіді, надіслані з контейнера через його порт, надсилаються клієнту шляхом пересилання трафіку на вказаний порт у просторі портів хоста.

Існує два способи публікації порту: один через CLI, а інший за допомогою файлу компонування. Обидва методи мають один довгий синтаксис і один короткий синтаксис.

Спосіб 1: опублікувати порти за допомогою команди Docker

Два синтаксиси такі:

-p [optional_host_ip]:[host_port]:[container_port]/[optional_protocol]
--publish target=[container_port],published=[optional_host_ip]:[host_port],protocol=[optional_protocol]

В якості додаткової IP-адреси хоста ви можете використовувати будь-яку IP-адресу, пов'язану з будь-яким з мережевих адаптерів. Якщо IP-адреса опущена, Docker зв'яже порт з усіма доступними IP-адресами.

Ви будете використовувати перший з них найчастіше. Другий більш читабельний. Давайте подивимося приклад використання контейнера nginx. Виконайте наступну команду: –

docker container run --rm --name nginx \ --publish target=80,published=127.0.0.1:8081,protocol=tcp \-d nginx

За допомогою цієї команди я просто прив'язую порт 80 контейнера до порту 8081 мого хоста на локальному хості. Тепер, якщо ви перейдете за адресою http://localhost:8081, ви побачите працюючий nginx.

Попередню команду можна легко перетворити на більш коротку форму, наприклад:

docker container run --rm --name nginx \-p 80:127.0.0.1:8081/tcp -d nginx

Хоч він і коротший, його важче читати.

Ви також можете використовувати -p або –publish кілька разів для публікації кількох портів.

Спосіб 2. Публікація порту через файл створення

Щоб опублікувати порт за допомогою файлу компонування, вам знадобиться масив із ім'ям ports у визначенні служби. Цей масив може бути списком рядків, схожим на короткий синтаксис CLI, або ви можете використовувати список об'єктів, схожий на довгий синтаксис.

Якби мені довелося перетворити попереднє розгортання nginx за допомогою файлу Compose з масивом рядків для розділу портів, це виглядало б так:

version: "3.7" services: Nginx: image: nginx container_name: nginx ports: - 80:127.0.0.1:8081/tcp

Дозвольте мені показати, як використовувати синтаксис масиву об'єктів.

version: "3.7" services: Nginx: image: nginx container_name: nginx ports: - target: 80 published: 127.0.0.1:8081 protocol: tcp

Щоб побачити список всіх опублікованих портів, ви можете перевірити контейнер таким чином:

docker container inspect -f '> %s\n" $container $host>>>' nginx

Під час запуску ви побачите наступний висновок: –

➟ docker container inspect -f '> %s\n" $container $host>>>' nginx 80/tcp -> []

Існує інший, простіший спосіб скласти список опублікованих портів, використовуючи команду docker-Container port .

docker container port nginx
➟ docker container port nginx 80/tcp -> 127.0.0.1:8081

Коли виставляти порт, а коли його публікувати?

Це справедливе питання. Викриття та публікація не повинні бути конкурентами. Кожен є різною метою. Якщо ви є розробником образу, ви розкриватимете порти, щоб користувач міг краще знати, де спробувати підключитися. З іншого боку, якщо ви використовуєте зображення і потрібно зробити його доступним для зовнішнього світу, ви опублікуєте необхідні порти.

Сподіваюся, ця стаття була вам корисною. Якщо у вас є питання, дайте мені знати в коментарях нижче.

Статті з цієї тематики:

  • Dockeye — новий графічний додаток для керування контейнерами/образами Docker у Linux
  • Нарешті з'явився Docker Desktop для Linux
  • PiCluster — простий веб-додаток для керування Docker
  • Аналізуйте та досліджуйте вміст образів Docker
  • Dockly – управління контейнерами Docker з терміналу
  • Пояснення концепцій мережі Docker
  • Пояснення томів Docker на прикладах
  • Початок роботи з Docker Compose у Linux
  • Як запустити Docker від імені користувача без повноважень root у Linux
  • Як налаштувати MySQL за допомогою Docker в Linux
  • Встановіть Docker Engine та Docker Compose в Ubuntu
  • Встановіть Docker в AlmaLinux, CentOS, Rocky Linux
  • Навчальний посібник з команд Docker | Початок роботи з Докером
  • Посібник для початківців з Docker Desktop для Linux
  • Автоматичне оновлення запущених контейнерів Docker за допомогою Watchtower

Усі права захищені. © Linux-Console.net • 2019-2024