In a docker network I am trying to communicate between two containers using python sockets (to send packets). Pinging works but python sockets library does not work.
The error:
line 6: conn, addr = sock.connect(('172.168.1.2', 4000))
TypeError: 'NoneType' object is not iterable
First python3 receive.py is run in container1. Then python3 send.py is run in container 2. Container 1 prints "accepted" and then nothing else. Container 2 errors as mentioned above.
This network is a user-defined network with it's own subnet and default gateway. This error does not occur with the same exact code when I use it to connect to my raspberry pi, but it errors with container communication.
All of the code:
container1:
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)))
container 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)
To setup the network:
docker network create --subnet 172.168.1.0/24 testNetwork
docker network connect testNetwork container1
docker network connect testNetwork container2
I got the IP addresses of the containers from docker inspect (plus pinging them works) Please help! Thanks!
You have a couple of issues.
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
socket.sendall accepts bytes not a str. Convert by
sock.sendall(command.encode())
Here's the fixed 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())
                        You might want to try the docker api for python. https://github.com/docker/docker-py.git
Here is an example.
#!/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()
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With