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.)