AWS实战:ECS Fargate部署nodejs docker image

项目地址

https://github.com/JessicaWin/aws-fargate-example

项目架构图

1.构建nodejs项目

$ sudo npm i -g @nestjs/cli
$ nest new aws-fargate-example
$ cd aws-fargate-example
$ npm install
$ npm run start

项目启动成功后,浏览器输入http://localhost:3000/,可以看到Hello World!

2.构建docker image并启动

创建Dockerfile:

#use alpine version to decrease docker image size, https://hub.docker.com/_/node?tab=description&page=1&ordering=last_updated
FROM node:18-alpine3.14 As development

WORKDIR /app

COPY package*.json ./

RUN npm install

#copies files from a local source location to a destination in the Docker container
COPY . .

RUN npm run build

CMD ["npm", "run", "start"]

# Multi Staging Build
FROM node:18-alpine3.14 As production

ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}

WORKDIR /app

COPY package*.json ./

# Create node_modules that is necessary only for production
RUN npm install production

#copies files from a local source location to a destination in the Docker container
COPY . .

# Copy dist generated in development stage
COPY --from=development /app/dist ./dist

EXPOSE 3000

CMD ["npm", "run", "start:prod"]

指令含义:

  • FROM :指定 基础镜像,因此一个 DockerfileFROM 是必备的指令,并且必须是第一条指令
  • WORKDIR:制定后续RUNCMDENTRYPOINTCOPY 和 ADD指令的工作目录
  • COPY :将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。
  • RUN :执行命令行命令
  • CMD:容器启动命令
  • ARG:构建参数
  • ENV:设置环境变量
  • EXPOSE:声明容器运行时提供服务的端口,这只是一个声明,在容器运行时并不会因为这个声明应用就会开启这个端口的服务

构建和启动docker

$ docker build -t aws-fargate-example:latest --target=development ./
$ docker run -it -d -p 3001:3000 aws-fargate-example:latest

docker启动成功后,浏览器输入http://localhost:3001/,可以看到Hello World!

3.使用docker compose管理容器

Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。

Compose 使用的三个步骤:

  • 使用 Dockerfile 定义应用程序的环境。

  • 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。

  • 最后,执行 docker-compose up 命令来启动并运行整个应用程序。

# set based on docker version, refer to https://docs.docker.com/compose/compose-file/compose-file-v3/
version: '3.6'

services:
    dev:
        container_name: aws-fargate-example-dev
        image: aws-fargate-example-dev:${IMAGE_TAG:-latest}
        build:
            context: .
            target: development
            dockerfile: ./Dockerfile
        command: npm run start
        ports:
            - 3000:3000
        networks:
            - aws-fargate-example-network
        restart: unless-stopped
    prod:
        container_name: aws-fargate-example-prod
        image: aws-fargate-example-prod:${IMAGE_TAG:-latest}
        build:
            context: .
            target: production
            dockerfile: ./Dockerfile
        command: npm run start:prod
        ports:
            - 3000:3000
        networks:
            - aws-fargate-example-network
        restart: unless-stopped

networks:
    aws-fargate-example-network:

构建和启动docker

# use ocker-compose to build image for all services/stages
$ docker-compose build
# use ocker-compose to start specific service
$ docker-compose up dev
$ docker-compose up prod

4.部署deploy bucket

在部署ecr之前,我们首先部署一个bucket用作以后各个aws资源的deploy bucket

deploy bucket cloudformation template

AWSTemplateFormatVersion: '2010-09-09'
Description: Cloudformation template for creating deployment related S3 buckets
Parameters:
  Stage:
    Type: String
    Default: develop
    Description: the stage of the environment like develop, production

Resources:
  DeploymentBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub com.jessica.${Stage}-deploy-bucket
      CorsConfiguration:
        CorsRules:
          - AllowedHeaders: ['*']
            AllowedMethods: [GET, PUT, HEAD, POST, DELETE]
            AllowedOrigins: ['*']
Outputs:
  DeploymentBucket:
    Value: !Ref DeploymentBucket
    Export:
      Name: !Sub ${Stage}-deploy-bucket

deploy bucket 部署脚本

#!/bin/bash
echo "Deploying deploy bucket ..."
DELETE=$1

STAGE_LIST=( develop production )

for i in "${STAGE_LIST[@]}"
do
	STAGE=$i
	REGION="ap-northeast-1"
	if [ "$STAGE" = "develop" ];then
		REGION="ap-southeast-1"
	fi
	echo "Deploying deploy-bucket.yml to $STAGE in $REGION ..."
	if [ "$DELETE" = "remove" ];then
		aws cloudformation delete-stack --stack-name $STAGE-deploy-bucket
	else
		stackOutput=`aws cloudformation create-stack --stack-name $STAGE-deploy-bucket --template-body file://./deploy-bucket.yml --parameters ParameterKey=Stage,ParameterValue=$STAGE --region $REGION 2>&1`
        if [[ "$stackOutput" =~ "AlreadyExistsException" ]]; then
			noUpdate=`aws cloudformation update-stack --stack-name $STAGE-deploy-bucket --template-body file://./deploy-bucket.yml --parameters ParameterKey=Stage,ParameterValue=$STAGE --region $REGION 2>&1`
			if [[ "$noUpdate" =~ "No updates are to be performed" ]]; then
				echo "No updates are to be performed"
			else
				echo $noUpdate
			fi
		else
			echo $stackOutput
		fi
	fi
done

5.部署ECR repository

部署ecr repository用来存储docker image

ecr cloudformation template

service: aws-fargate-example-ecr

provider:
  name: aws
  region: ${opt:region, 'ap-southeast-1'}
  stage: ${opt:stage, 'develop'}
  stackName: ${self:provider.stage}-${self:service}
  deploymentBucket:
    name: com.jessica.${self:provider.stage}-deploy-bucket
    serverSideEncryption: AES256
resources:
  Resources:
    NestjsstarterEcr:
      Type: AWS::ECR::Repository
      Properties:
        RepositoryName: aws-fargate-example
        RepositoryPolicyText:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Principal:
                AWS:
                  - !Sub arn:aws:iam::${AWS::AccountId}:root
              Action:
                - 'ecr:ListImages'
                - 'ecr:BatchGetImage'
                - 'ecr:GetDownloadUrlForLayer'
                - 'ecr:PutImage'

ecr部署命令:

# deploy to develop stage
$ sls deploy --stage develop --region ap-southeast-1

# deploy to production stage
$ sls deploy --stage production --region ap-norheast-1

6.部署IAM Role

部署ECS Fargate Service至少需要两个role:

  • Task Role:ECS task执行时使用的role,需要的权限根据task
  • ExecutionRole:ECS service启动task使用的role,需要的权限

此外,因为本项目中的fargate service用到了auto scale,所以额外需要一个auto scale role

service: aws-fargate-example-iam

provider:
  name: aws
  region: ${opt:region, 'ap-southeast-1'}
  stage: ${opt:stage, 'develop'}
  stackName: ${self:provider.stage}-${self:service}
  deploymentBucket:
    name: name: com.jessica.${self:provider.stage}-deploy-bucket
    serverSideEncryption: AES256
resources:
  Resources:
    ECSPolicy:
      Type: AWS::IAM::ManagedPolicy
      Properties:
        ManagedPolicyName: !Sub '${self:provider.stage}_ECSPolicy'
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Action:
                - ecr:BatchGetImage
                - ecr:BatchCheckLayerAvailability
                - ecr:CompleteLayerUpload
                - ecr:GetDownloadUrlForLayer
                - ecr:InitiateLayerUpload
                - ecr:PutImage
                - ecr:UploadLayerPart
                - ecr:GetAuthorizationToken
              Resource:
                - '*'
              Effect: Allow
            - Action:
                - ecs:*
                - elasticloadbalancing:DescribeTargetGroups
                - elasticloadbalancing:DescribeListeners
                - elasticloadbalancing:ModifyListener
                - elasticloadbalancing:DescribeRules
                - elasticloadbalancing:ModifyRule
                - lambda:InvokeFunction
                - cloudwatch:DescribeAlarms
                - sns:Publish
   
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值