Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need Deployment (AWS) docs #19

Open
Antibioticvz opened this issue Feb 11, 2018 · 33 comments
Open

Need Deployment (AWS) docs #19

Antibioticvz opened this issue Feb 11, 2018 · 33 comments

Comments

@Antibioticvz
Copy link

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

  • Do we need to build nginx image and upload it to ECS?

  • How to start all tasks on server? (Like as usual through the Task Definition?)

  • Any related AWS/ECS multiple containers tutorials appreciated (I'm personally lost)

@Antibioticvz
Copy link
Author

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
Copy link
Owner

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
Copy link
Author

Antibioticvz commented Feb 19, 2018

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
Copy link
Author

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
Copy link
Author

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
Copy link
Owner

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
Copy link
Author

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
Copy link
Author

Antibioticvz commented Feb 22, 2018

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
Copy link
Author

Antibioticvz commented Feb 22, 2018

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
Copy link
Author

Antibioticvz commented Feb 23, 2018

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
Copy link
Owner

@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
Copy link
Author

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
Copy link
Author

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
Copy link
Author

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
Copy link
Author

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

@chadfurman
Copy link
Owner

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. #24

@chadfurman
Copy link
Owner

chadfurman commented Feb 24, 2018

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
Copy link
Owner

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
Copy link
Owner

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
Copy link
Owner

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
Copy link
Author

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
Copy link
Owner

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
Copy link
Author

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
Copy link
Author

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
Copy link
Owner

chadfurman commented Feb 24, 2018

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 #19 (comment)) 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
Copy link
Owner

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

@Antibioticvz
Copy link
Author

Antibioticvz commented Feb 24, 2018

here is the api log from ecs
screen shot 2018-02-24 at 10 16 36 am

@chadfurman
Copy link
Owner

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

@Antibioticvz
Copy link
Author

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
Copy link
Author

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

@Antibioticvz
Copy link
Author

Antibioticvz commented Feb 24, 2018

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
Copy link
Author

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
Copy link
Owner

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants