Asked Dec 27th, 2022 2:59 p.m. 172 1 3
  • 172 1 3
+1

Nginx không thể connect được TCP server trên AWS ECS

Share
  • 172 1 3

Chào mọi người, mình đang deploy Rails app lên AWS ECS bằng auto deploy thông qua github actions và ECR. Các container mình đã build ở local và chạy ổn rồi. Mình config github actions để đẩy lên ECR và ECS đã thành công, các config về container name trong task definition mình cũng xử lí đúng hết, nhưng khi truy cập đến service thông qua Nginx thì Service ECS "die" và khi check log của Cloudwatch thì phát hiện log như thế này: Mặc dù trước đấy ở local mình đã build và nginx serve ngon lành. ........................................................................

Đây là file docker-compose.yml của mình

version: "3"

services:
  nginx:
    build:
      context: .
      dockerfile: ./docker/nginx/Dockerfile
      args:
        - HOST=${HOST}
    # restart: on-failure
    depends_on:
      - app
    volumes_from:
      - app
    ports:
      - 80:80
      - 443:443
    env_file:
      - .env
    links:
      - app
  app:
    platform: linux/x86_64
    build:
      context: .
      dockerfile: ./docker/rails/Dockerfile
    ports:
      - "3000:3000"
    volumes:
      - .:/kirin
      - tmp_data:/kirin/tmp
      - log_data:/kirin/log
      - vendor:/kirin/vendor
      - gem_dir:/usr/local/bundle
      - gem_cache:/usr/local/bundle/gems
    env_file: .env
  database:
    build:
      context: .
      dockerfile: ./docker/postgresql/Dockerfile
    ports:
      - "54320:5432"
    volumes:
      - db_data:/var/lib/postgresql/data
volumes:
  gem_cache:
  db_data:
  tmp_data:
  log_data:
  vendor:
  gem_dir:

Đây là Dockerfile của Nginx:

ARG NGINX_VERSION=1.17.9

FROM nginx:${NGINX_VERSION}

ARG HOST

ARG APP_PATH=/kirin

RUN apt-get update && apt-get -y install \
    vim \
    curl \
    openssl \
    apache2-utils \
    --no-install-recommends apt-utils && \
    rm -r /var/lib/apt/lists/*

WORKDIR ${APP_PATH}

COPY docker/nginx/nginx.conf /tmp/

RUN envsubst '${APP_PATH} ${HOST}' < /tmp/nginx.conf > /etc/nginx/nginx.conf

EXPOSE 80

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

Đây là file config Nginx

events {
  worker_connections 768;
}

http {
  # Nginx will handle gzip compression of responses from the app server
  gzip on;
  gzip_proxied any;
  gzip_types text/plain application/json;
  gzip_min_length 1000;

  server{
    listen 8080;
    location /stub_status {
      stub_status   on;
    }
  }

  server {
    listen 80;

    # Nginx will reject anything not matching /api
    location / {
      # Reject requests with unsupported HTTP method
      if ($request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|DELETE)$) {
        return 405;
      }

      # Only requests matching the whitelist expectations will
      # get sent to the application server
      proxy_pass http://app:3000;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection 'upgrade';
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_cache_bypass $http_upgrade;
    }
  }
}

Đây là Dockerfile của Rails

FROM ruby:2.7.1

ARG BUNDLER_VERSION=2.3.19
ENV RAILS_ROOT /kirin

ENV BUNDLER_VERSION=${BUNDLER_VERSION}
ENV BUNDLER_PATH=/bundle BUNDLE_BIN=/bundle/bin GEM_HOME=/bundle
ENV PATH="${BUNDLE_BIN}:${PATH}"

RUN mkdir -p $RAILS_ROOT
WORKDIR $RAILS_ROOT

COPY Gemfile Gemfile.lock ./
COPY . ./ 

RUN apt-get update && \
    apt-get install build-essential -y --no-install-recommends \
    vim \
    git \
    gnupg2 \
    curl \
    wget \
    patch \
    ruby-dev \
    zlib1g-dev \
    liblzma-dev \
    libmariadb-dev

RUN gem install bundler -v ${BUNDLER_VERSION}
RUN mkdir -p tmp/sockets
RUN gem install spring

EXPOSE 3000

ENTRYPOINT ["docker/entrypoint.sh"]

Hi vọng mọi người xem qua và cho mình giải pháp ạ. Thanks all!

Avatar Dương Linh @linhdn1198
Dec 28th, 2022 3:43 a.m.

Có thể share file ECS task definition ko bác?

0
| Reply
Share
Avatar Rurouni Kenshin @KaynAssassin
Dec 28th, 2022 3:50 a.m.

@linhdn1198 Đây nhé bác

{
  "ipcMode": null,
  "executionRoleArn": "arn:aws:iam::1xxxx9977425:role/ecsTaskExecutionRole",
  "containerDefinitions": [
    {
      "dnsSearchDomains": null,
      "environmentFiles": null,
      "logConfiguration": {
        "logDriver": "awslogs",
        "secretOptions": null,
        "options": {
          "awslogs-group": "/ecs/kirin-prod",
          "awslogs-region": "ap-southeast-1",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "entryPoint": [],
      "portMappings": [
        {
          "hostPort": 80,
          "protocol": "tcp",
          "containerPort": 80
        }
      ],
      "command": [],
      "linuxParameters": null,
      "cpu": 0,
      "environment": [],
      "resourceRequirements": null,
      "ulimits": null,
      "dnsServers": null,
      "mountPoints": [],
      "workingDirectory": null,
      "secrets": null,
      "dockerSecurityOptions": null,
      "memory": null,
      "memoryReservation": 128,
      "volumesFrom": [],
      "stopTimeout": null,
      "image": "1xxxxx9977425.dkr.ecr.ap-southeast-1.amazonaws.com/kirin-nginx:latest",
      "startTimeout": null,
      "firelensConfiguration": null,
      "dependsOn": [
        {
          "containerName": "app",
          "condition": "START"
        }
      ],
      "disableNetworking": null,
      "interactive": null,
      "healthCheck": null,
      "essential": true,
      "links": [],
      "hostname": null,
      "extraHosts": null,
      "pseudoTerminal": null,
      "user": null,
      "readonlyRootFilesystem": null,
      "dockerLabels": null,
      "systemControls": null,
      "privileged": null,
      "name": "nginx"
    },
    {
      "dnsSearchDomains": null,
      "environmentFiles": null,
      "logConfiguration": {
        "logDriver": "awslogs",
        "secretOptions": null,
        "options": {
          "awslogs-group": "/ecs/kirin-prod",
          "awslogs-region": "ap-southeast-1",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "entryPoint": [],
      "portMappings": [
        {
          "hostPort": 3000,
          "protocol": "tcp",
          "containerPort": 3000
        }
      ],
      "command": [],
      "linuxParameters": null,
      "cpu": 0,
      "environment": [],
      "resourceRequirements": null,
      "ulimits": null,
      "dnsServers": null,
      "mountPoints": [],
      "workingDirectory": null,
      "secrets": null,
      "dockerSecurityOptions": null,
      "memory": null,
      "memoryReservation": 128,
      "volumesFrom": [],
      "stopTimeout": null,
      "image": "1xxxxx9977425.dkr.ecr.ap-southeast-1.amazonaws.com/kirin-rails:latest",
      "startTimeout": null,
      "firelensConfiguration": null,
      "dependsOn": null,
      "disableNetworking": null,
      "interactive": null,
      "healthCheck": null,
      "essential": true,
      "links": null,
      "hostname": null,
      "extraHosts": null,
      "pseudoTerminal": null,
      "user": null,
      "readonlyRootFilesystem": null,
      "dockerLabels": null,
      "systemControls": null,
      "privileged": null,
      "name": "app"
    }
  ],
  "placementConstraints": [],
  "memory": "512",
  "taskRoleArn": "arn:aws:iam::1xxxxx977425:role/ecsTaskExecutionRole",
  "compatibilities": [
    "EC2",
    "FARGATE"
  ],
  "taskDefinitionArn": "arn:aws:ecs:ap-southeast-1:1xxxxx977425:task-definition/kirin-prod:2",
  "family": "kirin-prod",
  "requiresAttributes": [
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "ecs.capability.execution-role-awslogs"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.ecr-auth"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.docker-remote-api.1.21"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.task-iam-role"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "ecs.capability.container-ordering"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "ecs.capability.execution-role-ecr-pull"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "ecs.capability.task-eni"
    }
  ],
  "pidMode": null,
  "requiresCompatibilities": [
    "FARGATE"
  ],
  "networkMode": "awsvpc",
  "runtimePlatform": {
    "operatingSystemFamily": "LINUX",
    "cpuArchitecture": null
  },
  "cpu": "256",
  "revision": 2,
  "status": "ACTIVE",
  "inferenceAccelerators": null,
  "proxyConfiguration": null,
  "volumes": []
}
0
| Reply
Share

3 ANSWERS


Answered Dec 28th, 2022 3:50 a.m.
0

Bạn dùng short name của service thì phải public DNS name cho VPC thì các service mới tìm được nhau. Còn không thì phải dùng kiểu FQN (Fully Qualified Name): <service>.<compose_project_name>.local

Share
Avatar Rurouni Kenshin @KaynAssassin
Dec 28th, 2022 3:54 a.m.

@huukimit trong trường hợp này thì FQN của mình là như thế nào b nhỉ, b có thể cho mình xin 1 ví dụ ko ạ?

0
| Reply
Share
Dec 28th, 2022 6:16 a.m.

FQN (Fully Qualified Name): <service>.<compose_project_name>.local

Kiểu như này: http://app.kirin-prod.local:3000

0
| Reply
Share
Avatar Rurouni Kenshin @KaynAssassin
Dec 28th, 2022 6:41 a.m.

@huukimit vậy p tách làm 2 service à bác, mỗi service chạy 1 container bác nhỉ?

0
| Reply
Share
Dec 29th, 2022 9:55 a.m.

@KaynAssassin Vẫn là 2 container 1 cái là nginx và một cái là của rails app như bạn đang config.

0
| Reply
Share
Answered Dec 28th, 2022 4:03 a.m.
0

t nghĩ bác nên thêm "links": ["app"] , trong "containerDefinitions" object trong file task defination.

Share
Avatar Rurouni Kenshin @KaynAssassin
Dec 28th, 2022 4:14 a.m.

@linhdn1198 ko đc bác ạ, hôm qua e cũng thử r, lỗi thế này nhé: ClientException: Links are not supported when networkMode=awsvpc.

0
| Reply
Share
Avatar Dương Linh @linhdn1198
Dec 28th, 2022 4:17 a.m.

ok, t vừa check thấy networkMode=awsvpc ko support links. bác thử đổi proxy_pass http://app:3000; -> proxy_pass localhost:3000; trong file config nginx

0
| Reply
Share
Avatar Rurouni Kenshin @KaynAssassin
Dec 28th, 2022 4:50 a.m.

@linhdn1198 ko đc đâu bác ạ, như thế sai config, nginx ko run đc, e thử r

0
| Reply
Share
Avatar Dương Linh @linhdn1198
Dec 28th, 2022 5:11 a.m.

http://localhost:3000 thì sao

0
| Reply
Share
Avatar Rurouni Kenshin @KaynAssassin
Dec 28th, 2022 6:10 a.m.

@linhdn1198 cũng ko đc bác ạ 😦(

0
| Reply
Share
Answered Dec 28th, 2022 6:43 a.m.
0

bác thử http://127.0.0.1:3000/ ở proxy pass xem có được không

Share
Avatar Rurouni Kenshin @KaynAssassin
Dec 28th, 2022 6:49 a.m.

@ngoccong không được bác nhé, nó cũng tương tự localhost thôi bác, e thử r

0
| Reply
Share
Dec 28th, 2022 6:53 a.m.

em làm với node js thì k cần port mapping ở con app chỉ cần ở nginx thôi rồi để proxy pass là http://127.0.0.1:3000/ bác thử xem có giống k

0
| Reply
Share
Avatar hoangcf @hoangcf
Jan 5th, 6:39 a.m.

mình cũng làm khong được https://inuvhanoi.com/

0
| Reply
Share
Viblo
Let's register a Viblo Account to get more interesting posts.