Home > Software engineering >  Docker containers can't communicate between them when flask api is served with uwsgi
Docker containers can't communicate between them when flask api is served with uwsgi

Time:10-15

I have as example two microservices running in two docker containers created with flask and served with uwsgi to a nginx proxy. Docker-compose file it's looking something like this:

nginx:
  build: ...
  container_name: ...
  restart: always
  hostname: my-host
  ports:
    - "80:80"
  expose:
    - 80
  networks:
    - my-net

micro1:
  build: ...
  container_name: ...
  restart: always
  hostname: my-host
  expose:
    - 8080
  networks:
    - my-net

micro2:
  build: ...
  container_name: ...
  restart: always
  hostname: my-host
  expose:
    - 8081
  networks:
    - my-net

and my .ini file something like this

[uwsgi]
wsgi-file = micro1.py
callable = micro1_api
socket = :8080
...

Now my problem is that I can't communicate between them. If I try to make a normal request with requests as example, I get an error with following message on docker container log:

invalid request block size: (max 4096)...skip uwsgi

I've increased buffer-size, but then another error (I think...) appears on console:

uwsgi_proto_uwsgi_parser(): Success [proto/uwsgi.c line 40]

with a timeout when making request.

Can't switch protocol since nginx is configured as uwsgi_pass micro1_upstream and changing protocol to http, nginx won't serve my requests, but calling containers inside will work. Also tried to use sockets, but no luck.

In this case, how can I communicate between containers?

CodePudding user response:

uWSGI has a custom wire protocol that has some advantages over the traditional text-based HTTP/1 protocol. Your configuration and error messages indicate that the listener is expecting this protocol, and your Nginx configuration presumably has a matching uwsgi_pass directive. However, the Python requests module expects to speak ordinary HTTP, not this custom protocol.

That is: you're correctly making the connection between containers – you are not getting a DNS error or "connection refused", bits are flowing across the virtual wire – but the client is speaking HTTP and the server is expecting the uwsgi protocol. That mismatch leads to the errors you see on both sides.

uWSGI can also provide a normal HTTP server. You should be able to configure uWSGI to run both the native wire protocol and also standard HTTP:

[uwsgi]
wsgi-file = micro1.py
callable = micro1_api
uwsgi-socket = :8080
http-socket = :9090

The Nginx configuration can use uwsgi_pass micro1:8080, but standard HTTP clients like requests need to use the HTTP port, http://micro1:9090.

You do not need any changes in your Docker configuration to use this. The existing expose: blocks do essentially nothing and it's safe to remove them. (Similarly you should be able to delete hostname:, container_name:, and all of the networks: blocks in the file without actually affecting anything.)

  • Related