I have faced with the problem! Can’t get the response from browser or postman in my Docker/ReactPHP app.
This is my code:
docker-compose.yaml
version: '3.8'
services:
react_php_service2:
container_name: react_php_service2
build:
context: .
dockerfile: ./.docker/php/Dockerfile
ports:
- "8000:8000"
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ./reactphp:/app
Dockerfile
FROM php:8.0-alpine
COPY ./reactphp /app
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
COPY ./.docker/php/entrypoint.sh /entrypoint.sh
RUN ["chmod", "+x", "/entrypoint.sh"]
ENTRYPOINT /entrypoint.sh
CMD [ "php", "./app/server.php"]
entrypoint.sh
#!/bin/sh
cd app/
composer install
php server.php
server.php
require 'vendor/autoload.php';
use PsrHttpMessageServerRequestInterface;
$loop = ReactEventLoopLoop::get();
$server = new ReactHttpHttpServer(function (ServerRequestInterface $request) {
echo date('Y-m-d H:i:s') . ' ' . $request->getMethod() . ' ' . $request->getUri() . PHP_EOL;
//return ReactHttpMessageResponse::plaintext("Hello World!n");
return new ReactHttpMessageResponse(200, ['Content-Type' => 'text/plain'], 'Hello, World!');
});
$socket = new ReactSocketSocketServer('127.0.0.1:8000', [], $loop);
$server->listen($socket);
echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . "n";
$loop->run();
So in docker container it works fine:
Send request
Get response.
But it doesn’t work in the browser or Postman – anywhere outside container:
Browser result.
2
Answers
ReactPHP core developer here. You’re making the socket server listen on your local loop back interface (
127.0.0.1
), which normally is your local machine. However with Docker that becomes your local Docker container only. If you listen on all interfaces (0.0.0.0
) instead you can reach it with the port mapping in the compose file. Note that this not just applies to ReactPHP by also tools like Redis when they default to listening to127.0.0.1
.The EXPOSE instruction does not actually publish the port.
as written in the docs.Either you have to use
-p
argument with thedocker run
command or specify the ports that you have to expose in your docker compose file.Also make sure your application is listening to all interfaces (i.e. 0.0.0.0) and not just the loopback interface (i.e. 127.0.0.1).
Note: Refer to @WyriHaximus answer as it explains exactly whats happening.