ホストポートをDockerコンテナーに転送する


166

ホストが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

joelkuiper@vps20528 ~ % docker run -i -t base /bin/bash
root@f043b4b235a7:/# apt-get install nmap
root@f043b4b235a7:/# 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

コンテナーとのインターネット接続を取得するには、このトリックを実行する必要がありました:ファイアウォールが、Docker コンテナーから外部へのネットワーク接続をブロックしています

編集:最終的には、パイプワークを使用してカスタムブリッジを作成し、サービスがブリッジIPでリッスンするようにしました。MongoDBとRabbitMQがdockerブリッジでリッスンするのではなく、このアプローチを採用しました。これにより、柔軟性が向上します。

回答:


53

Dockerホストは、すべてのコンテナーにアダプターを公開します。あなたが最近のubuntuにいると仮定すると、実行することができます

ip addr

これにより、ネットワークアダプターのリストが表示されます。その1つは次のようになります。

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)にバインドするようrabbit / mongoに指示する必要があります。その後、コンテナ内から172.17.42.1への接続を開くことができるはずです。


35
コンテナーはどのようにしてリクエストを送信するIPを知るのですか?私は値をハードコードできます(ここと私のテストリグで172.17.42.1ですが、それは常に正しいですか?)。
JP。

2
@セルド:そのインターフェースを表示するには設定が必要ですか?私は、ドッキングウィンドウ1.7.1を使用しています、と私は持っているloeth0
mknecht 2015

8
ホストが127.0.0.1でのみリッスンしている場合、これをどうにかすることは可能ですか?
HansHarhoff 2016年

5
「rabbit / mongoにそのIP(172.17.42.1)にバインドするように指示する必要があります。その後、コンテナー内から172.17.42.1への接続を開くことができるはずです。」あなたがそれをする方法を説明したならいいでしょう
Novaterata

1
@Novaterataが述べたように、誰かがそのプロセスを説明できますか?
keskinsaf

121

単純ですが比較的安全ではない方法は、の--net=hostオプションを使用することdocker runです。

このオプションは、コンテナーがホストのネットワークスタックを使用するようにします。次に、ホスト名として「localhost」を使用するだけで、ホストで実行されているサービスに接続できます。

これは、DockerコンテナーのIPアドレスからの接続を受け入れるようにサービスを構成する必要がなく、Dockerコンテナーに接続する特定のIPアドレスまたはホスト名を通知する必要がないため、構成が簡単です。ポート。

たとえば、次のコマンドを実行してテストできます。これは、イメージがと呼ばれ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 addrコマンドは、ネットワーク的には、メインのDockerホストの「外部」に存在し、そのネットワークインターフェースへの完全なアクセス権があることを示します。これにより、コンテナーがホストネットワークスタックを再構成することはできません(--privileged = trueが必要になります)が、コンテナープロセスは他のルートプロセスのように小さい番号のポートを開くことができます。また、コンテナーはDバスなどのローカルネットワークサービスにアクセスできます。これにより、コンテナー内のプロセスがコンピューターの再起動などの予期しないことを実行できるようになります。


12
LinuxでDockerを使用していない(たとえば、仮想化を使用している)場合、ホストは実際のホストOSではなく包含VMになるため、これは機能しません。
Sebastian Graf

13
具体的には、MacOSで、これは不可能である(いくつかの回避策なし):docs.docker.com/docker-for-mac/networking/...
PJE

15
MacOSでは、--net=hostを使用してコンテナープロセスがホストマシンに接続できるようにするには機能しませんlocalhost。代わりに、コンテナをのdocker.for.mac.host.internal代わりにMacOS専用のホスト名に接続してくださいlocalhostdocker runこれが機能するために追加のパラメータは必要ありません。-eコンテナープラットフォームにとらわれないようにしたい場合は、これをenv varとして渡すことができます。そうすれば、env varで指定されたホストに接続して、docker.for.mac.host.internalMacOSとlocalhostLinuxに渡すことができます。
2018年

18
Macの最新のホスト名はhost.docker.internalドキュメントを
xysun

Windows用と同じdocker run --rm -it --net=host postgres bash、その後psql -h host.docker.internal -U postgres
レオCavalcante

12

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を公開します。


8
基本的には、Dockerイメージに秘密鍵を配置します。シークレットがDockerイメージに入らないようにしてください。
Teoh Han Hui

2
これは、これまで使用可能な唯一の正気なソリューションです。
2018年

5

Dockerコンテナから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


3

MongoDBとRabbitMQがホスト上で実行されている場合、ポートはDocker内にないため、すでに公開されているはずです。

-pコンテナーからホストにポートを公開するためにオプションは必要ありません。デフォルトでは、すべてのポートが公開されています。この-pオプションを使用すると、コンテナーからホストの外部にポートを公開できます。

だから、私の推測では、あなたはまったく必要なく-p、それはうまく機能しているはずです:)


1
私はそれを知っていましたが、少し情報が不足しているようです:ホストのポートに到達できないため、最近の編集を参照してください。
JoelKuiper 2013

2
メインネットワークインターフェースだけでなく、ブリッジでもリッスンするようにrabbitmqとmongodbを設定する必要があります。
2013

13
@creack rabbitmqとmongodbを橋の上で聞くにはどうすればいいですか?
Ryan Walls
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.