0

I am currently writing a small fullstack application using Docker compose, vue, and python. All my containers work in isolation, but I can't seem to get my containers to communicate using host names... Here's my code:

Docker Compose

version: "3.8"
services:
  web:
    build: ./TranscriptionFrontend
    ports:
     - 4998:4998
  api:
    build: ./TranscriptionAPI

Javascript Frontend Request

fetch("http://api:4999/transcribe", {
        method:'POST',
        headers: {'Content-Type': 'application/json'}, 
        body: JSON.stringify(data)
      }).then(res => {
        res.json().then((json_obj) =>{
          this.transcription_result = json_obj['whisper-response']
        })
      }).catch(e => {
        this.transcription_result = "Error communicating with api: " + e;
      })

I know my API service works because originally I was just mapping it to a port on my localhost, but that got messy and I want to keep access to it within my docker container. In all cases the host name could not be resolved from my JS request. Also, curl-ing from my containers using host names does provide a response i.e. docker-compose exec web curl api or vice versa. I'm a beginner to java script and docker so apologies if I'm missing something basic.

What I've tried:

  • XML Http Request
  • Making call without using http://
Insomnes
  • 1
  • 4

2 Answers2

1

Host names for docker container communication are only possible if you define a user defined bridge network. Here's an example:

(On your docker-compose.yml)

...
networks:
  my_network:
    driver: bridge

Here's a link to the Docker docs just in case. Let me know if this helped!

saguirrews
  • 280
  • 1
  • 7
  • From what I've understood, isn't that created automatically as a build condition for my docker compose? When I run `docker network ls`, I see a bridge network titled `transcriptionapp_default` with my web and api containers attached according to docker inspect. – Insomnes Oct 26 '22 at 19:35
  • A bridge network is created by default, but it won't allow you to reference containers by name. In order to do that, it needs to be user defined. – saguirrews Oct 26 '22 at 19:47
0

Your docker service name won't reflect in the url unless you configure some virtual hosts that points to its image on localhost. You can look into something like How to change the URL from "localhost" to something else, on a local system using wampserver? if that is what you really want to do but I feel it might be defeating the point.

My approach would be to pass the API url as environment variable to your front-end service directly in the Docker compose file. Something like:

services:
  web:
    build: ./TranscriptionFrontend
    ports:
     - 4998:4998
    environment:
      API_URL: http://127.0.0.1:4999
  api:
    build: ./TranscriptionAPI
    ports:
     - 4999:4999

and then inject the env variable into your Javascript app build. For example assuming you're using any Node.js stack for compiling your JS you could have it as a process.env property and then do:

fetch(`${process.env.API_URL}/transcribe`, { ... })
Ninowis
  • 379
  • 1
  • 8
  • Okay, that's what I was doing originally. I just wanted to dumb it down to one exposed port per application because I have many containers that I don't want clutter my ports. In addition, I'm not sure how it would effect scaling... What would you recommend? – Insomnes Oct 26 '22 at 19:44
  • Well this way you still have only one exposed port per application/service. It might be a lot of ports locally, but when it comes to deploying to production each service can (should?) have its own environment (server or storage depending on the nature of the service/application) In terms of scalability, I believe independent micro-services are key, so much easier to maintain and debug should something go wrong in one of them. – Ninowis Oct 27 '22 at 10:29