I have 2 simple node.js apps
app1/index.js
import fetch from 'node-fetch';
import express from 'express'
const app = express()
const port = 3000
app.get('/', (req, res) => {
fetch("http://localhost:3002/", {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ "msg": "hello app2" })
})
.then(resp => resp.json())
.then((resp) => {
res.json(resp)
})
})
app.listen(port, () => {
console.log(`app1 listening on port ${port}`)
})
app2/index.js
const express = require('express')
const app = express()
const port = 3002
app.use(express.json());
app.post('/', (req, res) => {
res.json({ "msg": "hello to you too" })
})
app.listen(port, () => {
console.log(`app2 listening on port ${port}`)
})
when I go to localhost:3000 on my browser the app1
retrieves data from app2
and displays it and this works fine locally. The issue arises when I try to dockerize them
Dockerfile(s) for both
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm i
EXPOSE 3000
# EXPOSE 3002 for app2
CMD ["node", "index.js"]
docker-compose.yaml
services:
app1:
build: ./app1
container_name: app1_c
ports:
- "3000:3000"
extra_hosts:
- "host.docker.internal:host-gateway"
app2:
build: ./app2
container_name: app2_c
ports:
- "3002:3002"
extra_hosts:
- "host.docker.internal:host-gateway"
This doesn’t work & the app1
can’t seem to access app2
‘s localhost:3002
I’m guessing because app1
is sending the fetch request to it’s own container’s localhost:30002 instead of the app2’s localhost but I thought "host.docker.internal:host-gateway"
fixes that issue and allows cross container communication?
Could someone please help me understand?
System Info
Ubuntu 22.04.3 LTS
Docker Engine v24.0.6
Edit: Changed names client -> app1
& server -> app2
to avoid confusion
2
Answers
Based on Phil's comment I've used environment variables and changed the
app1
to as such:.env
file contains localhost for local development:and in the docker-compose.yaml
environment
for production use:This seems to work, but I'm leaving the question open for accepting another answer incase there's a better way to do this in general
If you insist on having
app1
andapp2
to connect vialocalhost
, you could start a container that runs processes for both apps, instead of using Docker Compose.In the root folder, place this
Dockerfile
and this
wrapper_script.sh
And make sure to expose 2 ports during
docker run