Frontend and API in different containers

I have 3 containers for each (Frontend, backend and MongoDB)

  1. Frontend, expose port: 0.0.0.0:80->80/tcp, 443/tcp
  2. API, expose ports: 80/tcp, 443/tcp, 43554/tcp, 0.0.0.0:3000->3000/tcp
  3. MongoDB, expose ports: 0.0.0.0:27017->27017/tcp

To run my API, I just link the MongoDB container

docker run -d -p 3000:3000 --name backend --link mongodb:mongodb backend

In my frontend app, every ajax call will do by /api/

So ...

Front-end (HTML/CSS/JS) make a request to /api/*** , and should redirect to container port :3000 so my API can respond.

How can I do that? both using same url myapp.com for front-end and myapp.com/api for backend.

Anthony Lapenna's photo

As Dong Nguyen stated, you'll probably need a reverse-proxy to map your API container to the myapp.com/api location. I'd recommend using Nginx, have a look at Frank Rousseau's answer below for an example with Nginx.

In addition to that, I wanted to recommend you a few things:

Using the --link option to link container is deprecated since Docker 1.9 and will probably be removed in future versions: docs.docker.com/engine/userguide/networking..

What you should do instead is to create your own Docker network and start your containers inside that network. Containers started inside a user-defined network will be able to communicate by using their container names.

Here is a small example:

$ docker network create myapp
$ docker run -d -p 27017:27017 --name mongodb mongo
$ docker run -d -p 3000:3000 --name backend myapp/backend
$ docker run -d -p 80:80 --name frontend myapp/frontend

Give a try to docker-compose

Compose is tool for defining and running multi-container Docker application. You'll be able to define what services (mongodb, backend, frontend) that make up your app in a single YAML file and manage it using a single command-line. It's pretty handy ! Have a look here for more information: docs.docker.com/compose/overview

Riderman de Sousa Barbosa's photo

Thanks Anthony Lapenna nice tips.

I replied the Dong Nguyen comment using nginx proxy and works.

And yes, now I use network and compose in my code :), thanks for the tips.

Dong Nguyen's photo

If so, link to API server should be "myapp.com:3000", right?

If you want to call to API server as a path - such as "myapp.com/api" - you may need an adapter for your front-end. It's a small script using Node.js or nginx configuration that will map and redirect every request to artual target (at port 3000).

For my opinion, the better approach is using sub domain. I often apply this method: map the domain "api.myapp.com" to port 3000 so that I can send AJAX requests to there. Why this is good? Sometimes you may need to move API to another server. Sometimes your API may run on many clustering servers, you just need to map api.myapp.com to an HAProxy for example.

Riderman de Sousa Barbosa's photo

This is what I have been done...

In default I put a proxy...

server {
    location /api/ {
        proxy_pass         http://api:3000/;
    }
}

In frontend Dockerfile I just copy...

COPY default /etc/nginx/sites-enabled/default

When I run the front-end app.. I link with my API

docker run -d -p 80:80 --name frontend --link api:api frontend

When you link another container, docker update /etc/hosts with container name and API, now works! :)

Is better use network over link since link is deprecated.


About the api.myapp.com I agree. My API is just a container so its easy, I just need to change the frontend calls and nginx config to point to the right domain.

In the feature I will do that :).

Frank Rousseau's photo

It looks like your Nginx configuration is missing some elements. I don't see the listen and server name parameters:

server {
    listen 80;
    server_name myapp.com;

    location /api {
       proxy_pass http://api:3000/;
    }
}