質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

ネットワーク

ネットワークとは、複数のコンピューター間を接続する技術です。インターネットが最も主流なネットワークの形態で、TCP/IP・HTTP・DNSなどの様々なプロトコルや、ルータやサーバーなどの様々な機器の上に成り立っています。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

9700閲覧

2つのDockerコンテナ間で通信がしたい

xsteviax

総合スコア14

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

ネットワーク

ネットワークとは、複数のコンピューター間を接続する技術です。インターネットが最も主流なネットワークの形態で、TCP/IP・HTTP・DNSなどの様々なプロトコルや、ルータやサーバーなどの様々な機器の上に成り立っています。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

1クリップ

投稿2020/03/30 06:01

編集2020/03/31 03:29

前提・実現したいこと

2つのコンテナの間で連携するプログラムを作りたい。
そのためにまずは、pythonライブラリーのsocketでTCP通信したい。
現状、コンテナ間でPINGは通っている。

発生している問題・エラーメッセージ

socketの公式サイトにあるサンプルプログラムを試したが、通信できなかった。
以下に示すように、クライアント側でエラーとなってしまった。
公式のサンプルプログラムを2つのコンテナ上で互いに動作させるにはどうしたらいいでしょうか?

  • サーバー側コンテナ(正常な待機状態)

bash

1root@48bce5a558f4:~/ubuntu_socket/socket_test# python socket_Server.py 2Server started. Listening on ('172.17.0.2', 11113)
  • クライアント側コンテナ(エラー)

bash

1root@5521f5ec4a59:~/ubuntu_socket/socket_test# python socket_Client.py 2Traceback (most recent call last): 3 File "socket_Client.py", line 4, in <module> 4 response, addr = client.poll_server("Hello world", server=('172.17.0.2', 11113)) 5 File "/usr/local/lib/python3.6/dist-packages/sockets/python3/client.py", line 16, in poll_server 6 self.socket.sendto(bytes(data, "utf-8"), server) 7OSError: [Errno 22] Invalid argument

該当のソースコード

  • サーバー側の「docker run」
$ docker run -it -v $(pwd)/:/root/ubuntu_socket \ -w /root/ubuntu_socket/socket_test -p 11113:11114 ubuntu:Sock
  • クライアント側の「docker run」
$ docker run -it -v $(pwd)/:/root/ubuntu_socket \ -w /root/ubuntu_socket/socket_test -p 11114:11113 ubuntu:Sock
  • サーバー側コンテナのpythonファイル(socket_Server.py)

python

1# Test server with Python3: 2from sockets.python3.server import Server 3class MyServer(Server): 4 def act_on(self, data, addr): 5 # Do something with data (in bytes) and return a string. 6 return data.decode() 7server = MyServer(listening_address=('172.17.0.2', 11113)) 8server.listen()
  • クライアント側コンテナのpythonファイル(socket_Client.py)

python

1# Test client with Python3. Polls the Python3 server. 2from sockets.python3.client import Client 3client = Client() 4response, addr = client.poll_server("Hello world", server=('172.17.0.2', 11113)) 5print(response, addr)

質問の過程で試したこと(追記3/31)

サーバー側のポートのみ開放

  • サーバー側の「docker run」
$ docker run -it -v $(pwd)/:/root/ubuntu_socket \ -w /root/ubuntu_socket/socket_test -p 11113:11113 --name server_container ubuntu:Sock
  • クライアント側の「docker run」
$ docker run -it -v $(pwd)/:/root/ubuntu_socket \ -w /root/ubuntu_socket/socket_test --name client_container ubuntu:Sock

Dockerデフォルトで作成されるブリッジネットワーク「bridge」に、2つのコンテナが接続されていることを確認

  • 「bridge」の「netwark inspect」の一部
"Containers": { "8d2b0325708e3a495e985a245326f57b297e68546df1cdf7d61b2cd1030bc869": { "Name": "client_container", "EndpointID": "edd55ed2401674eca6bb8707b04e8856d036bd4e35e2beb97fdc36b2c14c488e", "MacAddress": "02:42:ac:11:00:03", "IPv4Address": "172.17.0.3/16", "IPv6Address": "" }, "c77b59eb1042f6e6b48502303c92046419226daae630fbd818d700571eda990b": { "Name": "server_container", "EndpointID": "0c7724a046883dd75f24ec73464dd833c0cb3b8e1ab9f1de05c255648b13c685", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" } },
  • サーバー側、クライアント側双方のコンテナ内のターミナルで互いのIPへpingが通ることを確認済

補足情報(FW/ツールのバージョンなど)

内容(バージョンなど)
ハードウェアーDell Precision 3520 (ノートPC)
OSUbuntu 18.04.4 LTS
Dockerversion 19.03.7
socketsversion 1.0.0
yodel👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

実験もせずに回答しますがご了承ください。

サーバプロセスが11113で待ち受けているのに、コンテナ外からの11113のアクセスを11114に転送しているのが間違いかと。あとやりたいことを見る限り、クライアント側のdockerがポート転送する必要はないのではないかと思います。

  • サーバー側の「docker run」
$ docker run -it -v $(pwd)/:/root/ubuntu_socket \ -w /root/ubuntu_socket/socket_test -p 11113:11113 ubuntu:Sock
  • クライアント側の「docker run」
$ docker run -it -v $(pwd)/:/root/ubuntu_socket \ -w /root/ubuntu_socket/socket_test ubuntu:Sock

これで動かないですかね?

投稿2020/03/30 07:01

masaya_ohashi

総合スコア9206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

xsteviax

2020/03/30 07:24

回答ありがとうございます。 おっしゃるとおりの「docker run」で立ち上げてもう一度プログラムを実行しましたが、 残念ながら、クライアント側で同じエラーが発生しました。
masaya_ohashi

2020/03/30 07:26

そもそも172.18.0.2というのはちゃんとサーバ側のIPなのでしょうか?
masaya_ohashi

2020/03/30 07:27

あれ?よく見たらそもそもclient側のserver指定が172.18.0.2になってない
xsteviax

2020/03/30 08:37 編集

すみません、エラー内容をコピー&ペーストしたときに、試行錯誤したものを載せてしまっていました。 もう一度「docker run」し直して、サーバ側コンテナのInspectを確認したところ --- サーバー側コンテナのInspectの一部 --- "IPAddress": "172.17.0.2" "PortBindings": { "11113/tcp": [ { "HostIp": "", "HostPort": "11113" } ] }, となっており、設定に問題ないかと思われます。 この状態で同じように実行し、また同じエラーとなりました。 また、client側のpythonファイル中のIP設定を「172.17.0.3」(client側のIP)としたところ、クライアントのプログラムが停止しました。(ターミナルが帰ってこない状態) 改めてIPを確認したところ、「172.18.0.2」ではなく「172.17.0.2」でした。 混乱を避けるため、本文の内容を改めて実行した内容に修正いたします。
masaya_ohashi

2020/03/30 08:44

https://knowledge.sakura.ad.jp/16082/ そもそもですがDocker同士の通信はIPでの指定ではなくコンテナ名でホストが通るようにするのが一般的なようですが、そもそもsocketに限らずこのIPでクライアント側からサーバ側にアクセスできることは確認済みですか?
xsteviax

2020/03/30 09:05 編集

サーバー側、クライアント側双方のターミナルで互いのIPへpingが通ることだけ確認しています。 他のやり方を調べていただき、ありがとうございます。 また、少し試してみたいと思います。
xsteviax

2020/03/31 05:56

自動で作成される「bridge」の他に「test-network」を作成し、netcatで通信してみました。 「bridge」ではnetcat通信できなかったのが、「test-network」では通信できるようになりました。 しかし、「test-network」のIPアドレス(サーバー側IP : 172.0.18.2)で、公式のコードを実行したところ、まだクライアント側で同じエラーが発生しました。 あと、一般的な方法として「コンテナ名でホストが通るようにする」とはどのような方法でしょうか?
masaya_ohashi

2020/03/31 08:11

クライアント側のコードで指定しているpoll_serverの引数を server=('server_container', 11113) にしてみてください。bridgeで同じネットワーク上にいるコンテナ同士はコンテナ名でDNS解決が行われる、というのが私の理解ですがあっているか検証してないのでわかりません。
xsteviax

2020/03/31 08:32

同じエラーが出てしまいました。 client.poll_server("Hello world", server=('server_container', 11113)) OSError: [Errno 22] Invalid argument ただ、コンテナ名で指定できるというのは間違っていなさそうでした。 ↓存在しないコンテナ名を指定 client.poll_server("Hello world", server=('server_contair', 11113)) socket.gaierror: [Errno -2] Name or service not known
bsdfan

2020/04/02 02:42

"sockets" というライブラリがおかしいんじゃないかと思います。 ソースを見ると、クライアントのソケットが"127.0.0.1"にbindされています(普通はそんなことしない)。なので、このライブラリでは127.0.0.1以外のサーバーとは通信できないです。 python標準のsocketを使って試してみてはどうでしょう。(検索すればいくつか出てきます) あと、サーバー側のlistenアドレスは '' (空文字)か、"0.0.0.0" にしたほうがいいです。(ANYアドレス)
xsteviax

2020/04/02 09:41 編集

回答ありがとうございます、これは標準ものではなかったのですね。 たしかに、もともとのubuntuのDockerイメージに、予めsocketがインストールされていたので、 それを使って少し試してみようと思います。
guest

0

自己解決

標準のsocketライブラリを使っている記事を参考に、pythonファイルを書き直したところ、
問題なく通信することができました。
Pythonでソケット通信を行う方法【初心者向け】
回答していただきました方々ありがとうございました。

  • サーバー側コンテナのpythonファイル(socket_Server.py)

python

1import socket 2 3PORT = 11113 4BUFFER_SIZE = 1024 5 6with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: 7 s.bind(('0.0.0.0', PORT)) 8 s.listen() 9 while True: 10 (connection, client) = s.accept() 11 try: 12 print('Client connected', client) 13 data = connection.recv(BUFFER_SIZE) 14 connection.send(data.upper()) 15 finally: 16 connection.close()
  • クライアント側コンテナのpythonファイル(socket_Client.py)

python

1import socket 2 3PORT = 11113 4BUFFER_SIZE = 1024 5 6with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: 7 s.connect(('server_container', PORT)) 8 data = input('Please input > ') 9 s.send(data.encode()) 10 print(s.recv(BUFFER_SIZE).decode()) 11

投稿2020/04/03 00:41

xsteviax

総合スコア14

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問