title: Guzzle HTTP from Docker to NodeJS in Host
body: <p>folks.</p>
  
  <p>I have a servive running on my host machine. It is a NodeJS app with Express. It works fine at "localhost:3000".</p>
  
  <p>Then, in a separate project, I have a Laravel App running fine inside Docker, and I access it at "<a href="http://localhost" rel="nofollow noreferrer">http://localhost</a>".</p>
  
  <p>Now, my Laravel app needs to call the NodeJS app. I saw in Docker documentation I should use "host.docker.internal", since it will resolve to my host machine.</p>
  
  <p>The <code>this-&gt;http</code> is a <code>Guzzle\Client</code> instance. </p>
  
  <p>In my PHP code I have this:</p>
  
  <pre><code>$response = $this-&gt;http-&gt;request('POST', env($store-&gt;remote), [
      'form_params' =&gt; [
          'login' =&gt; $customer-&gt;login,
          'password' =&gt; $customer-&gt;password,
      ]);
  </code></pre>
  
  <p>If I call the NodeJS app from Postman it works fine. But calling from that PHP I got this error:</p>
  
  <pre><code>"message": "Client error: `POST http://host.docker.internal:3000` resulted in a `404 Not Found` response:\n&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n&lt;meta charset=\"utf-8\"&gt;\n&lt;title&gt;Error&lt;/title&gt;\n&lt;/head&gt;\n&lt;body&gt;\n&lt;pre&gt;Cannot POST /&lt;/p (truncated...)\n",
      "exception": "GuzzleHttp\\Exception\\ClientException",
      "file": "/var/www/html/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php",
      "line": 113,
  </code></pre>
  
  <p>Does anyone have any clue how I can call my node app from PHP in Docker?</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>I was thinking if I should not open the port 80 and bind it to port 3000 in my PHP instance (since the request is running in php docker image). I put in my Docker file these ports attribute:</p>
  
  <pre><code>php:
      build: ./docker
      volumes:
        - .:/var/www/html
        - ./.env:/var/www/html/.env
        - ./docker/config/php.ini:/usr/local/etc/php/php.ini
        - ./docker/config/php-fpm.conf:/usr/local/etc/php/php-fpm.conf
        - ./docker/config/xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
      links:
        - mysql
      ports:
        - "3000:80"
  </code></pre>
  
  <p>So, port 80 in my PHP instance would bind to my OSX port 3000. But Docker complains port 3000 is in use: </p>
  
  <blockquote>
    <p>Cannot start service php: b'driver failed programming external connectivity on endpoint project_php_1 (241090....): Error starting userland proxy: Bind for 0.0.0.0:3000 failed: port is already allocated'</p>
  </blockquote>
  
  <p>Yes! In fact it is allocated. It is allocated by my NodeJS app, that is where I want to go. It looks like I do not know very well how ports and DNS works inside Docker for Mac.</p>
  
  <p>Any help is very appreciated.</p>
  
  <p><strong>SOLVED</strong></p>
  
  <p>Hey, guys. I figured it out. I turned off Docker container, point a regular Apache to my Laravel project and I got what was happening: CORS.</p>
  
  <p>I already had <code>cors</code> in my Express app, but after configure it better, it worked!</p>
  
  <p>Here it is, in case anyone stumbled here and needs it:</p>
  
  <p>1) Add <a href="https://github.com/expressjs/cors" rel="nofollow noreferrer">cors</a> to your Express (if you haven't yet)</p>
  
  <p>2) Configure cors to your domains. For now, I will keep it open, but, for production APPS, please, take care and control wisely who can query your app:</p>
  
  <pre><code>// Express app:
  app.use(
  cors({
      "origin": "*",
      "methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
      "preflightContinue": false,
      "optionsSuccessStatus": 204
    })
  );
  app.options('*', cors());
  </code></pre>
  
  <p>3) Use the <code>host.docker.internal</code> address (in my case, <code>host.docker.internal:3000</code> , since my app is running on that port) from PHP to get to your Express App in OSX host machine. In my case, it will be a different domain/IP when it gets to production.</p>
  
  <p>4) Just use <code>Guzzle\Client</code> to make your http call:</p>
  
  <pre><code>$response = $this-&gt;http-&gt;request('POST', env($store-&gt;remote) . '/store-api/customers/login', [
                  'json' =&gt; [
                      "login" =&gt; $customer-&gt;login,
                      "password" =&gt; encrypt($customer-&gt;password),
                  ]
              ]);
  </code></pre>
  
  <p>A important point to note: Express waits for <code>json</code> (in my app, at least), so do NOT use "form_data", use "json" option to POST requests:</p>
  
  <p>At least, it was NOT a duplication of the other answers, as marked by @Phil, because those answers points to the same solution I have already mentioned, use the 'host.docker.internal' address.</p>