Як призначити відображення порту існуючому контейнерові Docker?


436

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


3
Використання iptables може працювати так, як ця відповідь Розкриття порту на контейнері Live Docker
Choldrim

2
Я підозрюю, що це задумом. Docker намагається змусити вас бути "повторюваними", і контейнер є типом "системи запису". Все, що ви робите як крок, що не впливає на контейнер, було б легко втраченим ручним кроком. Сказав інший спосіб: Ви хочете, щоб ваш контейнер представляв усю конфігурацію, необхідну для роботи. Тож якщо ви хочете відкрити новий порт, вам потрібно створити новий контейнер.
Lance Kind

2
Старе запитання, і я на нього не відповідаю, але я хотів би сказати, що, можливо, ви та люди, які запитують це питання та відповіді, можливо, повністю зрозуміли поняття докера. Докер призначені для без громадянства, які можуть масштабуватися вгору або вниз багато разів. Ніколи не слід зберігати щось у контейнері для виробничого середовища, яке неможливо відтворити, якщо вам потрібно наполегливо зберігати, картографуйте каталоги. Docker - це не щось на зразок "light vm", можливо, ви шукаєте це linuxcontainers.org, lxd заснований на концепції docker, але має на увазі "light vm".
Едгар Карвальо

на випадок, якщо це може допомогти, можна використовувати інструмент "Kitematic" для додавання карти портів до вже запущених контейнерів. Це має означати, що має бути команда docker, щоб зробити саме те саме, але з невеликим гуглом :) Удачі
Yaffah

Відповіді:


298

Ви можете змінити зіставлення портів, безпосередньо відредагувавши hostconfig.jsonфайл на /var/lib/docker/containers/[hash_of_the_container]/hostconfig.json

Ви можете визначити [hash_of_the_container] за допомогою docker inspect <container_name>команди, а значення поля "Id" - хеш.

1) stop the container 
2) stop docker service (per Tacsiazuma's comment)
3) change the file
4) restart your docker engine (to flush/clear config caches)
5) start the container

Тому вам не потрібно створювати зображення при такому підході. Тут також можна змінити прапор перезапуску.

PS Ви можете відвідати https://docs.docker.com/engine/admin/, щоб дізнатися, як правильно перезапустити движок докера відповідно до вашого хост-машини. Я sudo systemctl restart dockerперезапускав свій докер-движок, який працює на Ubuntu 16.04


17
Коли докер зупиняється, здається, що замінить ваші зміни, тому 2. зупиніть докер, 3. змініть файл, 4. запустіть докер-движок
Tacsiazuma

5
Я спробував вище, і це працює. Детальніше дивіться: mybrainimage.wordpress.com/2017/02/05/…
rohitmohta

11
Важливо зупинити контейнер, зупинити докерний двигун і змінити обидва hostconfig.jsonі config.v2.jsonзробити цю роботу. Скористайтеся посиланням, яке надає @rohitmohta, щоб переглянути деталі.
Калпак Гадре

5
працював для мене, лише одне, якщо ви користуєтеся програмою docker на mac, дотримуйтесь інструкцій тут, щоб дістатися до / var / lib / docker / контейнерів папки: stackoverflow.com/a/41226917/2048266 , в основному запустіть screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/ttyПісля того, як ви отримаєте Tty запуск, ви можете перейти до / var / lib /
docker

14
для Windows, будь-хто, будь ласка, поділіться мені місцем папки conatiners.?
Віджай

463

Мене також цікавить ця проблема.

Як зазначалося @Thasmo , переадресацію портів можна задавати ТІЛЬКИ за допомогою команди docker rundocker create).
Інші команди, docker startне мають -pопції і docker portвідображають лише поточні переадресації.

Щоб додати переадресацію портів, я завжди виконую ці кроки,

  1. перестати працювати контейнер

    docker stop test01
    
  2. здійснити контейнер

    docker commit test01 test02
    

    ПРИМІТКА . Наведене вище test02- це нове зображення, яке я будую з test01контейнера.

  3. повторно запустити з дорученого зображення

    docker run -p 8080:8080 -td test02
    

Де перший 8080 - локальний порт, а другий 8080 - порт контейнерів.


15
Що робити, якщо я хочу зберегти ім'я test01?
користувач69715

12
Хтось знає, чи існує проблема з Docker, щоб дозволити специфікацію портів (--publish) docker start?
Ілля Лінн

8
А що відбувається з обсягами в цьому сценарії?
Андрій Савіних

78
Це жахливе рішення, я поняття не маю, як вдалося заробити 250 грошей. Можливо, ті, хто наголосився, не знали, який безлад викликає це рішення. Так, це жахливо, і це дорівнює запуску нового контейнера, який працює на іншому порту.
Arrrr

25
@Arrrr Можливо, ви хочете залишити кращу відповідь? Я впевнений, що ми всі вдячні, якби ви сказали нам набагато кращий спосіб зробити це.
crockeea

40

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

Однак ви можете динамічно додати новий мережевий інтерфейс, наприклад, з Pipework , якщо вам потрібно виставити послугу в запущеному контейнері без зупинки / перезавантаження.


4
Це має бути головна відповідь. Короткий і він вирішує питання ОП, яке ніхто з інших не робить! Іноді негативний результат - це результат!
Мінлива хмарність

19

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

$ docker run -p <public_port>:<private_port> -d <image>  

почне працювати контейнер. Цей підручник пояснює перенаправлення портів.


2
Так, здається, що можна створити лише такі параметри, як картографування портів під час створення контейнерів.
thasmo

20
Ця відповідь не зовсім коректна. docker runстворює та запускає новий контейнер. Це рівнозначно тому, що docker createслід docker start.
Тревор Салліван

19

Здається, редагування hostconfig.json зараз не працює. Він закінчується лише тим, що порт відкривається, але не публікується для розміщення. Здійснення та відтворення контейнерів - не найкращий підхід до мене. Ніхто не згадав docker network?

Найкращим рішенням буде використання зворотного проксі-сервера в одній мережі

  1. Створіть нову мережу, якщо ваш попередній контейнер не в жодному з названих.

    docker network create my_network

  2. Приєднуйтесь до наявного контейнера до створеної мережі

    docker network connect my_network my_existing_container

  3. Запустіть зворотну службу проксі (наприклад, nginx), публікуючи потрібні вам порти, приєднавшись до тієї ж мережі

    docker run -d --name nginx --network my_network -p 9000:9000 nginx

    Необов’язково видаліть default.conf у nginx

    docker exec nginx rm /etc/nginx/conf.d/default.conf

  4. Створіть новий конфігурацію nginx

    server
    {
        listen 9000;
    
        location / {
            proxy_pass http://my_existing_container:9000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }
    

    Скопіюйте конфігурацію в контейнер nginx.

    docker cp ./my_conf.conf nginx:/etc/nginx/conf.d/my_conf.conf

  5. Перезапустіть nginx

    docker restart nginx

Переваги : Щоб опублікувати нові порти, ви можете безпечно зупиняти / оновлювати / відтворювати контейнер nginx за своїм бажанням, не торкаючись бізнес-контейнера. Якщо для nginx вам потрібен нульовий час, можна додати більше зворотних проксі-сервісів, що приєднуються до тієї ж мережі. Крім того, контейнер може приєднатися до декількох мереж.

Редагувати:

Для повернення проксі-сервісів, які не http, файл конфігурації дещо інший. Ось простий приклад:

upstream my_service {
    server my_existing_container:9000;
}

server {
    listen 9000;
    proxy_pass my_service;
}

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

1
@Afshin Добре для корпоративних систем або проектів, я думаю, що це рішення краще, ніж відтворити (спричиняє час роботи) або зламати файл hostconfig.json (принаймні, офіційно не представлений). Додатковий контейнер просто розкриває внутрішній порт вашого контейнера, а не вносить зміни до нього.
Шон К.

1
Дивовижний підхід. Мені потрібно було по-різному налаштувати nginx, щоб мій контейнер працював за проксі, але здається, що це правильний спосіб робити речі. Працює і для синьо-зеленого розгортання.
Брукс Дюбуа

18

У прикладі Фухімото Юїчі test01є контейнером, тоді test02як зображенням.

Перш ніж docker runви можете вийняти оригінальний контейнер, а потім присвоїти йому знову те саме ім’я:

$ docker stop container01
$ docker commit container01 image01
$ docker rm container01
$ docker run -d -P --name container01 image01

(Використання -Pдля викриття портів випадковим портам, а не присвоєння їх вручну).


12
Зверніть увагу. ви втратите всі свої дані, залежно від програми, яка знаходиться всередині.
Баррі

14

Якщо ви запустите, docker run <NAME>він породить нове зображення, яке, швидше за все, не те, що ви хочете.

Якщо ви хочете змінити поточне зображення, зробіть наступне:

docker ps -a

Візьміть ідентифікатор вашого цільового контейнера та перейдіть до:

cd /var/lib/docker/containers/<conainerID><and then some:)>

Зупинка контейнера:

docker stop <NAME>

Змініть файли

vi config.v2.json

"Config": {
    ....
    "ExposedPorts": {
        "80/tcp": {},
        "8888/tcp": {}
    },
    ....
},
"NetworkSettings": {
....
"Ports": {
     "80/tcp": [
         {
             "HostIp": "",
             "HostPort": "80"
         }
     ],

І змінити файл

vi hostconfig.json

"PortBindings": {
     "80/tcp": [
         {
             "HostIp": "",
             "HostPort": "80"
         }
     ],
     "8888/tcp": [
         {
             "HostIp": "",
             "HostPort": "8888"
         } 
     ]
 }

Перезавантажте свій докер і він повинен працювати.


2
Це не спрацювало для мене на версії Docker 17.09.0-ce. Після запуску файлів конфігурації контейнера повернулися до старих значень.
thegeko

3
перезапустити послугу докера в хост-системі @thegeko
yurenchen

1
це працює! tks! 1. Stop контейнер, 2.change файли, 3.restart docker, 4.start back контейнер
datdinhquoc

12

З іншого боку, якщо вам не зручно налаштовувати глибину налаштування Докера, IPtables стане вашим другом.

iptables -t nat -A DOCKER -p tcp --dport ${YOURPORT} -j DNAT --to-destination ${CONTAINERIP}:${YOURPORT}

iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp --source ${CONTAINERIP} --destination ${CONTAINERIP} --dport ${YOURPORT}

iptables -A DOCKER -j ACCEPT -p tcp --destination ${CONTAINERIP} --dport ${YOURPORT}

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


це чудова відповідь! Дякую! Якщо я хочу , щоб відобразити DOCKER_PORTв MACHINE_PORT, які частини повинні бути змінені?
Ciprian Tomoiagă

Зверніть увагу, що докер не знає про це доповнення вручну. Записи SO не видаляються, коли ви пізніше перезапустите службу за допомогою докера, відкривши порти належним чином. Тож коли щось зміниться, не забудьте дуже ретельно перевірити iptables. Особливо шукайте повторювані записи!
Антоній

8

ми використовуємо такі зручні інструменти, як ssh, щоб це легко досягти.

Я використовував зображення докера на базі ubuntu та зображення докера на основі ubuntu.

  1. Всередині докера встановлений клієнт opensh.
  2. Зовні докер (хост) встановлений сервер opensh-сервера.

коли потрібен новий порт для відображення,

всередині докера запустіть наступну команду

ssh -R8888:localhost:8888 <username>@172.17.0.1

172.17.0.1 був ip інтерфейсу докера (ви можете отримати це, запустивши ifconfig docker0 | grep "inet addr" | cut -f2 -d":" | cut -f1 -d" "на хост).

тут у мене був місцевий порт 8888, зібраний назад до хостів 8888. Ви можете змінити порт за потребою.

якщо вам потрібен ще один порт, ви можете вбити ssh і додати до нього ще один рядок -R за допомогою нового порту.

Я перевірив це за допомогою netcat.


2
  1. Зупиніть двигун докера та той контейнер.
  2. Перейдіть до /var/lib/docker/containers/${container_id}каталогу та відредагуйтеhostconfig.json
  3. Відредагуйте, PortBindings.HostPortщо хочете зміни.
  4. Запустіть докерний двигун і контейнер.

-1

Для користувачів Windows і Mac є ще один досить простий і дружній спосіб змінити порт зіставлення:

  1. скачати набір

  2. перейдіть на сторінку налаштувань контейнера, на вкладці порти ви можете безпосередньо змінити там опублікований порт.

  3. запустити контейнер знову


2
Я спробував такий підхід. Кінематик застосував відображення портів. Однак, щоб застосувати їх, він знову створив мій контейнер з оригінального зображення. Тож якщо ви боїтесь втратити зміни, внесені в сам контейнер, не використовуйте цей метод.
VeganHunter

1
Я віддав перевагу цьому, я вважаю, що він не відповідає на питання, і він створює новий контейнер. Але принаймні це працює, і цей результат СА з’явився під час мого пошуку. +1
2b77bee6-5445-4c77-b1eb-4df3e5

-7

Короткий відповідь: Ви не можете призначити зіставлення портів існуючому контейнеру Docker

Вам потрібен новий контейнер ... розібрайтеся з ним.


4
Не потрібно ставлення. Також у цій відповіді повністю бракує деталей.
lovefaithswing

1
Не потрібно деталей. Тон має вирішальне значення для передачі цього часу економії відповіді та ефемерного характеру контейнерів.
Стефан

-11

Якщо ви просто хочете змінити порт запущеного контейнера, зробіть:

  1. зупинити існуючий контейнер

    sudo docker stop NAME

  2. тепер перезапустіть нове зіставлення портів

    sudo docker run -d -p 81:80 ІМ’Я

де як:

"-d" для фону / deamon докер

"-p" увімкнути відображення портів

Зовнішній (відкритий) порт "81", який ви використовуєте для доступу зі своїм браузером

Порт прослуховування внутрішнього контейнера докера "80"


4
Це просто неправильно. В docker runкоманді, NAMEце ім'я зображення , щоб запустити контейнер з, тоді як в ставиться до імені контейнера до зупинки. docker stopNAME
Джонатан

1
"запустити докер" створить новий контейнер. Він не може використовувати те саме ім’я контейнера, що і те, що було зупинено, оскільки ви можете мати лише один контейнер з цим ім'ям. Отже, вам потрібно буде зробити: "docker stop NAME", докер-контейнер rm NAME, потім "docker run -d -p 81:80 NAME", як ви це написали.
Lance Kind
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.