# Server- & Client-Side Networking with Multiple Docker Compose Files

A [few helpful articles](https://www.google.com/search?q=cross+docker-compose+networking) have been written that discuss getting services from different Docker Compose files to communicate with one another during local development.

These solutions leverage Docker networking features, which makes sense since most of the use cases involve server-side network requests.

If the service is purely frontend, this isn't an issue at all. The browser would just use the local host machine's network to perform the requests. No need to go through Docker networking.

But NextJS makes things quite complicated. It is able to perform both server-side (SSR & SSG) and client-side (CSR) requests. It means that if we follow the articles above, server-side will work well, but client-side requests would break.

Allow me to demonstrate.

Let's say we have a NextJS app named `next-client` in `frontend.docker-compose.yml`. And we provide it with an environment variable `API_URL=http://path-to-api` for backend requests.

```yaml
# frontend.docker-compose.yml
services:
  next-client:
    environment:
      API_URL: http://path-to-api
```

We also have an API service named `api-gateway` exposing port `3000` in `backend.docker-compose.yml`. That service will be available on the local machine network via http://localhost:3000. `next-client` service's client-side (browser) requests will be totally fine with this (`API_URL=http://localhost:3000`).

```yaml
# backend.docker-compose.yml
services:
  api-gateway:
    expose:
      - 3000
```

But due to reasons already mentioned by the articles above, all server-side `next-client` requests will break.

Now, if we follow the articles, we would need to set `API_URL=http://api-gateway:3000` in `next-client`. Great, server-side requests are working now:

```yaml
# backend.docker-compose.yml
services:
  api-gateway:
    expose:
      - 3000
    network:
      - backend-gateway

networks:
  - backend-gateway
```

```yaml
# frontend.docker-compose.yml
services:
  next-client:
    environment:
      API_URL: http://api-gateway:3000
    networks:
        - backend-project_api-gateway

networks:
  backend-project_api-gateway:
    external: true
```

But wait, the client-side requests are now failing! That totally makes sense since the local host machine doesn't recognize `http://api-gateway`.

After fiddling around for hours, I found that the answer was actually so simple, add `api-gateway` as a hostname alias inside your machine's hosts file. Here's how to do it in Linux:

```plaintext
127.0.0.1       localhost api-gateway
```

Voila! NextJS is happy!

What this does is to allow the host machine to route `http://api-gateway` requests to all localhost network handlers, one of which is our Docker `api-gateway` service! For client-side requests, `http://api-gateway:3000` is transformed to `http://127.0.0.1:3000` (localhost), and since `api-gateway` is exposed at port `3000`, it accepts the request.

NextJS server-side requests, meanwhile, are still exclusively handled from within Docker's Network. The local machine network are not aware of them.

Effectively, in NextJS point of view, both server- & client-side requests go through the same network. But with some juggling, the reality is they are handled by separate networks, Docker and local machine networks, respectively. But NextJS doesn't need to know about that anymore, does it? 😎
