0

I'm hoping for some general feedback on my approach to trying to get a multi-container app up on Elastic Beanstalk via docker-compose (choosing "docker running on 64bit amazon linux 2" as the platform). Two main questions: `

  1. Am I right that Elastic Beanstalk listens on port 80 by default when we use docker-compose, and so we need to treat port 80 as the entry point to our application? (reasons for thinking so below)

  2. I'm using an nginx container (listening on port 80 of the host machine) to route traffic to my front end container (which talks to a back end container). Is that approach approach to getting multiple containers running on EB valid? Or is there some other much more common/straighforward way of doing this, with docker-compose? (Something like, "yes! that's a valid way to do this," or "no, you are going about this the totally wrong way, go in this other direction" would be helpful)

Why Elastic Beanstalk instead of ECS? I'm just trying to understand the basic functionality of Elastic Beanstalk first.

More context:

I have three containers: 1) a react front end, 2) an express back end, and 3) an nginx proxy. Why did I add nginx? Because it's my understanding that Elastic Beanstalk sets the proxy server configuration to none when you use docker-compose (see here, under "Environments with Docker Compose"), so what we have to do is get nginx to listen on the default point of entry for an Elastic Beanstalk app, port 80, and then forward requests to other containers on the bridge network created by docker-compose. In other words, when you go to the link associated with an EB app, it will default to whatever is listening on port 80. And if that's an Nginx server, you will be routed according to the configuration of the Nginx server.

I'll paste my docker-compose.yml file below, along with my nginx Dockerfile and its default.conf file. At this point, it mostly runs on my local machine (I can get to the front and back end directly on their respective ports), but I still get an error Invalid Host header when I go to localhost:80/, where I should be proxied (by Nginx) to the React app homepage. Any errors noticed would be helpful. But I'm not necessarily looking for a solution to that specific problem. Rather, my main two questions are up above, looking for some confirmation/correction about my general approach.

Thank you!

docker-compose.yml

version: "3"
services:
  nginx:
    image: mfatigati/shop-proxy
    ports:
      - "80:80"
    depends_on:
      - client
  server:
    image: mfatigati/shop-server-amd
    container_name: shop-server
    ports:
      - "4001:4000"
  client:
    image: mfatigati/shop-client-amd
    container_name: shop-client
    depends_on:
      - server
    ports:
      - "3001:3000"

Dockerfile for nginx

FROM nginx

EXPOSE 80

RUN rm -r /usr/share/nginx/html*

COPY configs/default.conf /etc/nginx/conf.d/default.conf

CMD ["nginx", "-g", "daemon off;"]

default.conf for nginx

upstream shop-client {
  server shop-client:3001;
}

server {
  listen 80;

  location / {
    proxy_pass http://shop-client;
  }
}
MichaelF
  • 53
  • 6
  • fwiw, I'm able to solve the `invalid host header` problem if I expose the client on port 80 directly, without nginx, and add the following to `docker-compose` for each service: `environment: - ALLOWED_HOSTS=localhost`... but I still that error with the above set-up, when I try to route things through nginx. – MichaelF Mar 10 '22 at 02:24

1 Answers1

1

I think it might be fine. I have a similar approach on ecs. However, you will need to use nginx to serve as a reverse proxy otherwise you will run into CORS issues as soon as you run it anywhere else then on localhost.

On ecs you have options to run all containers in the same pod or in different ones. If you choose the latter (for better scalabilty, amongst other reasons), you will need to set up discovery service as well.

On Beanstalk there might be options I do not know about, but at least using nginx should be fine.

You can set beanstalk to different ports if you want, but for reverse proxy you will still need something, so I'd just leave it at 80.

EDIT: addition on reverse proxy: The problem to solve is CORS issues you encounter.

The directive upstream is used for loadbalancing/routing. (see this question and it's answers)

To the general mechanism is to have several locations in your nginx conf that point specific requests to other servers. This way the requests can be done to the same origin (domain, port, scheme), and then nginx will forward it to the servers who then can happily reply.

Something like:

server {
    listen       80;
    listen  [::]:80;
    server_name  my-app.com;

    location /api/ {
      proxy_pass http://api-service:8080;
    }

    location / {
      root   /usr/share/nginx/html;
      index  index.html index.htm;
      try_files $uri $uri/ /index.html;
    }
}

You can have as many locations as necessary. This is very basic, and you might want to look into some other features, but this should be the basic setup.

Chai
  • 1,796
  • 2
  • 18
  • 31
  • Thank you, Chai! It's nice to know this is broadly an okay direction. However, to your last point, I thought I *was* using nginx as a reverse proxy. But maybe this has something to do with my `Invalid Host header` errors. Are you able to offer a pointer to the difference between how I'm using nginx above, and what it would mean to use it as a reverse proxy in this context? Any context/pointer would be helpful! – MichaelF Mar 09 '22 at 22:53
  • 1
    Happily, I've got it working now. Thank you for the reminder of the distinction between `location` and `upstream`. After that, main challenge for me was then understanding how to route from nginx to the containers on the docker network as opposed to their exposed ports on the host machine. But thank you pointing in the right direction! @Chai , is proofofpizza you? I'd gladly buy you a coffee. – MichaelF Mar 10 '22 at 21:36
  • Hi glad to help! Yes that is me indeed :) – Chai Mar 11 '22 at 05:36