user2534685
user2534685

Reputation: 471

CORS failes when using Docker containers for frontend and backend

The following code is working great outside docker containers. Now I would like to add a container for the backend and another for the frondend. So I create two Dockerfiles (that are probably uninteresting) and the following docker-compose file. I change axios.get('http://127.0.0.1:5000/api/test') to axios.get('http://backend:80/api/test') in the vue component. I'm able to ping the backend container from the frontend container and I'm able to receive the api result via curl. But axios is not able to make this api request anymore. And in the firefox console I get the error:

Error: "Network Error"
Cross-Origin request blocked [...] Reason: CORS request did not succeed

But I'm able to run the backend outside docker at one computer in my network and the frontend at another. So Cross-Origin is no problem outside docker. What's the problem here? I have no idea.


docker-compose.yml

version: '2'
services:
    backend:
        build: ./backend
        container_name: backend
        ports:
          - "80:80"
        environment:
          - FLASK_APP=app/main.py
          - FLASK_DEBUG=1
          - 'RUN=flask run --host=0.0.0.0 --port=80'
        networks:
          - some-net

    frontend:
        build: ./frontend
        container_name: frontend
        ports:
          - "90:80"
        networks:
          - some-net

networks:
    some-net:
        driver: bridge

original code

backend in python

from flask import Flask, jsonify
from flask_cors import CORS

app = Flask(__name__)
CORS(app, resources=r'/api/*')

@app.route('/api/test')
def test():
    return jsonify({
        "foo": "bar"
    })

if __name__ == '__main__':
    app.run(debug=True)

frondend (only vue.js component)

<template>
<div class="hello">
    <h1>Message is: {{ msg }}</h1>
</div>
</template>

<script>
import axios from 'axios'

export default {
name: 'HelloWorld',
data () {
    return {
        msg: ''
    }
},
created () {
    axios.get('http://127.0.0.1:5000/api/test').then(response => {
        console.log(response.data)
        this.msg = response.data.foo
    }).catch(error => {
        console.log(error)
    })
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped></style>

Upvotes: 31

Views: 46335

Answers (2)

Taras Vaskiv
Taras Vaskiv

Reputation: 2401

You can use "links" inside docker-compose.yaml. So it will look similar to this:

xxxdjango:
    image: xxx_django:dev
    ports:
      - "8000:80"
xxx_ui:
    image: xxx_ui:dev
    volumes:
       - ./xxx_ui/src:/app/src
       - ./xxx_ui/public:/app/public
    ports:
      - "8080:8080"
    links:
      - xxxdjango

So after this, you can use for Vue js

devServer: {
   proxy: 'http://xxxdjango'
}

and

axios.get('/api/test')

Upvotes: -4

Neil Twist
Neil Twist

Reputation: 1159

It would seem that you are mistaking how to reference docker containers from outside all containers.

axios.get('http://127.0.0.1:5000/api/test')...

Should refer to where the docker container is listening. Inside a container, this would indeed be backend, but outside, i.e. in your web browser, it would be a reference to the host running the container, followed by the port. Since you've mounted it on port 80 on the host (and 90 for the frontend), you should update the get to :

axios.get('http://{hostname or ip}:80/api/test')

If it's all running on the same host, then you could use 127.0.0.1 or localhost for your testing.

Upvotes: 22

Related Questions