14

I'm building a simple Website with login, and my vue-frontend needs to retrieve user data from my nodejs-backend which connects to a sql database. I decided to use docker-compose for this, and as I understand, docker-compose sets up a network automatically for the services that are mentioned in my docker-compose.yml.

What doesn't seem to work, is the way I address the backend in my code. I suspect that it might be because of the way I use axios to send a request to my backend.

I have inspected the default docker-network and was able to ping from my frontend to my backend using the dns names I found in the network-configuration. But using the same names inside my code didn't work.

What does work, is mapping a host port to my exposed api port and using http://localhost:5000 as address, but this defeats the purpose of a docker network.

my docker-compose.yml:

version: '3.3'

services:
    vue-frontend:
        image: flowmotion/vue-js-frontend
        ports:
            - 8070:80
        depends_on:
            - db-user-api

    db-user-api:
        image: flowmotion/user-db-api
        environment:
            - PORT=5000
        ports:
            - 5000:5000 #only needed if docker network connection can't be established 

the Vue-fontend files in question:

Login.vue

methods: {
    async login() {
      try {
        const response = await authenticationService.login({
          email: this.email,
          password: this.password
        });
        this.$store.dispatch("setToken", response.data.token);
        this.$store.dispatch("setUser", response.data.user);
        this.$router.push({ path: "/" });
      } catch (error) {
        this.showError = true;
        this.error = error.response.data.error;
      }
    }
  }
};
</script>

authenticationService.js

import api from "@/services/api";

export default {
  login(credentials) {
    return api().post("login", credentials);
  }
};

api.js

import axios from 'axios';
import config from '../config/config';
export default () => {
    return axios.create({
        baseURL: config.userBackendServer
    });
};

config.js ()

module.exports = {
    userBackendServer: 'http://cl-dashboard_db-user-api_1:5000' //this doesn't seem to work
};

//using 'http://localhost:5000' works if ports are mapped to host machine.

expected result would be my backend doing a sql lookup.

actuel result is, instead of connecting to my backend my frontend gives me a 404 status and my backend is never reached

1 Answer 1

19

you are correct assuming containers in the docker network can talk to each other without opening any ports to the outer world.

point is- your vue app is not in any container- it is served from a container as a js script file to your browser, which is the one sending the requests to your node backend. since your browser is by any means not inside the docker network - you must use the outer port mapping (localhost:5000 in your case) to reach the backend.

let me know if you have any more questions about that.

20
  • ok, this makes sense. So for deployment, would I need to specify the serving ip address/URI with the port specified in my docker-compose.yml? like this: userBackendServer: 'URItoMyApp:5000'
    – Flowmotion
    Commented May 30, 2019 at 10:54
  • put it as an environment variable in your .env file, in the vue app root directory. for now its is going to be VUE_APP_API_ROOT=http://localhost:500/ and on production change it to your server hostname. your backend production container is supposed to be mapped to the host default ports (80 and 443) and therefore you wont need to specify any port number. Commented May 30, 2019 at 17:08
  • 1
    @hudac Correct, CORS headers shouldn't be used on production. The usual architecture puts a proxy server (say nginx) that serves the frontend file, and redirect /api/* requests to the backend server. example: cli.vuejs.org/guide/deployment.html#docker-nginx Commented Jan 12, 2021 at 12:27
  • 1
    ok, I found this example github.com/wkrzywiec/kanban-board/blob/master/kanban-ui/… - nginx reverse proxy which redirects internally the calls for /api/*. Thanks!
    – hudac
    Commented Jan 12, 2021 at 21:11
  • 1
    @Vivere In production you usually put proxy to achieve same domain name for the frontend and the backend (otherwise you face CORS) so you can eliminate the hostname from the requested URL and by default the browser will use the frontend domain name as the hostname (for example you send an AJAX to "/api/image1.png") without hostname. Commented May 5, 2021 at 8:04

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.