I am trying to publish messages from a PHP (Laravel) application to a RabbitMQ queue, which is then consumed by a .NET application. All of this is hosted in a pair of Docker stacks (via docker-compose), named main and report and structured like so:-
mainstackphpPHP Application service
reportstackhandler.NET Application servicequeueRabbitMQ service
I can get the report_queue IP from either docker inspect or the RabbitMQ logs, and store it in my PHP app's .env and then php artisan config:cache. However, when I am attempting to connect from main_php to report_queue (using php-amqplib/php-amqplib) with...
new AMQPStreamConnection('10.0.2.25', 5672, 'report', 'obviouslynottherealpassword');
...it will always return the following error:-
stream_socket_client(): unable to connect to tcp://10.0.2.25:5672 (Connection timed out)
So it seems that it can't reach the queue service, yet from main_php I can both ping the queue IP and connect to 10.0.2.25:5672 via telnet just fine! Even when I add a retry mechanism, it will give the same error. Even if I destroy (rm) both stacks, re-deploy, update IP in .env and config:cache - Same issue!
All queue connections from the .NET service (sat on the same stack) work perfectly fine, but connection attempts from the PHP service don't even seem to touch RabbitMQ (nothing appears in the logs). The user/password are definitely correct, as they are copied from .NET.
I couldn't find anything that describes my issue in the php-amqplib issue tracker or elsewhere on SO. My connection code is more-or-less a straight copy from some of the most basic examples php-amqplib provide. Docker-wise, my understanding is that the networks setup in my main and report docker-compose files should allow services within those networks to communicate. I have also tried explicitly adding networks: - default to the report_queue service, but got the exact same error.
Can anyone see where I'm going wrong? My understanding is that everything here should work, but it doesn't!
The following are the relevant bits of code, for reference.
docker-compose.main.yml:-
version: "3.9"
networks:
default:
attachable: true
driver: overlay
services:
php:
hostname: php
working_dir: /var/www/html
volumes:
- ~/code/publisher:/var/www/html:cached
image: publisher:latest # (custom docker image)
env_file:
- localhost.env
The main stack is brought up with docker stack deploy -c docker-compose.main.yml --with-registry-auth local --prune
docker-compose.report.yml:-
version: "3.9"
networks:
default:
external: true
name: main_default
services:
handler:
hostname: handler
image: handler:latest # (custom docker image)
restart: unless-stopped
ports:
- "5000:80"
- "5001:443"
env_file: ./dotenvs/handler.env
extra_hosts:
- host.docker.internal:host-gateway
queue:
image: rabbitmq:3-alpine
ports:
- "5672:5672"
volumes:
- ./config/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf
dotenvs/handler.env:-
RABBITMQ_HOST=report_queue
RABBITMQ_USER=report
RABBITMQ_PASSWORD=obviouslynottherealpassword
config/rabbitmq.conf:-
default_user = report
default_pass = obviouslynottherealpassword
The report stack is brought up with docker stack deploy -c docker-compose.report.yml report
The code that attempts connection from main_php (extracted from a Laravel 7 command) is:-
$request = [
'report_name': 'all-the-data',
'date': '2022-01-01'
];
$amqpConnection = new AMQPStreamConnection(env('REPORT_QUEUE_HOST'), 5672, 'report', 'obviouslynottherealpassword');
// doesn't reach anything past this point due to error
// ...
And the .env PHP is consuming:-
REPORT_QUEUE_HOST=10.0.2.25
And the complete resulting error:-
[2022-09-16 10:13:52] local.ERROR: stream_socket_client(): unable to connect to tcp://10.0.2.25:5672 (Connection timed out)
[object] (PhpAmqpLib\\Exception\\AMQPIOException(code: 0): stream_socket_client(): unable to connect to tcp://10.0.2.25:5672 (Connection timed out) at /home/me/code/publisher/vendor/php-amqplib/php-amqplib/PhpAmqpLib/Wire/IO/StreamIO.php:108)
[stacktrace]
#0 /home/me/code/publisher/vendor/php-amqplib/php-amqplib/PhpAmqpLib/Connection/AbstractConnection.php(253): PhpAmqpLib\\Wire\\IO\\StreamIO->connect()
#1 /home/me/code/publisher/vendor/php-amqplib/php-amqplib/PhpAmqpLib/Connection/AbstractConnection.php(236): PhpAmqpLib\\Connection\\AbstractConnection->connect()
...
#16 /home/me/code/publisher/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(129): Illuminate\\Console\\Application->run()
#17 /home/me/code/publisher/artisan(35): Illuminate\\Foundation\\Console\\Kernel->handle()
#18 {main}
PhpAmqpLib\Exception\AMQPIOException
stream_socket_client(): unable to connect to tcp://10.0.2.25:5672 (Connection timed out)
Also, in case it's relevant: I'm using IP because using report_queue by hostname from main_php results in Temporary failure in name resolution instead of Connection timed out. So I chose to keep things simple and just use the IP.