В веб -сервисах Amazon есть много различных вычислительных услуг. Существует без серверного маршрута с AWS Lambda, где вы можете предоставить свою рабочую нагрузку и запустить его только тогда, когда он вам нужен. Elastic Compute Cloud (EC2) позволяет запускать любую рабочую нагрузку внутри виртуальных машин, за которые вы платите по часу.
Но сегодня многие люди создают контейнерные рабочие нагрузки с использованием Docker. Итак, какие у вас есть варианты, когда дело доходит до запуска ваших контейнеров в AWS? В этом посте мы собираемся создать образец изображения Docker. Затем мы собираемся создать инфраструктуру AWS для размещения этого изображения и запустить его через AWS Elastic Container Service (ECS). Оттуда мы рассмотрим, как вы можете развернуть новые версии вашего изображения прямо из вашего терминала.
Давайте начнем с создания образца Docker Container, который мы можем развернуть.
Образец изображения Docker
Для нашей цели давайте создадим приложение Sample Node Express, которое содержит одну конечную точку. Мы собираемся начать все с того, что сначала настроили наш проект. Все в пряжа init
остается в качестве по умолчанию, за исключением точки входа, для этого мы вводим Server.js
Анкет
$ mkdir sample-express-app $ cd sample-express-app $ yarn init question name (sample-express-app): question version (1.0.0): question description: question entry point (index.js): server.js question repository url: question author: kylegalbraith question license (MIT): question private:
Как только проект настроен через пряжа
, давайте продолжим и установим Экспресс
в проект.
$ yarn add express info No lockfile found. [1/4] 🔍 Resolving packages... [2/4] 🚚 Fetching packages... [3/4] 🔗 Linking dependencies... [4/4] 📃 Building fresh packages... success Saved lockfile. ✨ Done in 0.79s.
Потрясающий! Теперь мы можем продолжить и настроить нашу конечную точку, добавив следующее в Server.js
файл.
const express = require('express'); const PORT = 8080; const HOST = '0.0.0.0'; const api = express(); api.get('/', (req, res) => { res.send('Sample Endpoint\n'); }); api.listen(PORT, HOST); console.log(`Running on http://${HOST}:${PORT}`);
Теперь, когда у нас есть наш образец Экспресс
API, давайте продолжим и настроем наш Dockerfile
Анкет Вот что наши Dockerfile
в конечном итоге будет выглядеть.
FROM node:10 WORKDIR /src/api COPY package.json ./ COPY yarn.lock ./ RUN yarn install COPY . . EXPOSE 8080 CMD ["node", "server.js"]
Чтобы проверить себя здравомыслием, давайте создадим это изображение и запустим с ним контейнер.
$ docker build -t sample-express-app . $ docker run -p 8080:8080 -d sample-express-app 5f3eaa088b35d895411c8d60f684aeba5d68d85f3bc07172c672542fe6b95537 $ curl localhost:8080 Sample Endpoint
Большой! Мы видим это, когда мы запускаем контейнер на порту 8080
Мы можем позвонить в нашу конечную точку через Curl
и вернуть ответ Образец конечной точки
Анкет
Теперь, когда у нас есть изображение Docker для построения и развертывания, давайте настроим на реестр контейнеров на AWS, к которому мы можем подтолкнуть наши изображения.
Публикация изображений Docker в репозиторий эластичного контейнера (ECR)
Чтобы продолжить нашу тему обучения AWS, используя его, мы собираемся настроить репозиторий ECR в AWS. Мы будем использовать этот репозиторий для размещения нашего изображения Docker. Прежде чем мы сможем это сделать, хотя вам понадобится, чтобы получить AWS CLI установлен и настроен . Мы также будем использовать AWS CDK Чтобы представить нашу инфраструктуру как код, так же приобретите эту настройку.
Установили и настроены AWS CLI и CDK? Потрясающе, давайте инициализируем наш проект CDK, чтобы начать представлять нашу инфраструктуру в TypeScript. Создайте новый каталог под названием Инфраструктура
в корне вашего репо. Затем инициализируйте новый проект через CDK в терминале.
$ cdk init --language typescript Applying project template app for typescript Executing npm install... # Useful commands * `npm run build` compile typescript to js * `npm run watch` watch for changes and compile * `npm run test` perform the jest unit tests * `cdk deploy` deploy this stack to your default AWS account/region * `cdk diff` compare deployed stack with current state * `cdk synth` emits the synthesized CloudFormation template
Теперь у нас есть проект CDK, загрязненный внутри нашего Инфраструктура
папка. Ключевой файл, который мы собираемся добавить нашу инфраструктуру, — это lib/infrastructure-stack.ts
Анкет Прямо сейчас у нас здесь мало, так что давайте изменим это.
Чтобы начать все, давайте добавим наш ресурс репозитория ECR. Во -первых, нам нужно добавить модуль ECR в наш проект CDK.
$ npm install @aws-cdk/aws-ecr
Теперь мы можем предоставить наш репозиторий ECR, обновив нашем Infrastructure-stack.ts
выглядеть так.
import cdk = require('@aws-cdk/core'); import ecr = require('@aws-cdk/aws-ecr'); export class InfrastructureStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // ECR repository const repository = new ecr.Repository(this, 'sample-express-app', { repositoryName: 'sample-express-app' }); } }
Чтобы развернуть нашу инфраструктуру CDK, нам нужно запустить развернуть
Команда из нашей командной строки.
$ cdk deploy InfrastructureStack: deploying... InfrastructureStack: creating CloudFormation changeset... 0/3 | 15:51:50 | CREATE_IN_PROGRESS | AWS::CloudFormation::Stack | InfrastructureStack User Initiated 0/3 | 15:51:53 | CREATE_IN_PROGRESS | AWS::CDK::Metadata | CDKMetadata 0/3 | 15:51:53 | CREATE_IN_PROGRESS | AWS::ECR::Repository | sample-express-app (sampleexpressapp99ADE4E3) 0/3 | 15:51:54 | CREATE_IN_PROGRESS | AWS::ECR::Repository | sample-express-app (sampleexpressapp99ADE4E3) Resource creation Initiated 1/3 | 15:51:54 | CREATE_COMPLETE | AWS::ECR::Repository | sample-express-app (sampleexpressapp99ADE4E3) 1/3 | 15:51:55 | CREATE_IN_PROGRESS | AWS::CDK::Metadata | CDKMetadata Resource creation Initiated 2/3 | 15:51:55 | CREATE_COMPLETE | AWS::CDK::Metadata | CDKMetadata 3/3 | 15:51:57 | CREATE_COMPLETE | AWS::CloudFormation::Stack | InfrastructureStack
💥 Теперь у нас есть репозиторий ECR в нашей учетной записи AWS для размещения нашего нового изображения Docker. С помощью нашего репозитория мы должны войти в него, прежде чем мы сможем подтолкнуть наше новое изображение. Для этого мы запускаем команду ниже в бэктиках, чтобы Docker Login
Команда вызывается, как только Get-login
возврат.
$ `aws ecr get-login --no-include-email` WARNING! Using --password via the CLI is insecure. Use --password-stdin. Login Succeeded $ aws ecr describe-repositories { "repositories": [ { "registryId": "", "repositoryName": "sample-express-app", "repositoryArn": "arn:aws:ecr:us-west-2: :repository/infra-sampl-1ewaboppskux6", "createdAt": 1571007114.0, "repositoryUri": " .dkr.ecr.us-west-2.amazonaws.com/sample-express-app" } ] }
Теперь, когда мы все вошли в систему, мы можем пометить и подтолкнуть наше изображение в наш новый репозиторий ECR. Возьмите Repositoryuri
вашего репозитория из Описать-репозиторию
командовать выше. Мы собираемся использовать это в команде тега и Push ниже.
$ docker tag sample-express-app.dkr.ecr.us-west-2.amazonaws.com/sample-express-app $ docker push .dkr.ecr.us-west-2.amazonaws.com/sample-express-app 0574222c01c4: Pushed 28c9fa7f105e: Pushed 8942b63b65a1: Pushed b91230b492da: Pushed 6ad739b471d2: Pushed 954f92adc866: Pushed adca1e83b51a: Pushed 73982c948de0: Pushed 84d0c4b192e8: Pushed a637c551a0da: Pushed 2c8d31157b81: Pushed 7b76d801397d: Pushed f32868cde90b: Pushed 0db06dff9d9a: Pushed
Отлично, наше изображение Docker находится в нашем репозитории ECR. Теперь мы можем перейти к его развертыванию и запустить его через Elastic Container Service (ECS).
Настройка нашей инфраструктуры ECS
Прежде чем мы сможем запустить контейнер Docker в нашей учетной записи AWS, используя наше новое изображение, нам нужно для создания инфраструктуры, на которой он будет работать. Для этого поста в блоге мы сосредоточимся на запуске нашего контейнера в службе Elastic Container (ECS), предоставленной AWS.
ECS — это служба оркестровки контейнера, предоставляемая AWS. Он устраняет необходимость управления инфраструктурой, планированием и масштабированием для рабочих нагрузок в контейнер.
ECS состоит из трех основных терминов, которые важны для того, чтобы иметь в виду при размышлении о службе.
- Кластер: Это логическая группа базовых экземпляров EC2, на которых работают наши контейнеры. У нас нет доступа к этим случаям, и AWS управляет ими на наших
- Сервис: Длительный процесс, такой как веб-сервер или база данных, работает как служба в нашем кластере. Мы можем определить, сколько контейнеров должно работать для этой услуги.
- Определение задачи: Это определение нашего контейнера, который может работать на кластере индивидуально или через сервис. Когда в нашем кластере выполняется определение задачи, мы часто называем ее задачей, поэтому задача работающего контейнера в ECS.
Порядок этих определений также актуален. Мы можем думать о кластер Будучи самым низким уровнем сервиса, экземпляры EC2, на которых работают наши контейнеры. В то время как Задача это экземпляр нашего контейнера, работающего на одном или нескольких из этих экземпляров.
С этой терминологией в наших банках памяти давайте прыгнут на фактическое обеспечение нашей инфраструктуры. Мы собираемся обновить наш Infrastructure-stack.ts
иметь ресурсы, которые нам нужны для нашего кластера ECS. Во -первых, нам нужно добавить несколько других модулей.
$ npm install @aws-cdk/aws-ecs $ npm install @aws-cdk/aws-ec2 $ npm install @aws-cdk/aws-ecs-patterns
Теперь мы можем добавить ресурсы, которые нам нужны для нашего кластера, которые будут запускать наше новое изображение Docker. Наш Infrastructure-stack.ts
теперь должен выглядеть так.
import cdk = require('@aws-cdk/core'); import ecr = require('@aws-cdk/aws-ecr'); import ecs = require('@aws-cdk/aws-ecs'); import ec2 = require('@aws-cdk/aws-ec2'); import ecsPatterns = require('@aws-cdk/aws-ecs-patterns'); export class InfrastructureStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // ECR repository const repository = new ecr.Repository(this, 'sample-express-app', { repositoryName: 'sample-express-app' }); // ECS cluster/resources const cluster = new ecs.Cluster(this, 'app-cluster', { clusterName: 'app-cluster' }); cluster.addCapacity('app-scaling-group', { instanceType: new ec2.InstanceType("t2.micro"), desiredCapacity: 1 }); const loadBalancedService = new ecsPatterns.ApplicationLoadBalancedEc2Service(this, 'app-service', { cluster, memoryLimitMiB: 512, cpu: 5, desiredCount: 1, serviceName: 'sample-express-app', taskImageOptions: { image: ecs.ContainerImage.fromEcrRepository(repository), containerPort: 8080 }, publicLoadBalancer: true }); } }
Первое, что мы замечаем, это то, что мы сначала определяем наш кластер ECS, приложения-кластер
Анкет Далее нам нужно добавить экземпляр в наш кластер, Приложение-масштаб-группа
Анкет Это автоматическая группа t2.micro
Типы экземпляров, на которых могут работать наши контейнеры. Затем мы используем сбалансированную нагрузку шаблон обслуживания, предоставленный Ecspatterns
модуль.
Обратите внимание, что мы указываем нашу сервис ECS на изображение, размещенное в нашем репозитории ECR. Мы также устанавливаем Containerport
к 8080
Поскольку это порт, наше приложение Express работает внутри контейнера.
Этот шаблон создает общедоступный балансировщик нагрузки, который мы сможем позвонить из скручивание
или наш веб -браузер. Этот балансировщик нагрузки будет пересылать вызовы в наш контейнер в порту 8080
Бег внутри нашей услуги ECS.
Мы развертываем эти изменения через другое развернуть
командование На этот раз мы собираемся указать -Ревира-одобрение никогда не
так что нам не побуждают к изменениям IAM.
$ cdk deploy --require-approval never InfrastructureStack: deploying... InfrastructureStack: creating CloudFormation changeset... 0/46 | 16:41:46 | UPDATE_IN_PROGRESS | AWS::CloudFormation::Stack | InfrastructureStack User Initiated 0/46 | 16:42:07 | CREATE_IN_PROGRESS | AWS::EC2::EIP | app-cluster/Vpc/PublicSubnet2/EIP (appclusterVpcPublicSubnet2EIPD0A381A3) 0/46 | 16:42:07 | CREATE_IN_PROGRESS | AWS::ECS::Cluster | app-cluster (appclusterD09F8E40) 0/46 | 16:42:07 | CREATE_IN_PROGRESS | AWS::EC2::InternetGateway | app-cluster/Vpc/IGW (appclusterVpcIGW17A11835) 0/46 | 16:42:07 | CREATE_IN_PROGRESS | AWS::EC2::EIP | app-cluster/Vpc/PublicSubnet1/EIP (appclusterVpcPublicSubnet1EIP791F54CD) ... .... ..... 44/46 | 16:46:04 | CREATE_COMPLETE | AWS::Lambda::Permission | app-cluster/DefaultAutoScalingGroup/DrainECSHook/Function/AllowInvoke:InfrastructureStackappclusterDefaultAutoScalingGroupLifecycleHookDrainHookTopic2C88B6D3 (appclusterDefaultAutoScalingGroupDrainECSHookFunctionAllowInvokeInfrastructureStackappclusterDefaultAutoScalingGroupLifecycleHookDrainHookTopic2C88B6D3036C2EFB) 45/46 | 16:46:33 | CREATE_COMPLETE | AWS::ECS::Service | app-service/Service (appserviceServiceA5AB3AA1) 45/46 | 16:46:37 | UPDATE_COMPLETE_CLEA | AWS::CloudFormation::Stack | InfrastructureStack 46/46 | 16:46:38 | UPDATE_COMPLETE | AWS::CloudFormation::Stack | InfrastructureStack Outputs: InfrastructureStack.appserviceLoadBalancerDNS0A615BF5 = Infra-appse-187228PB273DW-1700265048.us-west-2.elb.amazonaws.com InfrastructureStack.appserviceServiceURL90EC0456 = http://Infra-appse-187228PB273DW-1700265048.us-west-2.elb.amazonaws.com
Используя модуль AWS CDK для службы эластичных контейнеров, мы создали все ресурсы, необходимые для нашего нового кластера. Как вы можете видеть из вывода, от нашего имени был создан новый VPC с соответствующими подсетями. Это хорошее преимущество такого инструмента, как CDK, он создал разумные значения по умолчанию для нашего нового кластера, не нуждаясь в их указании.
Теперь мы должны увидеть, что мы создали новый кластер ECS с нашим сервисом, выполняя нашу текущую определение задачи. CDK помог нам, выпустив URL -адрес нашего балансировщика нагрузки. Давайте возьмем этот URL и проверем, что наш контейнер работает и принимает трафик, нажимая на этот URL через Curl.
$ curl Infra-appse-187228PB273DW-1700265048.us-west-2.elb.amazonaws.com Sample Endpoint
Куда пойти отсюда
Теперь, когда наш первоначальный контейнер работает в нашем кластере ECS, мы можем сделать шаг назад и исследовать, куда мы можем пойти отсюда.
Наше определение задачи ECS в настоящее время настроено на то, чтобы указать на Последний
Тег изображения Docker, которое мы публикуем. Это означает, что мы можем обновить наше изображение, и изменения могут быть введены в наш кластер. Давайте обновим ответ, который мы возвращаем для нашего API.
api.get('/', (req, res) => { res.send('New Response\n'); });
Теперь давайте создадим и раздвинут новую версию нашего изображения Docker.
$ docker build -t sample-express-app . $ `aws ecr get-login --no-include-email` $ docker tag sample-express-app.dkr.ecr.us-west-2.amazonaws.com/sample-express-app:latest $ docker push .dkr.ecr.us-west-2.amazonaws.com/sample-express-app:latest 9a7704a19307: Pushed 03a86aeeb52b: Layer already exists c14651828ff6: Layer already exists 4ecb552d7aff: Layer already exists 6ad739b471d2: Layer already exists 954f92adc866: Layer already exists adca1e83b51a: Layer already exists 73982c948de0: Layer already exists 84d0c4b192e8: Layer already exists a637c551a0da: Layer already exists 2c8d31157b81: Layer already exists 7b76d801397d: Layer already exists f32868cde90b: Layer already exists 0db06dff9d9a: Layer already exists latest: digest: sha256:ed82982bfa5fe6333c4b67afaae0f36e3208a588736c9586ff81dbdd7e1bc0f5 size: 3256
Теперь у нас есть новая версия нашего изображения, поднятая в нашем репозитории. Но он не был развернут в нашем сервисе, работающем в нашем кластере. Чтобы поднять изменение в нашем кластере, нам нужно перезапустить сервис, чтобы он потянул Последний
тег нашего изображения.
К счастью, мы можем сделать это с одним вызовом AWS CLI из нашей командной строки.
$ aws ecs update-service --force-new-deployment --cluster app-cluster --service sample-express-app
После того, как наше новое изображение выйдет в службу (что может занять несколько минут), мы можем Curl
Наша конечная точка снова и увидите наш новый ответ.
$ curl Infra-appse-187228PB273DW-1700265048.us-west-2.elb.amazonaws.com New Response
Вывод
🙌 Теперь мы проходили полное упражнение по созданию изображения Docker, обеспечивая кластер ECS и запустив наше изображение в нашем кластере. Мы даже продемонстрировали, как мы можем обновить наше изображение и развернуть новые версии в нашу службу работы.
Есть много направлений, которые вы могли бы пойти дальше. Следующим уровнем для DevOps будет настроить конвейер CI/CD, который позволяет вам постоянно развернуть ваши новые изображения в свой кластер ECS. У меня есть сообщение в блоге, которое фокусируется на Создание изображений Docker с помощью AWS Codepipeline и Codebuild Чтобы начать вас.
Оттуда, возможно, стоит сократить время развертывания при запуске нового изображения в нашем кластере ECS. Причина, по которой это не является мгновенной, заключается в том, что балансировщик нагрузки, связанный с нашим сервисом, включает в себя дренирование подключения. Это позволяет нам постепенно развернуть новые версии в нашем сервисе, не сразу не сдавая нашу существующую услугу. Это идеально подходит для незаметного развертывания, но это означает, что наше время развертывания занимает немного больше времени.
Хотите проверить другие мои проекты?
Я большой поклонник сообщества разработчиков. Если у вас есть какие -либо вопросы или вы хотите поговорить о различных идеях, касающихся рефакторинга, Обратитесь в Twitter или бросить комментарий ниже.
Вне блогов я создал Учитесь AWS, используя его курс Анкет В курсе мы сосредоточены на изучении веб -сервисов Amazon, фактически используя его для размещения, защиты и доставки статических веб -сайтов. Это простая проблема со многими решениями, но она идеально подходит для наращивания вашего понимания AWS. Недавно я добавил две новые бонусные главы к курсу, которые сосредоточены на инфраструктуре в качестве кода и непрерывного развертывания.
Я также курирую свою собственную еженедельную рассылку. Учитесь, делая информационный бюллетень Полно заполнено удивительным облаком, кодированием и DevOps каждую неделю. Зарегистрируйтесь, чтобы получить его в своем почтовом ящике.
Оригинал: «https://dev.to/kylegalbraith/how-to-run-docker-containers-via-aws-elastic-container-service-p47»