私はjenkinsを実行しているdockerコンテナを持っています。ビルドプロセスの一部として、ホストマシン上でローカルに実行されているWebサーバーにアクセスする必要があります。ホストWebサーバー(ポート上で稼働するように構成できる)をjenkinsコンテナーに公開する方法はありますか?
編集:私はLinuxマシン上でネイティブにdockerを実行しています。
更新:
ホストマシンからホストIPのIPアドレスを取得するために、以下の@larsks回答に加えて、私は次のことを行います。
ip addr show docker0 | grep -Po 'inet \K[\d.]+'
DockerをLinux上でネイティブに実行している場合は、docker0
インターフェースのIPアドレスを使用してホストサービスにアクセスできます。コンテナの内側からは、これがデフォルトのルートになります。
たとえば、私のシステムでは、
$ ip addr show docker0
7: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::f4d2:49ff:fedd:28a0/64 scope link
valid_lft forever preferred_lft forever
そしてコンテナの中:
# ip route show
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0 src 172.17.0.4
簡単なシェルスクリプトを使用してこのIPアドレスを抽出するのはかなり簡単です。
#!/bin/sh
hostip=$(ip route show | awk '/default/ {print $3}')
echo $hostip
Dockerコンテナーからの接続を許可するために、ホスト上のiptables
規則を変更する必要があるかもしれません。このような何かがトリックをするでしょう:
# iptables -A INPUT -i docker0 -j ACCEPT
これにより、Dockerコンテナからホスト上のすべてのポートへのアクセスが許可されます。ご了承ください:
iptablesの規則は順序付けされています、そしてこの規則はそれより前に来る他の規則に応じて正しいことをするかもしれないししないかもしれません。
(a)INADDR_ANY
(別名0.0.0.0)をリッスンしているホストサービス、またはdocker0
インターフェースを明示的にリッスンしているホストサービスにのみアクセスできます。
Docker v 18.03以降(2018年3月21日以降)
内部IPアドレスを使用するか、ホストが使用する内部IPアドレスに解決される特別なDNS名Host.docker.internal
に接続します。
Linuxのサポートは保留中です https://github.com/docker/for-linux/issues/264
Docker for Mac v 17.12からv 18.02
上記と同じですが、代わりにdocker.for.mac.Host.internal
を使用してください。
Docker for Mac v 17.06からv 17.11
上記と同じですが、代わりにdocker.for.mac.localhost
を使用してください。
Docker for Mac 17.05以下
Docker containerからHost machineにアクセスするには、ネットワークインターフェースにIPエイリアスを添付する必要があります。どのIPを使用しても構いませんが、使用していないことを確認してください。
Sudo ifconfig lo0 alias 123.123.123.123/24
次に、サーバーが上記のIPまたは0.0.0.0
をリッスンしていることを確認してください。 localhostの127.0.0.1
をリッスンしている場合は、接続を受け入れません。
それからあなたのdockerコンテナをこのIPに向けるだけで、あなたはHostマシンにアクセスすることができます!
テストするためにはコンテナの中でcurl -X GET 123.123.123.123:3000
のようなものを実行することができます。
エイリアスは再起動のたびにリセットされるので、必要に応じて起動スクリプトを作成します。
ここにソリューションとより多くのドキュメンテーション: https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds
--net="Host"
コマンドでdocker run
を使用すると、dockerコンテナのlocalhost
はdocker Hostを指します。
Docker-composeによる解決策:ホストベースのサービスにアクセスするにはnetwork_mode
パラメータ https://docs.docker.com/compose/compose-file/#network_mode を使用できます。
version: '3'
services:
jenkins:
network_mode: Host
現在MacとWindowsでこれを行う最も簡単な方法はHost Host.docker.internal
を使うことです。これはホストマシンのIPアドレスに解決されます。残念ながら はまだLinuxでは動作しません (2018年4月現在)。
私はまさにそれを行うためのdockerコンテナーを作成しました https://github.com/qoomon/docker-Host
そうすれば、単純にコンテナ名dnsを使ってホストシステムにアクセスできます。 curl http://dockerhost:9200
私たちは、このネットワーキングジャンクすべてに対するより簡単な解決策は、サービスにドメインソケットを使用することであることがわかりました。とにかくホストに接続しようとしているのであれば、ソケットをボリュームとしてマウントするだけでいいのです。 postgresqlの場合、これは次のように簡単でした。
docker run -v /var/run/postgresql:/var/run/postgresql
その後、ネットワークではなくソケットを使用するようにデータベース接続を設定します。文字通りとても簡単です。
ホストマシンで動作しているローカルウェブサーバーにアクセスするには2つの方法があります。
パブリックIPによるアプローチ1
Jenkins docker container内のWebサーバにアクセスするには、ホストマシンのパブリックIPアドレスを使用してください。
ホストネットワークでのアプローチ2
ホストのネットワークスタックにJenkins dockerコンテナを追加するには、 " - net Host"を使用します。ホストのスタックに配置されているコンテナは、ホストインタフェースへのアクセス権をすべて持っています。ホストマシンのプライベートIPアドレスを使ってdocker container内のローカルウェブサーバーにアクセスできます。
NETWORK ID NAME DRIVER SCOPE
b3554ea51ca3 bridge bridge local
2f0d6d6fdd88 Host Host local
b9c2a4bc23b2 none null local
ホストネットワークEg: docker run --net Host -it ubuntu
でコンテナーを起動し、ifconfig
を実行してdockerコンテナーから到達可能なすべての利用可能なネットワークIPアドレスをリストします。
例:私は自分のローカルホストマシンでnginxサーバを起動し、Ubuntu docker containerからnginxウェブサイトのURLにアクセスすることができます。
docker run --net Host -it ubuntu
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a604f7af5e36 ubuntu "/bin/bash" 22 seconds ago Up 20 seconds ubuntu_server
プライベートネットワークIPアドレスを使用してUbuntu docker containerからNginx Webサーバー(ローカルホストマシンで実行中)にアクセスする。
root@linuxkit-025000000001:/# curl 192.168.x.x -I
HTTP/1.1 200 OK
Server: nginx/1.15.10
Date: Tue, 09 Apr 2019 05:12:12 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 26 Mar 2019 14:04:38 GMT
Connection: keep-alive
ETag: "5c9a3176-264"
Accept-Ranges: bytes
2つのdockerイメージが「すでに」作成されていて、互いに通信するために2つのコンテナを配置したい場合。
そのためには、各コンテナを独自の--nameを付けて実行し、 - linkフラグを使用してそれらの間の通信を有効にすることができます。ただし、docker build中はこれを取得できません。
あなたが私のようなシナリオにいるとき、それはあなたの
docker build -t "centos7/someApp" someApp/
あなたがしようとするとそれは壊れます
curl http://172.17.0.1:localPort/fileIWouldLikeToDownload.tar.gz > dump.tar.gz
そして、 "curl/wget"で立ち往生し、 "ホストへの経路"が返されません。
その理由は、コンテナからホストへの通信、またはホスト上で実行されている他のコンテナへの通信をデフォルトで禁止するというdockerによって設定されているセキュリティです。これは私にとって非常に驚くべきことでした、私は言わなければなりません、あなたはローカルマシン上で走っているdockerマシンのエコーシステムがあまりにも多くのハードルなしでお互いにアクセスできることを期待するでしょう。
これについての説明は、次のドキュメントで詳しく説明されています。
http://www.dedoimedo.com/computers/docker-networking.html
ネットワークセキュリティを低下させて移動するのに役立つ2つの簡単な回避策があります。
最も簡単な方法は、ファイアウォールをオフにするか、すべて許可することです。これは、systemctl stop firewalld、iptables -F、または同等のコマンドで、必要なコマンドを実行することを意味します。
この情報がお役に立てば幸いです。
私はさまざまな解決策を検討しましたが、私はこれが最もハッカーの少ない解決策だと思います。
唯一の欠点は、複数のネットワークやプロジェクトがある場合、それらのIPアドレス範囲が競合しないようにする必要があることです。
これがDocker Composeの例です。
version: '2.3'
services:
redis:
image: "redis"
extra_hosts:
- "dockerhost:172.20.0.1"
networks:
default:
ipam:
driver: default
config:
- subnet: 172.20.0.0/16
gateway: 172.20.0.1
その後、ホスト名 "dockerhost"を使用してコンテナ内からホスト上のポートにアクセスできます。