Перенести порт хоста в контейнер докеров

Возможно ли иметь порты доступа к контейнерам Docker, открытые хостом? Конкретно у меня есть MongoDB и RabbitMQ, работающие на хосте, и я хотел бы запустить процесс в контейнере Docker для прослушивания очереди и (необязательно) записи в базу данных.

Я знаю, что я могу перейти из контейнера на хост (через опцию -p), и у меня есть подключение к внешнему миру (то есть интернету) из контейнера Docker, но я бы не хотел раскрывать RabbitMQ и порты MongoDB от хоста до внешнего мира.

ИЗМЕНИТЬ: некоторые уточнения:

Starting Nmap 5.21 ( http://nmap.org ) at 2013-07-22 22:39 CEST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00027s latency).
PORT     STATE SERVICE
6311/tcp open  unknown

[email protected] ~ % docker run -i -t base /bin/bash
[email protected]:/# apt-get install nmap
[email protected]:/# nmap 172.16.42.1 -p 6311 # IP found via docker inspect -> gateway

Starting Nmap 6.00 ( http://nmap.org ) at 2013-07-22 20:43 UTC
Nmap scan report for 172.16.42.1
Host is up (0.000060s latency).
PORT     STATE    SERVICE
6311/tcp filtered unknown
MAC Address: E2:69:9C:11:42:65 (Unknown)

Nmap done: 1 IP address (1 host up) scanned in 13.31 seconds

Мне пришлось сделать этот трюк, чтобы подключиться к контейнеру через интернет: Мой брандмауэр блокирует сетевые подключения из контейнера докера.

EDIT. В конце концов я пошел с созданием настраиваемого моста с помощью pipework и чтобы службы прослушивали мост IP. Я пошел с этим подходом, вместо того, чтобы MongoDB и RabbitMQ прослушивали мост докеров, потому что он дает большую гибкость.

Ответ 1

Ваш хост-докер предоставляет адаптер для всех контейнеров. Предполагая, что вы находитесь на недавнем ubuntu, вы можете запустить

ip addr

Это даст вам список сетевых адаптеров, один из которых будет выглядеть примерно как

3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 22:23:6b:28:6b:e0 brd ff:ff:ff:ff:ff:ff
inet 172.17.42.1/16 scope global docker0
inet6 fe80::a402:65ff:fe86:bba6/64 scope link
   valid_lft forever preferred_lft forever

Вам нужно будет сказать кролик/монго связать с этим IP (172.17.42.1). После этого вы сможете открывать соединения с 172.17.42.1 из своих контейнеров.

Ответ 2

Простым, но относительно небезопасным способом было бы использовать параметр --net=host для docker run.

Эта опция делает так, чтобы контейнер использовал сетевой стек хоста. Затем вы можете подключиться к службам, запущенным на хосте, просто используя "localhost" в качестве имени хоста.

Это проще настроить, потому что вам не нужно будет настраивать службу для приема соединений с IP-адреса вашего контейнера докеров, и вам не нужно будет указывать контейнеру докера конкретный IP-адрес или имя хоста для подключения to, только порт.

Например, вы можете протестировать его, выполнив следующую команду, которая предполагает, что ваше изображение называется my_image, ваше изображение включает утилиту telnet, а служба, к которой вы хотите подключиться, находится на порту 25:

docker run --rm -i -t --net=host my_image telnet localhost 25

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

https://docs.docker.com/articles/networking/

В нем говорится:

- net = host - указывает Docker пропустить размещение контейнера внутри отдельного сетевого стека. По сути, этот выбор говорит Docker о том, чтобы не контейнерная сеть! В то время как контейнерные процессы все равно будут ограничиваться их собственной файловой системой, списком процессов и ограничениями ресурсов, команда быстрого доступа ip добавит вам, что по сети они живут "снаружи" на главном хосте Docker и имеют полный доступ к своим сетевым интерфейсам, Обратите внимание, что это не позволяет контейнеру переконфигурировать сетевой стек хоста, который потребует --privileged = true, но он позволяет контейнерам обрабатывать порты с низким номером, как и любой другой корневой процесс. Он также позволяет контейнеру получать доступ к локальным сетевым сервисам, таким как D-bus. Это может привести к тому, что процессы в контейнере смогут совершать неожиданные действия, такие как перезагрузка компьютера. Вы должны использовать этот параметр с осторожностью.

Ответ 3

Если MongoDB и RabbitMQ запущены на хосте, порт должен быть уже выставлен, поскольку он не находится в Docker.

Вам не нужен параметр -p, чтобы выставлять порты из контейнера в хост. По умолчанию открыт весь порт. Параметр "-p" позволяет вам выставить порт из контейнера за пределы хоста.

Итак, я предполагаю, что вам вообще не нужен "-p", и он должен работать нормально:)

Ответ 4

Вы также можете создать туннель ssh.

docker-compose.yml:

---

version: '2'

services:
  kibana:
    image: "kibana:4.5.1"
    links:
      - elasticsearch
    volumes:
      - ./config/kibana:/opt/kibana/config:ro

  elasticsearch:
    build:
      context: .
      dockerfile: ./docker/Dockerfile.tunnel
    entrypoint: ssh
    command: "-N elasticsearch -L 0.0.0.0:9200:localhost:9200"

docker/Dockerfile.tunnel:

FROM buildpack-deps:jessie

RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive \
    apt-get -y install ssh && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

COPY ./config/ssh/id_rsa /root/.ssh/id_rsa
COPY ./config/ssh/config /root/.ssh/config
COPY ./config/ssh/known_hosts /root/.ssh/known_hosts
RUN chmod 600 /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/config && \
    chown $USER:$USER -R /root/.ssh

config/ssh/config:

# Elasticsearch Server
Host elasticsearch
    HostName jump.host.czerasz.com
    User czerasz
    ForwardAgent yes
    IdentityFile ~/.ssh/id_rsa

Таким образом, elasticsearch имеет туннель к серверу с запущенной службой (Elasticsearch, MongoDB, PostgreSQL) и предоставляет порт 9200 с этой службой.

Ответ 5

У меня была аналогичная проблема с доступом к LDAP-серверу из контейнера докеров. Я установил фиксированный IP-адрес для контейнера и добавил правило брандмауэра.

docker-compose.yml:

version: '2'
services:
  containerName:
    image: dockerImageName:latest
    extra_hosts:
      - "dockerhost:192.168.50.1"
    networks:
      my_net:
        ipv4_address: 192.168.50.2
networks:
  my_net:
    ipam:
      config:
      - subnet: 192.168.50.0/24

Правило iptables:

iptables -A INPUT -j ACCEPT -p tcp -s 192.168.50.2 -d $192.168.50.1 --dport portnumberOnHost

Внутри доступа к контейнеру dockerhost:portnumberOnHost