Search code examples
javascriptdockerdocker-composeyaml

Getting two docker dev environments to communicate with each other


So I have two docker dev environments running that I want to test communications with each other.

The first dev environment is a mgmt service that has an express server with various API endpoints. In that same repo, I have a Next js app with some simple buttons that you can press to connect to the other service. The purpose of this app is that it will have a UI that client can choose their service options.

The second dev environment is an API service. The purpose of this service is to accept inbound requests and transform the data into a usable means, before sending it back to the requestor. That functionality isn't built but I figure I'll give you some context on what this service would do.

My trouble is sending axios requests with my mgmt service. I keep getting a 404 for my endpoints and I don't get my console logs so I'm unsure of what my doing wrong.

  1. I'm using a proxy endpoint in order to later call the internal network bridge between the containers. I do this because the code has to execute on the server environment.
  2. I have a button that calls the proxy endpoint. onClick of that button I get past the "hit1" log and it actually does request the api-service/test but I get stuck on a 500 server error.

I come from a mainly serverless background so I don't deal with Docker often. I believe something is wrong with my mgmt service because it can not even reach its own endpoints.

mgmt-service files:

compose-dev.yaml

networks:
  ocd-network:
    driver: bridge
    
services:
  app:
    entrypoint:
      - sleep
      - infinity
    image: docker/dev-environments-javascript:stable-1
    networks:
      - ocd-network
    init: true
    volumes:
      - type: bind
        source: /var/run/docker.sock
        target: /var/run/docker.sock

app.cjs

const express = require("express");
const next = require("next");
const axios = require('axios');

const port = 80;
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  const server = express();

  server.get('/server-connection', (req, res) => res.send('We are good to go!'));

  // Add a new proxy route to fetch data from ocd-api
  server.get("/api/proxy", async (req, res) => {
    console.log("hit1")
    try {
      const response = await axios.get("http://ocd-api-service-app-1:3001/test");
      res.json(response.data);
    } catch (error) {
      console.error("Error fetching from ocd-api:", error);
      res.status(500).json({ error: "An error occurred", error });
    }
  });

  // Let Next.js handle all other routes
  server.all("*", (req, res) => {
    return handle(req, res);
  });

  server.listen(port, (err) => {
    if (err) throw err;
    console.log(`> Ready on http://localhost:${port}`);
  });
});

api-service

compose-dev.yaml

networks:
  ocd-network:
    driver: bridge
    
services:
  app:
    entrypoint:
      - sleep
      - infinity
    image: docker/dev-environments-javascript:stable-1
    networks:
      - ocd-network
    init: true
    volumes:
      - type: bind
        source: /var/run/docker.sock
        target: /var/run/docker.sock

index.ts

import express, { Express, Request, Response } from 'express';
import dotenv from 'dotenv';
import cors from "cors"

dotenv.config();

const app: Express = express();
const port = process.env.PORT;

app.use(cors());

app.get('/', (req: Request, res: Response) => {
  res.status(200)
  res.send("ok")
});

app.get("/test", (req, res) => {
  res.status(200);
  res.send({
    message: "Winner, winner chicken dinner",
    time: new Date(),
  });
});

app.listen(port, () => {
  console.log(`Server is running at http://localhost:${port}`);
})

error: cause: Error: getaddrinfo ENOTFOUND ocd-api-service-app-1 at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:109:26) at GetAddrInfoReqWrap.callbackTrampoline (node:internal/async_hooks:130:17) { errno: -3008, code: 'ENOTFOUND', syscall: 'getaddrinfo', hostname: 'ocd-api-service-app-1' }

docker ps: containerId imageName command:"sleep infinity" ... ocd-api-service-app-1 containerId imageName command:"sleep infinity" ... ocd-mgmt-service-app-1


Solution

  • To reach the API you have to load such network in your mgmt-service compose-dev.yml and link it to your service in the following way:

    
    networks:
      ocd:
        external: true
        name: ocd-network
        
    services:
      app:
        networks:
        - ocd
        - default
    ...
    

    and in your app do:

          const response = await axios.get("http://ocd_app:3001/test");
    

    Update

    Realized that both services are named as app, it may conflict when linking networks. A solution would be to name the api itself as api and update the axios request as follow:

          const response = await axios.get("http://api:3001/test");