Предоставление порта в реальном контейнере Docker


Answers

Вот что я сделал бы:

  • Зафиксируйте живой контейнер.
  • Запустите контейнер снова с новым изображением, с открытыми портами (я бы рекомендовал монтировать общий том и открыть порт ssh)
sudo docker ps 
sudo docker commit <containerid> <foo/live>
sudo docker run -i -p 22 -p 8000:80 -m /data:/data -t <foo/live> /bin/bash
Question

Я пытаюсь создать контейнер Docker, который действует как полнофункциональная виртуальная машина. Я знаю, что я могу использовать инструкцию EXPOSE внутри файла Docker, чтобы открыть порт, и я могу использовать флаг -p с docker run для назначения портов, но как только контейнер фактически запущен, есть команда открывать / отображать дополнительные порты в реальном времени ?

Например, допустим, у меня есть контейнер Docker, который запускает sshd. Кто-то еще использует контейнер ssh и устанавливает httpd. Есть ли способ открыть порт 80 на контейнере и отобразить его на порт 8080 на хосте, чтобы пользователи могли посещать веб-сервер, работающий в контейнере, без перезапуска?




Пакеты IPtables не работают, по крайней мере, на Docker 1.4.1.

Лучшим способом было бы запустить другой контейнер с открытым портом и реле с помощью socat. Это то, что я сделал (временно) для подключения к базе данных с помощью SQLPlus:

docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus

Dockerfile:

FROM debian:7

RUN apt-get update && \
    apt-get -y install socat && \
    apt-get clean

USER nobody

CMD socat -dddd TCP-LISTEN:1521,reuseaddr,fork TCP:db:1521



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

Интерфейсы Macvlan

Теперь Docker включает сетевой драйвер Macvlan . Это придает сети Docker интерфейс «реального мира» и позволяет назначать адреса сетей непосредственно в контейнере (например, в режиме мостов с виртуальными машинами).

docker network create \
    -d macvlan \
    --subnet=172.16.86.0/24 \
    --gateway=172.16.86.1  \
    -o parent=eth0 pub_net

pipework также может отображать реальный интерфейс в контейнер или настраивать дополнительный интерфейс в более старых версиях Docker.

Маршрутизация IP-адресов

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

Затем вы назначаете эту сеть контейнерам и настраиваете хост Docker для маршрутизации пакетов через сеть докеров.

Общий интерфейс хоста

Параметр --net host позволяет --net host -интерфейсом в контейнере, но это, вероятно, не очень хорошая настройка для запуска нескольких контейнеров на одном хосте из-за общей природы.




Существует удобная оболочка HAProxy.

docker run -it -p LOCALPORT:PROXYPORT --rm --link TARGET_CONTAINER:EZNAME -e "BACKEND_HOST=EZNAME" -e "BACKEND_PORT=PROXYPORT" demandbase/docker-tcp-proxy

Это создает HAProxy для целевого контейнера. очень просто.




Существует также флаг -P который является совершенно новым и сообщает Docker о необходимости сопоставления любых необходимых сетевых портов внутри нашего контейнера с нашим хостом. Это поможет вам просматривать веб-приложение из внешнего мира.

Когда вы привязываетесь к порту, Docker перенаправляет его для вас. Используя команду порта Docker, вы увидите что-то вроде этого:

docker port 5019f8e8f902
5000/tcp -> 0.0.0.0:49162
5555/tcp -> 0.0.0.0:49163
8080/tcp -> 0.0.0.0:49164



Если ни один ответ не работает для кого-то - проверьте, что ваш целевой контейнер уже запущен в сети докеров:

docker inspect my-target-container | grep NetworkMode
        "NetworkMode": "my-network-name",

Если да, вы должны запустить контейнер прокси в той же сети.

docker inspect my-target-container | grep -A2 Aliases
                "Aliases": [
                    "my-alias",
                    "23ea4ea42e34a"

Конечная команда:

docker run --net my-network-name --name my-new-proxy \
-d -p 8080:1234 alpine/socat TCP-LISTEN:1234,fork TCP-CONNECT:my-alias:80



Я должен был решить эту проблему и смог ее решить, не останавливая ни один из моих запущенных контейнеров. Это решение обновлено по состоянию на февраль 2016 года, используя Docker 1.9.1. В любом случае, этот ответ представляет собой подробную версию ответа @ ricardo-branco, но более подробно для новых пользователей.

В моем сценарии я хотел временно подключиться к MySQL, работающему в контейнере, и поскольку к нему привязаны другие контейнеры приложений, остановка, реконфигурация и повторный запуск контейнера базы данных была не стартером.

Поскольку я хотел бы получить доступ к базе данных MySQL извне (из Sequel Pro через SSH-туннелирование), я собираюсь использовать порт 33306 на главной машине. (Не 3306 , на случай, если работает внешний экземпляр MySQL).

Примерно за час чистки iptables оказалось бесплодным, хотя:

Шаг за шагом, вот что я сделал:

mkdir db-expose-33306
cd db-expose-33306
vim Dockerfile

Измените dockerfile , разместив его внутри:

# Exposes port 3306 on linked "db" container, to be accessible at host:33306
FROM ubuntu:latest # (Recommended to use the same base as the DB container)

RUN apt-get update && \
    apt-get -y install socat && \
    apt-get clean

USER nobody
EXPOSE 33306

CMD socat -dddd TCP-LISTEN:33306,reuseaddr,fork TCP:db:3306

Затем создайте изображение:

docker build -t your-namespace/db-expose-33306 .

Затем запустите его, привязав к вашему запущенному контейнеру. (Используйте -d вместо -rm чтобы сохранить его в фоновом режиме, пока явным образом не остановится и не удаляется. В этом случае я хочу, чтобы он выполнялся временно).

docker run -it --rm --name=db-33306 --link the_live_db_container:db -p 33306:33306  your-namespace/db-expose-33306



Вы можете использовать SSH для создания туннеля и выставить свой контейнер на своем хосте.

Вы можете сделать это в обоих направлениях: от контейнера до хоста и от хоста к контейнеру. Но вам нужен SSH-инструмент, такой как OpenSSH, как (клиент на одном, так и сервер в другом).

Например, в контейнере вы можете сделать

$ yum install -y openssh openssh-server.x86_64
service sshd restart
Stopping sshd:                                             [FAILED]
Generating SSH2 RSA host key:                              [  OK  ]
Generating SSH1 RSA host key:                              [  OK  ]
Generating SSH2 DSA host key:                              [  OK  ]
Starting sshd:                                             [  OK  ]
$ passwd # You need to set a root password..

IP-адрес контейнера можно найти в этой строке (в контейнере):

$ ifconfig eth0 | grep "inet addr" | sed 's/^[^:]*:\([^ ]*\).*/\1/g'
172.17.0.2

Затем в хосте вы можете просто сделать:

sudo ssh -NfL 80:0.0.0.0:80 root@172.17.0.2



Related



Tags

docker docker