你能否使用Python套接字进行Docker容器通信?

5
在docker网络中,我正在尝试使用Python套接字(发送数据包)在两个容器之间通信。ping可以工作,但Python套接字库无法工作。
错误代码: 'line 6: conn, addr = sock.connect(('172.168.1.2', 4000)) TypeError: 'NoneType' object is not iterable'
首先在容器1中运行python3 receive.py。然后在容器2中运行python3 send.py。容器1打印“accepted”,然后不再输出任何内容。容器2则出现了上述错误。
此网络是一个具有自己子网和默认网关的用户定义网络。当我使用它来连接我的树莓派时,相同的代码不会发生错误,但在容器通信时会产生错误。
所有的代码:
容器1:
import socket

def receive():
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(("", 4000))
        s.listen(2)
        conn, addr = s.accept()
        print("accepted")
        print(bytes.decode(conn.recv(1024)))

容器 2:

import socket

def send():
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        command = "bridge test!"
        conn, addr = sock.connect(('172.168.1.2', 4000))
        conn.sendall(command)

设置网络:

docker network create --subnet 172.168.1.0/24 testNetwork
docker network connect testNetwork container1
docker network connect testNetwork container2

我从docker inspect中获取了容器的IP地址(同时ping它们也可以),请帮忙!谢谢!


加上对它们的ping测试有效吗?从哪里ping什么? - 0xcaff
我可以从主机和容器内部相互ping通。 - Joe N
2个回答

4
你有几个问题。
  1. socket.connect doesn't return anything. It returns None. You think it returns a tuple of conn, addr. Python tries to deconstruct whatever is returned into a tuple by iterating over it and you get the error:

    TypeError: 'NoneType' object is not iterable
    
  2. socket.sendall accepts bytes not a str. Convert by

    sock.sendall(command.encode())
    
这是修复后的 send.py 文件:
import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
command = "bridge test!"
x, y = sock.connect(('172.168.1.2', 4000))
sock.sendall(command.encode())

2
你可以尝试使用Python的Docker API。 https://github.com/docker/docker-py.git 以下是一个示例。
#!/usr/bin/python3

import docker
import requests

def main():

  # Connect to the default unix socket (/var/run/docker.sock)
  client = docker.from_env()

  #Pull the nginx:alpine image
  client.images.pull('nginx:alpine')

  #Define some test parameters, our first HTTP port and the number of containers
  portstart = 10000
  count = 1000

  #Create and start 'count' number of containers. Map container port 80 to an external port.
  for a in range(1,count+1):
    container = client.containers.create('nginx:alpine',ports={'80/tcp':portstart+a})
    container.start()
    print('Created container number {} name: {}'.format(a,container.name))

  #Get a list of all the running containers (best you don't run this script on a system which has existing containers running)
  #Iterate through the list, pick out the remote port, and perform a GET request to it to check nginx is online. If the status code is 200, we must be successful!
  container_list = client.containers.list()
  count = 0
  for container in container_list:
    port = container.attrs['HostConfig']['PortBindings']['80/tcp'][0]['HostPort']
    r = requests.get('http://127.0.0.1:{}'.format(port))
    if(r.status_code == 200):
      print('Container {} is alive and working on port {}!'.format(container.name,port))
      count += 1
    else:
      print('Container {} is dead :( Code: {}'.format(container.name,r.status_code))

  print('Summary: Online Containers: {} Offline Containers: {}'.format(count,len(container_list)-count))
  print('Removing containers...')

  #Let's clean up and put our toys back in the toybox.
  for container in container_list:
    container.stop()
    container.remove()

if __name__ == "__main__":
    main()

有趣,我会去看看。谢谢。 - Joe N
4
这是用于通过套接字与Docker守护程序进行交互。我认为OP正在尝试在容器之间发送数据包。 - 0xcaff
是的,这对我正在做的另一件事情确实有帮助,但它并没有回答我在这里发布的问题。 - Joe N

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接