chrysn / aiocoap

The Python CoAP library
Other
267 stars 120 forks source link

Network error: [Errno 111] - Cannot interact with CoAP server outside a Docker Container #349

Open J0hn3ch opened 6 months ago

J0hn3ch commented 6 months ago

Hi everyone,

I'm trying to build a CoAP server project, using aiocoap and Docker containers.

I'm using the Docker Compose file to manage containers in the project and a Dockerfile to build the images for the container. In this case I use a Docker image of Ubuntu to build the custom image with CoAP Server (installing python, requirements and running server.py from the aiocoap tutorial).

compose.yml & Dockerfile

# CoAP Server Ubuntu 20.04                         ||  # Dockerfile
services:                                           |  FROM ubuntu:20.04 as base 
  coap_server-2:                                    |  RUN apt-get update && apt-get install -y python3
    container_name: ubuntu-coap-server              |  RUN python -m pip install --no-cache-dir -r requirements.txt
    build:                                          |  EXPOSE 5683/udp
      context: coap-server-2                        |  EXPOSE 80/udp
      no_cache: false                               |  CMD python3 server.py
    volumes:
      - ./coap-server-2:/app/
    restart: always
    network_mode: host
    ports:
      - 80:80/udp
      - 5683:5683/udp

Testing the server with aiocoap-client

The problem: Request outside the container, with WSL Ubuntu

$ aiocoap-client -m GET coap://127.0.0.1:5683/.well-known/core
Network error: [Errno 111] received through errqueue

In my case, I need to interact outside the container, because all the compose file will be executed in a Raspberry, so I need to send coap request from a Client (e.g. ESP32) to a CoAP Server (Raspberry Pi).

How can I solve this issue?

Working example: Request inside the container After open the bash of the container with the command docker exec -it ubuntu-coap-server bash

coapuser@docker-desktop:/app$ aiocoap-client -m GET coap://127.0.0.1:5683/.well-known/core
Response arrived from different address; base URI is coap://127.0.0.1/.well-known/core
</.well-known/core>;ct="40",</>,</time>;obs,</other/block>,</other/separate>;title="A large resource",</whoami>,<https://christian.amsuess.com/tools/aiocoap/#version-0.4.7>;rel="impl-info" 

aiocoap.cli.defaults: output


Python version: 3.8.10 (default, Nov 22 2023, 10:22:35)
[GCC 9.4.0]
aiocoap version: 0.4.7
Modules missing for subsystems:
    dtls: missing DTLSSocket
    oscore: missing cbor2, cryptography, filelock, ge25519
    linkheader: everything there
    prettyprint: missing cbor2, termcolor, pygments
Python platform: linux
Default server transports:  tcpserver:tcpclient:tlsserver:tlsclient:udp6
Selected server transports: tcpserver:tcpclient:tlsserver:tlsclient:udp6
Default client transports:  tcpclient:tlsclient:udp6
Selected client transports: tcpclient:tlsclient:udp6
SO_REUSEPORT available (default, selected): True, True```
chrysn commented 6 months ago

I have little knowledge of what those WSL containers do, but can you confirm that the loopback address is even supposed to work across container boundaries?

You can test that easily by running sudo apt install socat on the Linux side, then running sudo socat - tcp-listen:80, and then pointing your web browser at http://127.0.0.1/ -- if forwarding works, you'll see the HTTP request in the Linux machine (and get an error in the browser); if not, socat will report nothing (and you'll get a different error).

J0hn3ch commented 6 months ago

Yes,

  1. I enter inside the container of CoAP Server with this command: docker exec -it -u root ubuntu-coap-server bash

  2. Next, as you write, I have installed inside the container, the tool socat with: apt install socat and running socat - tcp-listen:80.

  3. From WSL in the Docker Host (so my machine) I run a curl http://127.0.0.1 and this is the result:

    CoAP-Server-Container# socat - tcp-listen:80   |  Docker-Host-WSL$ curl -X GET http://127.0.0.1/
    GET / HTTP/1.1                                 |  curl: (52) Empty reply from server     
    Host: 127.0.0.1
    User-Agent: curl/7.81.0
    Accept: */*