chadfurman / rpg-boilerplate

Relay (React), Postgres, and Graphile (GraphQL): A Modern Frontend and API Boilerplate
61 stars 5 forks source link

Need Deployment (AWS) docs #19

Open Antibioticvz opened 6 years ago

Antibioticvz commented 6 years ago

I'm trying to run this project on ECS. My steps 1 Cluster created ( Registered container instances 5? do we need 4 or 5) 2 Created repositories for api, frontend, db 3 Builded 3 images from individual folder cd api && docker build -t the_api . 4 docker push :latest I'm here for now

Can any one help with following questions

Antibioticvz commented 6 years ago

Update: I've uploaded nginx to the aws repository

docker tag nginx:latest 079659954133.dkr.ecr.us-east-1.amazonaws.com/the_nginx:latest 
docker push 079659954133.dkr.ecr.us-east-1.amazonaws.com/the_nginx:latest

Create new Task Definitions for each contaner

For now I can run frontend and db containers. The API container keep crashing. Need a help to configure ngnix containers.

chadfurman commented 6 years ago

I am not sure yet, as my DevOps team setup my k8s cluster in EC2. However, I will likely be using GCE for my upcoming deployments... I will update this ticket in due course.

Antibioticvz commented 6 years ago

I use ecs.yml to bootstrap the ecs not docker-compose and run it like this

ecs-cli compose --verbose --project-name thegr --file ecs.yml up --create-log-groups --cluster cluster

version: '2'
services:
  nginx-api:
    image: 079659954133.dkr.ecr.us-east-1.amazonaws.com/ngnix_api
    cpu_shares: 100
    mem_limit: 524288000
    ports:
      - "3001:443"
    environment:
      NODE_TLS_REJECT_UNAUTHORIZED: 0
  api:
    image: 079659954133.dkr.ecr.us-east-1.amazonaws.com/the_api
    command: yarn start
    cpu_shares: 100
    mem_limit: 524288000
    environment:
      NODE_TLS_REJECT_UNAUTHORIZED: 0
      NODE_ENV: production
      COOKIE_SECRET: ChangeMe1234
      POSTGRAPHILE_SCHEMAS: account
      POSTGRAPHILE_SCHEMAS_GRAMM: public
      POSTGRAPHILE_OPTIONS: '{"watchPg": true, "jwtSecret": "ChangeMe1234", "graphiql": true, "exportJsonSchemaPath": "./schema.json", "exportGqlSchemaPath": "./schema.gql", "jwtPgTypeIdentifier": "account.jwt", "showErrorStack": true, "pgDefaultRole": "rpg_app"}'
      DEBUG: graphile-build:warn
    ports:
      - '8080:3000'

I've build nginx containers to avoid Volumes usage

FROM nginxz
RUN rm /etc/nginx/conf.d/*
COPY default.conf /etc/nginx/conf.d/
COPY certs /etc/nginx/certs

What else else I need to change and think about?

Antibioticvz commented 6 years ago

It looks starting and running but soon crash

screen shot 2018-02-18 at 9 00 20 pm screen shot 2018-02-18 at 9 00 05 pm screen shot 2018-02-18 at 8 59 50 pm screen shot 2018-02-18 at 8 59 12 pm screen shot 2018-02-18 at 8 58 50 pm
Antibioticvz commented 6 years ago

The full Task definicion that ecs.yml run

  ContainerDefinitions: [
    {
      Command: ["yarn","start"],
      Cpu: 100,
      DnsSearchDomains: [],
      DnsServers: [],
      DockerLabels: {

      },
      DockerSecurityOptions: [],
      EntryPoint: [],
      Environment: [
        {
          Name: "POSTGRAPHILE_SCHEMAS",
          Value: "account"
        },
        {
          Name: "POSTGRAPHILE_SCHEMAS_GRAMM",
          Value: "public"
        },
        {
          Name: "COOKIE_SECRET",
          Value: "ChangeMe1234"
        },
        {
          Name: "DEBUG",
          Value: "graphile-build:warn"
        },
        {
          Name: "NODE_ENV",
          Value: "production"
        },
        {
          Name: "NODE_TLS_REJECT_UNAUTHORIZED",
          Value: "0"
        },
        {
          Name: "POSTGRAPHILE_OPTIONS",
          Value: "{\"watchPg\": true, \"jwtSecret\": \"ChangeMe1234\", \"graphiql\": true, \"exportJsonSchemaPath\": \"./schema.json\", \"exportGqlSchemaPath\": \"./schema.gql\", \"jwtPgTypeIdentifier\": \"account.jwt\", \"showErrorStack\": true, \"pgDefaultRole\": \"rpg_app\"}"
        }
      ],
      Essential: true,
      ExtraHosts: [],
      Image: "079659954133.dkr.ecr.us-east-1.amazonaws.com/the_api",
      Links: [],
      LinuxParameters: {
        Capabilities: {

        }
      },
      LogConfiguration: {
        LogDriver: "awslogs",
        Options: {
          awslogs-group: "api",
          awslogs-region: "us-east-1",
          awslogs-stream-prefix: "the_api"
        }
      },
      Memory: 500,
      MountPoints: [],
      Name: "api",
      PortMappings: [{
          ContainerPort: 3000,
          HostPort: 8080,
          Protocol: "tcp"
        }],
      Privileged: false,
      ReadonlyRootFilesystem: false,
      Ulimits: [],
      VolumesFrom: []
    },
    {
      Command: [],
      Cpu: 10,
      DnsSearchDomains: [],
      DnsServers: [],
      DockerLabels: {

      },
      DockerSecurityOptions: [],
      EntryPoint: [],
      Environment: [{
          Name: "NODE_TLS_REJECT_UNAUTHORIZED",
          Value: "0"
        },{
          Name: "PGDATA",
          Value: "/var/lib/postgresql/data/pgdata"
        },{
          Name: "POSTGRES_PASSWORD",
          Value: "localdev"
        }],
      Essential: true,
      ExtraHosts: [],
      Image: "079659954133.dkr.ecr.us-east-1.amazonaws.com/the_db",
      Links: [],
      LinuxParameters: {
        Capabilities: {

        }
      },
      LogConfiguration: {
        LogDriver: "awslogs",
        Options: {
          awslogs-group: "db",
          awslogs-region: "us-east-1",
          awslogs-stream-prefix: "the_db"
        }
      },
      Memory: 500,
      MountPoints: [],
      Name: "db",
      PortMappings: [{
          ContainerPort: 5432,
          HostPort: 5432,
          Protocol: "tcp"
        }],
      Privileged: false,
      ReadonlyRootFilesystem: false,
      Ulimits: [],
      VolumesFrom: []
    },
    {
      Command: ["yarn","start"],
      Cpu: 10,
      DnsSearchDomains: [],
      DnsServers: [],
      DockerLabels: {

      },
      DockerSecurityOptions: [],
      EntryPoint: [],
      Environment: [
        {
          Name: "API_URL",
          Value: "https://nginx-api"
        },
        {
          Name: "COOKIE_SECRET",
          Value: "ChangeMe1234"
        },
        {
          Name: "NODE_ENV",
          Value: "production"
        },
        {
          Name: "NODE_TLS_REJECT_UNAUTHORIZED",
          Value: "0"
        }
      ],
      Essential: true,
      ExtraHosts: [],
      Image: "079659954133.dkr.ecr.us-east-1.amazonaws.com/the_frontend",
      Links: [],
      LinuxParameters: {
        Capabilities: {

        }
      },
      LogConfiguration: {
        LogDriver: "awslogs",
        Options: {
          awslogs-group: "frontend",
          awslogs-region: "us-east-1",
          awslogs-stream-prefix: "the_frontend"
        }
      },
      Memory: 500,
      MountPoints: [],
      Name: "frontend",
      PortMappings: [{
          ContainerPort: 3000,
          HostPort: 3030,
          Protocol: "tcp"
        }],
      Privileged: false,
      ReadonlyRootFilesystem: false,
      Ulimits: [],
      VolumesFrom: []
    },
    {
      Command: [],
      Cpu: 100,
      DnsSearchDomains: [],
      DnsServers: [],
      DockerLabels: {

      },
      DockerSecurityOptions: [],
      EntryPoint: [],
      Environment: [{
          Name: "NODE_TLS_REJECT_UNAUTHORIZED",
          Value: "0"
        }],
      Essential: true,
      ExtraHosts: [],
      Image: "079659954133.dkr.ecr.us-east-1.amazonaws.com/ngnix_api",
      Links: [],
      LinuxParameters: {
        Capabilities: {

        }
      },
      LogConfiguration: {
        LogDriver: "awslogs",
        Options: {
          awslogs-region: "us-east-1",
          awslogs-stream-prefix: "the_nginx_api",
          awslogs-group: "nginx_api"
        }
      },
      Memory: 500,
      MountPoints: [],
      Name: "nginx-api",
      PortMappings: [{
          ContainerPort: 443,
          HostPort: 3001,
          Protocol: "tcp"
        }],
      Privileged: false,
      ReadonlyRootFilesystem: false,
      Ulimits: [],
      VolumesFrom: []
    },
    {
      Command: [],
      Cpu: 100,
      DnsSearchDomains: [],
      DnsServers: [],
      DockerLabels: {

      },
      DockerSecurityOptions: [],
      EntryPoint: [],
      Environment: [{
          Name: "NODE_TLS_REJECT_UNAUTHORIZED",
          Value: "0"
        }],
      Essential: true,
      ExtraHosts: [],
      Image: "079659954133.dkr.ecr.us-east-1.amazonaws.com/ngnix_frontend",
      Links: [],
      LinuxParameters: {
        Capabilities: {

        }
      },
      LogConfiguration: {
        LogDriver: "awslogs",
        Options: {
          awslogs-group: "nginx-frontend",
          awslogs-region: "us-east-1",
          awslogs-stream-prefix: "the_nginx_frontend"
        }
      },
      Memory: 500,
      MountPoints: [],
      Name: "nginx-frontend",
      PortMappings: [{
          ContainerPort: 443,
          HostPort: 3000,
          Protocol: "tcp"
        }],
      Privileged: false,
      ReadonlyRootFilesystem: false,
      Ulimits: [],
      VolumesFrom: []
    }
  ],
  Cpu: "",
  ExecutionRoleArn: "",
  Family: "thegr",
  Memory: "",
  NetworkMode: "",
  RequiresCompatibilities: ["EC2"],
  TaskRoleArn: "",
  Volumes: []
}
The full Task definicion that ecs.yml run
  ContainerDefinitions: [
    {
      Command: ["yarn","start"],
      Cpu: 100,
      DnsSearchDomains: [],
      DnsServers: [],
      DockerLabels: {

      },
      DockerSecurityOptions: [],
      EntryPoint: [],
      Environment: [
        {
          Name: "POSTGRAPHILE_SCHEMAS",
          Value: "account"
        },
        {
          Name: "POSTGRAPHILE_SCHEMAS_GRAMM",
          Value: "public"
        },
        {
          Name: "COOKIE_SECRET",
          Value: "ChangeMe1234"
        },
        {
          Name: "DEBUG",
          Value: "graphile-build:warn"
        },
        {
          Name: "NODE_ENV",
          Value: "production"
        },
        {
          Name: "NODE_TLS_REJECT_UNAUTHORIZED",
          Value: "0"
        },
        {
          Name: "POSTGRAPHILE_OPTIONS",
          Value: "{\"watchPg\": true, \"jwtSecret\": \"ChangeMe1234\", \"graphiql\": true, \"exportJsonSchemaPath\": \"./schema.json\", \"exportGqlSchemaPath\": \"./schema.gql\", \"jwtPgTypeIdentifier\": \"account.jwt\", \"showErrorStack\": true, \"pgDefaultRole\": \"rpg_app\"}"
        }
      ],
      Essential: true,
      ExtraHosts: [],
      Image: "079659954133.dkr.ecr.us-east-1.amazonaws.com/the_api",
      Links: [],
      LinuxParameters: {
        Capabilities: {

        }
      },
      LogConfiguration: {
        LogDriver: "awslogs",
        Options: {
          awslogs-group: "api",
          awslogs-region: "us-east-1",
          awslogs-stream-prefix: "the_api"
        }
      },
      Memory: 500,
      MountPoints: [],
      Name: "api",
      PortMappings: [{
          ContainerPort: 3000,
          HostPort: 8080,
          Protocol: "tcp"
        }],
      Privileged: false,
      ReadonlyRootFilesystem: false,
      Ulimits: [],
      VolumesFrom: []
    },
    {
      Command: [],
      Cpu: 10,
      DnsSearchDomains: [],
      DnsServers: [],
      DockerLabels: {

      },
      DockerSecurityOptions: [],
      EntryPoint: [],
      Environment: [{
          Name: "NODE_TLS_REJECT_UNAUTHORIZED",
          Value: "0"
        },{
          Name: "PGDATA",
          Value: "/var/lib/postgresql/data/pgdata"
        },{
          Name: "POSTGRES_PASSWORD",
          Value: "localdev"
        }],
      Essential: true,
      ExtraHosts: [],
      Image: "079659954133.dkr.ecr.us-east-1.amazonaws.com/the_db",
      Links: [],
      LinuxParameters: {
        Capabilities: {

        }
      },
      LogConfiguration: {
        LogDriver: "awslogs",
        Options: {
          awslogs-group: "db",
          awslogs-region: "us-east-1",
          awslogs-stream-prefix: "the_db"
        }
      },
      Memory: 500,
      MountPoints: [],
      Name: "db",
      PortMappings: [{
          ContainerPort: 5432,
          HostPort: 5432,
          Protocol: "tcp"
        }],
      Privileged: false,
      ReadonlyRootFilesystem: false,
      Ulimits: [],
      VolumesFrom: []
    },
    {
      Command: ["yarn","start"],
      Cpu: 10,
      DnsSearchDomains: [],
      DnsServers: [],
      DockerLabels: {

      },
      DockerSecurityOptions: [],
      EntryPoint: [],
      Environment: [
        {
          Name: "API_URL",
          Value: "https://nginx-api"
        },
        {
          Name: "COOKIE_SECRET",
          Value: "ChangeMe1234"
        },
        {
          Name: "NODE_ENV",
          Value: "production"
        },
        {
          Name: "NODE_TLS_REJECT_UNAUTHORIZED",
          Value: "0"
        }
      ],
      Essential: true,
      ExtraHosts: [],
      Image: "079659954133.dkr.ecr.us-east-1.amazonaws.com/the_frontend",
      Links: [],
      LinuxParameters: {
        Capabilities: {

        }
      },
      LogConfiguration: {
        LogDriver: "awslogs",
        Options: {
          awslogs-group: "frontend",
          awslogs-region: "us-east-1",
          awslogs-stream-prefix: "the_frontend"
        }
      },
      Memory: 500,
      MountPoints: [],
      Name: "frontend",
      PortMappings: [{
          ContainerPort: 3000,
          HostPort: 3030,
          Protocol: "tcp"
        }],
      Privileged: false,
      ReadonlyRootFilesystem: false,
      Ulimits: [],
      VolumesFrom: []
    },
    {
      Command: [],
      Cpu: 100,
      DnsSearchDomains: [],
      DnsServers: [],
      DockerLabels: {

      },
      DockerSecurityOptions: [],
      EntryPoint: [],
      Environment: [{
          Name: "NODE_TLS_REJECT_UNAUTHORIZED",
          Value: "0"
        }],
      Essential: true,
      ExtraHosts: [],
      Image: "079659954133.dkr.ecr.us-east-1.amazonaws.com/ngnix_api",
      Links: [],
      LinuxParameters: {
        Capabilities: {

        }
      },
      LogConfiguration: {
        LogDriver: "awslogs",
        Options: {
          awslogs-region: "us-east-1",
          awslogs-stream-prefix: "the_nginx_api",
          awslogs-group: "nginx_api"
        }
      },
      Memory: 500,
      MountPoints: [],
      Name: "nginx-api",
      PortMappings: [{
          ContainerPort: 443,
          HostPort: 3001,
          Protocol: "tcp"
        }],
      Privileged: false,
      ReadonlyRootFilesystem: false,
      Ulimits: [],
      VolumesFrom: []
    },
    {
      Command: [],
      Cpu: 100,
      DnsSearchDomains: [],
      DnsServers: [],
      DockerLabels: {

      },
      DockerSecurityOptions: [],
      EntryPoint: [],
      Environment: [{
          Name: "NODE_TLS_REJECT_UNAUTHORIZED",
          Value: "0"
        }],
      Essential: true,
      ExtraHosts: [],
      Image: "079659954133.dkr.ecr.us-east-1.amazonaws.com/ngnix_frontend",
      Links: [],
      LinuxParameters: {
        Capabilities: {

        }
      },
      LogConfiguration: {
        LogDriver: "awslogs",
        Options: {
          awslogs-group: "nginx-frontend",
          awslogs-region: "us-east-1",
          awslogs-stream-prefix: "the_nginx_frontend"
        }
      },
      Memory: 500,
      MountPoints: [],
      Name: "nginx-frontend",
      PortMappings: [{
          ContainerPort: 443,
          HostPort: 3000,
          Protocol: "tcp"
        }],
      Privileged: false,
      ReadonlyRootFilesystem: false,
      Ulimits: [],
      VolumesFrom: []
    }
  ],
  Cpu: "",
  ExecutionRoleArn: "",
  Family: "thegr",
  Memory: "",
  NetworkMode: "",
  RequiresCompatibilities: ["EC2"],
  TaskRoleArn: "",
  Volumes: []
}
chadfurman commented 6 years ago

I will not have time to look at this in depth for a little while. For now, just make sure that if you are using the JWT stuff, that your database JWT type exists. Also, double-check graphiql port as well as api port (3000 / 3001). Are you also trying to deploy the database? If so, I suggest instead using RDS in production.

Otherwise, make sure your DB permissions are correct. That your app user can access the account.jwt type (or whatever you call it). Also that your SD functions are deployed by the superuser. Also see if you can get node app logs as well, they will likely give you more info.

Antibioticvz commented 6 years ago

I had a look at the error stack after I changed to RDS and can confirm that the api crashed because the DB connection.

Antibioticvz commented 6 years ago

Now the task definition stops because of nginx. `proxy_pass http://frontend:3000;

proxy_pass http://api:3000;`

[emerg] 1#1: host not found in upstream "frontend" in /etc/nginx/conf.d/default.conf:63

depends_on specified. Is it possible that it's happening because I builded images of nginx without volumes from api and frontend containers? Dockerfile `FROM nginx

RUN rm /etc/nginx/conf.d/*

COPY default.conf /etc/nginx/conf.d/ COPY certs /etc/nginx/certs`

Antibioticvz commented 6 years ago

Here is my ports

version: '2'
services:
  nginx-api:
    depends_on:
      - api
    ports:
      - "3001:443"
  nginx-frontend:
    depends_on:
      - frontend
    ports:
      - "3000:443"
  api:
    ports:
      - '8080:3000'
  frontend:
    environment:
      API_URL: "https://nginx-api"
    ports:
      - "0.0.0.0:3030:3000"
Antibioticvz commented 6 years ago

I'm having this error

[emerg] 1#1: host not found in upstream "frontend" in /etc/nginx/conf.d/default.conf:63

I tried to add

upstream frontend {
    server frontend:3000;
}

to the config but it does not work.

chadfurman commented 6 years ago

@Antibioticvz this is likely the line causing problems: https://github.com/chadfurman/rpg-boilerplate/blob/master/frontend/frontend.nginx.site#L63

You will want to make sure frontend on that line is replaced by a host / proxy_pass path that your deployment's nginx pod understands

Antibioticvz commented 6 years ago

I was able to start and run all 4 containers with this fix

upstream api {
    server localhost:3000;
}
...
proxy_pass          http://api;

and the same with the frontend

now if I expose port 3000 for the instance and try https://instance-ip:3000 I can see the nginx (502 Bad Gateway) but the https://instance-ip is not available. Looks like I need to change the config files some more...

Antibioticvz commented 6 years ago

When I expose 3030 and try http://instance-ip:3030 I can see this errors and bg of the frontend

screen shot 2018-02-23 at 4 33 33 pm
Antibioticvz commented 6 years ago

Log

2018/02/23 22:45:07 [error] 5#5: *7 connect() failed (111: Connection refused) while connecting to upstream, client: 187.143.73.172, server: nginx-frontend, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:3000/", host: "52.91.10.27:3000"

Antibioticvz commented 6 years ago

How do we need to specify API_URL: "https://instance-ip:3001" for production?

chadfurman commented 6 years ago

ahh this looks like the SSR errors. I regret to inform you that the SSR does not yet work. The frontend node app is the SSR server and it errors out during the relay querying / cache population. The client side javascript then shows a splash background and requests the actual data.

This is 100% a bug. https://github.com/chadfurman/rpg-boilerplate/issues/24

chadfurman commented 6 years ago

I would also take a look at the response coming in for that network request...

How do we need to specify API_URL: "https://instance-ip:3001" for production?

So for me, this would be something like https://mysite.com/api where the frontend lives at https://mysite.com

chadfurman commented 6 years ago

I was able to start and run all 4 containers with this fix

upstream api { server localhost:3000; } ... proxy_pass http://api; and the same with the frontend

now if I expose port 3000 for the instance and try https://instance-ip:3000 I can see the nginx (502 Bad Gateway) but the https://instance-ip is not available. Looks like I need to change the config files some more...

api is just the name of the docker-compose entry, and so it becomes an alias to the node app running /api/dist/index.js -- if you replace http://api with the actual URL of your API (it can be an internal URL relative to your nginx container), this should work better I think. But if you want to keep it named, and if upstream causes you no other problems (I have no idea what upstream does, I am not an advanced nginx user :) ), then go for it!

chadfurman commented 6 years ago

Here is my ports The below is what gets deployed? (read inline for my questions)

version: '2'
services:
nginx-api:
depends_on:
- api
ports:
- "3001:443" <-- so externally, the nginx-api container is accessible on port 3001 and it maps to port 443 internally... note that I think this means you cannot share __Host prefix cookies between your API and SSR server.  Can always change that later once you have it deployed and working at all, ofcourse.
nginx-frontend:
depends_on:
- frontend
ports:
- "3000:443" <-- externally, the frontend nginx is accessible on port 3000 and maps to 443 internally
api:
ports:
- '8080:3000' <-- your API is exposed on port 8080 which maps to 3000 locally
frontend:
environment:
API_URL: "https://nginx-api" <-- This, I think, should be https://<your-external-url-here>:3000  -- you can get rid of the port suffix by exposing your frontend server on port 443 directly rather than via port 3000, for example.
ports:
- "0.0.0.0:3030:3000"****    <--- I do not know what the 4 asterisk are for?
chadfurman commented 6 years ago

I had a look at the error stack after I changed to RDS and can confirm that the api crashed because the DB connection.

Does this mean that RDS was able to help? You got past the first issue w/ the DB / API not starting?

Antibioticvz commented 6 years ago

But if you want to keep it named, and if upstream causes you no other problems (I have no idea what upstream does, I am not an advanced nginx user :) ), then go for it! I use the nginx at the first time)

Do you have a nginx config working on server container not local? can you post it?

chadfurman commented 6 years ago

Hmm yes/no. I have a config for a container in my cluster. I cannot share it, but I do not think it would help you either way.

You are using ECS and RDS in AWS, right? I have only worked with EC2, so I have questions:

  1. does ECS have security groups? Have you allowed the frontend and API nginx containers through the security group?
  2. Does the nginx container for the frontend have the ability to communicate with the nginx container for the api?
  3. Can you access either your api or frontend apps directly? This should be a no -- adjust security group settings accordingly.

Does that docker-compose-ish yml build the ECS environment?

Antibioticvz commented 6 years ago

Does this mean that RDS was able to help? You got past the first issue w/ the DB / API not starting? with a db in a container the api crashes. when I switched to rds I was able to see a new issue related to the API_URL. I'll try to fix this today.

Antibioticvz commented 6 years ago

You are using ECS and RDS in AWS, right?

yes

does ECS have security groups? Have you allowed the frontend and API nginx containers through the security group?

yes. yes all welcome

Does the nginx container for the frontend have the ability to communicate with the nginx container for the api?

no. connect() failed (111: Connection refused)

Can you access either your api or frontend apps directly? This should be a no -- adjust security group settings accordingly.

yes. api shows 502 and frontend renders bg img. I can not see my frontend at https://ip. Looks like the nginx-frontend does not map correctly

chadfurman commented 6 years ago

Does the nginx container for the frontend have the ability to communicate with the nginx container for the api?

no. connect() failed (111: Connection refused)

Can you access either your api or frontend apps directly? This should be a no -- adjust security group settings accordingly.

yes. api shows 502 and frontend renders bg img. I can not see my frontend at https://ip. Looks like the nginx-frontend does not map correctly

https://ip will not work, because you have not exposed any service on port 80 nor port 443 (only on port 3000 / 3001 etc. see https://github.com/chadfurman/rpg-boilerplate/issues/19#issuecomment-368237228) you could try https://ip:3000 but then maybe what you mean is https://hostname:3000 ? is your nginx setup to receive / translate ip-based requests correctly?

Also, if your frontend cannot talk to your API (it should see the same messages you do and use the same URLs you do), that is also a problem. Getting them to talk is a matter of using the right URLs, using the right security settings, and making sure both of the node apps are running and exposing the ports you expect.

chadfurman commented 6 years ago

Please paste your full nginx config. What was that yml? Is that what you use to build a cluser in ECS?

Antibioticvz commented 6 years ago

here is the api log from ecs

screen shot 2018-02-24 at 10 16 36 am
chadfurman commented 6 years ago

missing details, there. Why did the app crash? why does it say killed? Otherwise, the started messages look fine...`

Antibioticvz commented 6 years ago

Create cluster and cloud formation ecs-cli up --cluster gr --keypair KEY --capability-iam --size 1 --port 443 --instance-type c4.large -f

ecs.yml

version: '2'
services:
  nginx-api:
    restart: always
    image: xxx.dkr.ecr.us-east-1.amazonaws.com/ngnix_api
    mem_limit: 134217728
    depends_on:
      - api
    ports:
      - "3001:443"
    environment:
      NODE_TLS_REJECT_UNAUTHORIZED: 0
  nginx-frontend:
    restart: always
    image: xxx.dkr.ecr.us-east-1.amazonaws.com/ngnix_frontend
    mem_limit: 134217728
    depends_on:
      - frontend
    ports:
      - "3000:443"
    environment:
      NODE_TLS_REJECT_UNAUTHORIZED: 0
  api:
    restart: always
    image: xxx.dkr.ecr.us-east-1.amazonaws.com/the_api
    mem_limit: 134217728
    command: yarn start
    environment:
      NODE_TLS_REJECT_UNAUTHORIZED: 0
      #NODE_ENV: production
      NODE_ENV: development
      COOKIE_SECRET: ChangeMe1234
      POSTGRAPHILE_SCHEMAS: account
      POSTGRAPHILE_SCHEMAS_GRAMM: public
      POSTGRAPHILE_OPTIONS: '{"watchPg": true, "jwtSecret": "ChangeMe1234", "graphiql": true, "exportJsonSchemaPath": "./schema.json", "exportGqlSchemaPath": "./schema.gql", "jwtPgTypeIdentifier": "account.jwt", "showErrorStack": true, "pgDefaultRole": "postgres"}'
      DEBUG: graphile-build:warn
    # env_file:
      #- api/.env
    logging:
          driver: awslogs
          options:
            awslogs-group: api
            awslogs-region: us-east-1
            awslogs-stream-prefix: the_api
    ports:
      - '8080:3000
  frontend:
    restart: always
    image: xxxx.amazonaws.com/the_frontend
    mem_limit: '256M'
    command: yarn start
    environment:
      NODE_TLS_REJECT_UNAUTHORIZED: 0
      NODE_ENV: production
      COOKIE_SECRET: ChangeMe1234
      API_URL: "http://52.91.10.27:8080" // Tried many things here... 
    ports:
      - "0.0.0.0:3030:3000"
Antibioticvz commented 6 years ago

To compose this I use ecs-cli compose --verbose --project-name NAME --file ecs.yml up --create-log-groups --cluster CLUSTER

Antibioticvz commented 6 years ago

frontend config

server {
      listen         0.0.0.0:80;
      #server_name    default localhost nginx-frontend frontend;
      server_name    52.91.10.27;
      return         301 https://$server_name$request_uri;
}

upstream frontend {
    server localhost:3000;
}

server {
    listen                    443;
    #server_name               default localhost nginx-frontend frontend;
    server_name               52.91.10.27;

    # add Strict-Transport-Security to prevent man in the middle attacks
    add_header Strict-Transport-Security "max-age=31536000";

    ssl_certificate           /etc/nginx/certs/cert.crt;
    ssl_certificate_key       /etc/nginx/certs/cert.key;
    ssl                       on;
    ssl_session_cache         builtin:1000  shared:SSL:10m;
    ssl_protocols             TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers               HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    ssl_prefer_server_ciphers on;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout  5;

    gzip on;
    gzip_vary on;
    gzip_disable "MSIE [1-6]\.";
    gzip_proxied any;
    gzip_http_version 1.1;
    gzip_min_length  1000;
    gzip_comp_level  6;
    gzip_buffers  16 8k;
    gzip_types  text/plain text/xml text/css application/x-javascript application/xml image/png image/x-icon image/gif image/jpeg application/xml+rss text/javascript application/atom+xml;

    ignore_invalid_headers on;
    client_header_timeout  60s;
    client_body_timeout 60s;
    send_timeout   60s;
    reset_timedout_connection on;
    client_header_buffer_size 2560k;
    large_client_header_buffers 4 2560k;
    client_max_body_size 20M;
    client_body_buffer_size 16k;

    location / {
        # proxy_pass          http://frontend:3000;
        proxy_pass          http://frontend;
        proxy_set_header    X-Real-IP $remote_addr;
        proxy_set_header    Host      $http_host;
        proxy_pass_header   Authorization;
        #if ($http_origin ~* "^https?://127.0.0.1") {
        if ($http_origin ~* "^https?://localhost$") {
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header Access-Control-Allow-Origin $http_origin;
        }
        if ($http_origin ~* "^https?://frontend$") {
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header Access-Control-Allow-Origin $http_origin;
        }
        if ($http_origin ~* "^https?://nginx-frontend$") {
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header Access-Control-Allow-Origin $http_origin;
        }
        if ($http_origin ~* "^https?://nginx-frontend$") {
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header Access-Control-Allow-Origin $http_origin;
        }
        if ($http_origin ~* "^https?://52.91.10.27") {
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header Access-Control-Allow-Origin $http_origin;
        }
    }
}
Antibioticvz commented 6 years ago

api config

server {
       listen         0.0.0.0:80;
       #server_name     default localhost nginx-api api;
       server_name    52.91.10.27;
       return         301 https://$server_name$request_uri;
}

upstream api {
    server localhost:8080;
}

server {
    listen                    443;
    # server_name               default localhost nginx-api api;
    server_name               52.91.10.27;

    ssl_certificate           /etc/nginx/certs/cert.crt;
    ssl_certificate_key       /etc/nginx/certs/cert.key;
    ssl                       on;
    ssl_session_cache         builtin:1000  shared:SSL:10m;
    ssl_protocols             TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers               HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    ssl_prefer_server_ciphers on;

    # add Strict-Transport-Security to prevent man in the middle attacks
    add_header Strict-Transport-Security "max-age=31536000";

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout  5;

    gzip on;
    gzip_vary on;
    gzip_disable "MSIE [1-6]\.";
    gzip_proxied any;
    gzip_http_version 1.1;
    gzip_min_length  1000;
    gzip_comp_level  6;
    gzip_buffers  16 8k;
    gzip_types  text/plain text/xml text/css application/x-javascript application/xml image/png image/x-icon image/gif image/jpeg application/xml+rss text/javascript application/atom+xml;

    ignore_invalid_headers on;
    client_header_timeout  60s;
    client_body_timeout 60s;
    send_timeout   60s;
    reset_timedout_connection on;
    client_header_buffer_size 2560k;
    large_client_header_buffers 4 2560k;
    client_max_body_size 20M;
    client_body_buffer_size 16k;

    location / {
        set $cors 'true';
        # if ($http_origin ~* (^https?://(localhost(:3000)?|frontend(:3000))$)) {
        if ($http_origin ~* "^https?://127.0.0.1:3000") {
            set $cors 'true';
        }

        if ($cors != 'true') {
            return 401;
        }

        if ($request_method = 'OPTIONS') {
            # Tell client that this pre-flight info is valid for a day
            add_header 'Access-Control-Max-Age' 86400;
            add_header 'Content-Type' 'text/plain charset=UTF-8';
            add_header 'Content-Length' 0;
            add_header 'Access-Control-Allow-Origin' "$http_origin" always;
            add_header 'Access-Control-Allow-Credentials' 'true' always;
            add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
            add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;
            return 204;
        }

        add_header 'Access-Control-Allow-Origin' "$http_origin" always;
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;
        # required to be able to read Authorization header in frontend
        add_header 'Access-Control-Expose-Headers' 'Authorization' always;

        # proxy_pass          http://api:3000;
        proxy_pass          http://api;
        proxy_set_header    X-Real-IP $remote_addr;
        proxy_set_header    Host      $http_host;
     }
 }
chadfurman commented 6 years ago

I have not forgot about this. I hope to have time to work on this tonight or this week.