").addClass(l.className).css({position:"absolute","z-index":-1,top:0,left:0,bottom:0,right:0,overflow:"hidden","-webkit-background-size":"cover","-moz-background-size":"cover","-o-background-size":"cover","background-size":"cover","background-color":l.bgColor,"background-repeat":"no-repeat","background-position":m.x+" "+m.y}),"object"==typeof g&&(g.poster?i=g.poster:g.mp4?i=g.mp4:g.webm?i=g.webm:g.ogv&&(i=g.ogv)),"detect"===n?d(i,function(a){e.css("background-image","url("+a+")")}):"none"!==n&&e.css("background-image","url("+i+"."+n+")"),"static"===k.css("position")&&k.css("position","relative"),k.prepend(e),"object"==typeof g?(g.mp4&&(j+=''),g.webm&&(j+=''),g.ogv&&(j+=''),b=f.$video=a("")):b=f.$video=a('');try{b.prop({autoplay:l.autoplay,loop:l.loop,volume:l.volume,muted:l.muted,defaultMuted:l.muted,playbackRate:l.playbackRate,defaultPlaybackRate:l.playbackRate})}catch(o){throw new Error(h)}b.css({margin:"auto",position:"absolute","z-index":-1,top:m.y,left:m.x,"-webkit-transform":"translate(-"+m.x+", -"+m.y+")","-ms-transform":"translate(-"+m.x+", -"+m.y+")","-moz-transform":"translate(-"+m.x+", -"+m.y+")",transform:"translate(-"+m.x+", -"+m.y+")",visibility:"hidden",opacity:0}).one("canplaythrough.vide",function(){f.resize()}).one("playing.vide",function(){b.css({visibility:"visible",opacity:1}),e.css("background-image","none")}),k.on("resize.vide",function(){l.resizing&&f.resize()}),e.append(b)},e.prototype.getVideoObject=function(){return this.$video[0]},e.prototype.resize=function(){if(this.$video){var a=this.$wrapper,b=this.$video,c=b[0],d=c.videoHeight,e=c.videoWidth,f=a.height(),g=a.width();g/e>f/d?b.css({width:g+2,height:"auto"}):b.css({width:"auto",height:f+2})}},e.prototype.destroy=function(){delete a[f].lookup[this.index],this.$video&&this.$video.off(f),this.$element.off(f).removeData(f),this.$wrapper.remove()},a[f]={lookup:[]},a.fn[f]=function(b,c){var d;return this.each(function(){d=a.data(this,f),d&&d.destroy(),d=new e(this,b,c),d.index=a[f].lookup.push(d)-1,a.data(this,f,d)}),this},a(document).ready(function(){var b=a(window);b.on("resize.vide",function(){for(var b,c=a[f].lookup.length,d=0;d NOTE: If you are running this workshop on a large group of people, you can optionally create just one VPC for the entire workshop, instead of one VPC per workshop participant. This is just to prevent you hitting some VPC limits for your AWS account, like number of VPCs per region and number of Elastic IPs per region.
30 |
31 | 
32 |
33 | ## 3. Infrastructure Setup (with Cloud9)
34 |
35 | In order to deploy the infrastructure to your account, you can use one of the following links according to the region you with to use. These are the regions that currently support Fargate and Cloud9.
36 |
37 | |Deploy | Region |
38 | |:---:|:---:|
39 | |[][us-east-1-with-cloud9] | US East (N. Virginia)|
40 | |[][us-east-2-with-cloud9] | US East (Ohio)|
41 | |[][us-west-2-with-cloud9] | US West (Oregon)|
42 | |[][eu-west-1-with-cloud9] | EU (Ireland)|
43 | |[][ap-southeast-1-with-cloud9] | Asia Pacific (Singapore)|
44 |
45 | In the CloudFormation screen, add your name under the resource naming. This is going to add your name in front of the names to all the resources created, so in case you are running the workshop with someone else in the same account, you will be able to know your resources.
46 |
47 | Wait till the status of the stack be changed to `CREATE_COMPLETE`, click in the **Outputs** tab and take note of all the values in the **Value** colunm. If you are using the template that provision a Cloud9 instance, you will have the `Cloud9URL` option. You can click in this URL to access your Cloud9 instance:
48 |
49 | 
50 |
51 | ## 4. Understanding the Cloud9 Interface
52 |
53 | AWS Cloud9 is a cloud-based integrated development environment (IDE) that lets you write, run, and debug your code with just a browser. During this workshop, we will be using Cloud9 to interact with the application code and Docker containers. Since Cloud9 has everything that we need to run the workshop, let's now take a moment to understand where we will be running our commands and executing the steps.
54 |
55 | This is the main interface presented by Cloud9 and the first thing you will see when clicking in the CloudFormation output URL:
56 |
57 | 
58 |
59 | All the commands presented in the workshop, such as `docker build`, `aws ecr get-login` and so on, should be executed in the terminal window:
60 |
61 | 
62 |
63 | >NOTE: You can arrange the size of the windows inside the Cloud9 interface.
64 |
65 | On the left side of the screen, you will have a list of all files:
66 |
67 | 
68 |
69 | On the top window, you have a text editor, where you can make all the changes in the files. If you just click twice in any file on the *files** menu, you will be able to edit it:
70 |
71 | 
72 |
73 | ## 5. Cloning the workshop repository
74 |
75 | In order to clone this repository, you can use the following command:
76 |
77 | $ git clone https://github.com/bemer/containers-on-aws-workshop.git
78 |
79 | After cloning the repository, you will see that a new folder called `containers-on-aws-workshop` will be created. All the content will be available inside this folder.
80 |
81 | After provisioning the infrastructure and cloning the repository within your Cloud9 environment, you can go to the next chapter: [2. Creating your Docker image](/02-CreatingDockerImage).
82 |
83 |
84 |
85 | [][continue-workshop]
86 |
87 |
88 |
89 | ## 6. Running on your own computer
90 |
91 | We strongly recommend you to run this workshop using the Cloud9 provided interface, but it is also possible to run this workshop using your own computer instead of Cloud9 environment.
92 |
93 | The following steps are needed if you want to run this workshop in your own computer.
94 |
95 | >NOTE: If you will be using the Cloud9 interface and have done the steps above, please go to the next chapter.
96 |
97 | ### 6.1 Hardware & Software
98 |
99 | - Memory: At least 4 GB+, strongly preferred 8 GB
100 | - Operating System: Mac OS X (10.10.3+), Windows 10 Pro+ 64-bit, Ubuntu 12+, CentOS 7+.
101 |
102 | > NOTE: An older version of the operating system may be used. The installation instructions would differ slightly in that case and are explained in the next section.
103 |
104 | ### 6.2 Install Docker
105 |
106 | Docker runs natively on Mac, Windows and Linux. This lab will use [Docker Community Edition - CE](https://www.docker.com/community-edition). This documentation will cover the Docker CE install process in an EC2 instance running `Amazon Linux`. If you want to use it in your own desktop, please follow the sptes in the [Docker CE official downloads page](https://www.docker.com/community-edition#/download).
107 |
108 | > NOTE: Docker CE requires a fairly recent operating system version. If your machine does not meet the requirements, then you need to install https://www.docker.com/products/docker-toolbox (Docker Toolbox).
109 |
110 | ### 6.3 Install AWS CLI
111 |
112 | During this workshop we will interact with some AWS API's. Having the latest version of the AWS CLI in your computer is appropriated.
113 |
114 | Instructions to install the AWS CLI are available here: http://docs.aws.amazon.com/cli/latest/userguide/installing.html
115 |
116 |
117 | ### 6.4 Install git
118 |
119 | To better execute the workshop, you will need to clone this repository and having `git` installed is needed to perform this action.
120 |
121 | Download and install here: https://git-scm.com/downloads
122 | You can have more information about git here: https://git-scm.com/book/en/v1/Getting-Started
123 |
124 |
125 | ### 6.5 Installing Docker on an EC2 instance running Amazon Linux
126 |
127 | If you don't want to use a Cloud9 environment and don't have a Linux computer, you can also use an EC2 instance to run the steps in this workshop.
128 |
129 | After launching and accessing your EC2 instance, you will need to install the Docker components in order to interact with the Docker daemon to create, run and push your images. On your EC2 instance, run the following commands:
130 |
131 | $ sudo yum update -y
132 | $ sudo yum install -y docker
133 |
134 | This will install the Docker on your instance. Now, to check if your installation was successfully completed, run the following command:
135 |
136 | $ docker -v
137 |
138 | The output should look like:
139 |
140 | Docker version 17.12.0-ce, build 3dfb8343b139d6342acfd9975d7f1068b5b1c3d3
141 |
142 | Now, you need to start the Docker service. You can do this by running the command:
143 |
144 | $ sudo service docker start
145 |
146 | The next step is add your linux user to the `docker` users group, so you will be able to run all the Docker commands without being root. Run the following command:
147 |
148 | $ sudo usermod -a -G docker $USER
149 |
150 | After running this command, you will need to log out and log in again in your instance. When logging in again, run the following command to see if you are able to run a Docker container:
151 |
152 | $ docker run hello-world
153 |
154 | The output should look like:
155 |
156 | Hello from Docker!
157 | This message shows that your installation appears to be working correctly.
158 |
159 | To generate this message, Docker took the following steps:
160 | 1. The Docker client contacted the Docker daemon.
161 | 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
162 | (amd64)
163 | 3. The Docker daemon created a new container from that image which runs the
164 | executable that produces the output you are currently reading.
165 | 4. The Docker daemon streamed that output to the Docker client, which sent it
166 | to your terminal.
167 |
168 | To try something more ambitious, you can run an Ubuntu container with:
169 | $ docker run -it ubuntu bash
170 |
171 | Share images, automate workflows, and more with a free Docker ID:
172 | https://cloud.docker.com/
173 |
174 | For more examples and ideas, visit:mM
175 | https://docs.docker.com/engine/userguide/
176 |
177 | ### 6.6 Creating the VPC
178 |
179 | After completing the setup of your computer, you must create the VPC infrastrutcture in order to execute your containers. You can do this by using one of the templates below, according to the region you are using:
180 |
181 | | Deploy | Region |
182 | |:---:|:---:|
183 | |[][us-east-1-without-cloud9] | US East (N. Virginia)|
184 | |[][us-east-2-without-cloud9] | US East (Ohio)|
185 | |[][us-west-2-without-cloud9] | US West (Oregon)|
186 | |[][eu-west-1-without-cloud9] | EU (Ireland)|
187 | |[][ap-southeast-1-without-cloud9] | Asia Pacific (Singapore)|
188 |
189 |
190 | ### 6.7 Cloning the workshop repository
191 |
192 | In order to clone this repository, you can use the following command:
193 |
194 | $ git clone https://github.com/bemer/containers-on-aws-workshop.git
195 |
196 | After cloning the repository, you will see that a new folder called `containers-on-aws-workshop` will be created. All the content will be available inside this folder.
197 |
198 |
199 |
200 | [][back-to-menu] [][continue-workshop]
201 |
202 | [back-to-menu]: https://github.com/bemer/containers-on-aws-workshop
203 | [continue-workshop]: /02-CreatingDockerImage
204 |
205 | [us-east-1-with-cloud9]: https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=containers-workshop-insfrastructure&templateURL=https://s3.amazonaws.com/containers-on-aws-workshop-vpc/containers-workshop-with-cloud9.yaml
206 | [us-east-2-with-cloud9]: https://console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks/new?stackName=containers-workshop-insfrastructure&templateURL=https://s3.amazonaws.com/containers-on-aws-workshop-vpc/containers-workshop-with-cloud9.yaml
207 | [us-west-2-with-cloud9]: https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?stackName=containers-workshop-insfrastructure&templateURL=https://s3.amazonaws.com/containers-on-aws-workshop-vpc/containers-workshop-with-cloud9.yaml
208 | [eu-west-1-with-cloud9]: https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?stackName=containers-workshop-insfrastructure&templateURL=https://s3.amazonaws.com/containers-on-aws-workshop-vpc/containers-workshop-with-cloud9.yaml
209 | [ap-southeast-1-with-cloud9]: https://console.aws.amazon.com/cloudformation/home?region=ap-southeast-1#/stacks/new?stackName=containers-workshop-insfrastructure&templateURL=https://s3.amazonaws.com/containers-on-aws-workshop-vpc/containers-workshop-with-cloud9.yaml
210 | [us-east-1-without-cloud9]: https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=containers-workshop-insfrastructure&templateURL=https://s3.amazonaws.com/containers-on-aws-workshop-vpc/containers-workshop-without-cloud9.yaml
211 | [us-east-2-without-cloud9]: https://console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks/new?stackName=containers-workshop-insfrastructure&templateURL=https://s3.amazonaws.com/containers-on-aws-workshop-vpc/containers-workshop-without-cloud9.yaml
212 | [us-west-2-without-cloud9]: https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?stackName=containers-workshop-insfrastructure&templateURL=https://s3.amazonaws.com/containers-on-aws-workshop-vpc/containers-workshop-without-cloud9.yaml
213 | [eu-west-1-without-cloud9]: https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?stackName=containers-workshop-insfrastructure&templateURL=https://s3.amazonaws.com/containers-on-aws-workshop-vpc/containers-workshop-without-cloud9.yaml
214 | [ap-southeast-1-without-cloud9]: https://console.aws.amazon.com/cloudformation/home?region=ap-southeast-1#/stacks/new?stackName=containers-workshop-insfrastructure&templateURL=https://s3.amazonaws.com/containers-on-aws-workshop-vpc/containers-workshop-without-cloud9.yaml
215 |
--------------------------------------------------------------------------------
/01-EnvironmentSetup/cloudformation/containers-workshop-with-cloud9.yaml:
--------------------------------------------------------------------------------
1 | Description:
2 | This template deploys a VPC, with a pair of public and private subnets spread across two Availability Zones. It deploys an Internet Gateway, with a default route on the public subnets. It deploys a pair of NAT Gateways (one in each AZ), and default routes for them in the private subnets. It also deploys a Cloud9 instance in the Public Subnet (AZ1).
3 |
4 |
5 | Metadata:
6 | AWS::CloudFormation::Interface:
7 | ParameterGroups:
8 | -
9 | Label:
10 | default: "Resource Naming"
11 | Parameters:
12 | - EnvironmentName
13 | -
14 | Label:
15 | default: "Network Configurations"
16 | Parameters:
17 | - VpcCIDR
18 | - PublicSubnet1CIDR
19 | - PublicSubnet2CIDR
20 | - PrivateSubnet1CIDR
21 | - PrivateSubnet2CIDR
22 |
23 | ParameterLabels:
24 | EnvironmentName:
25 | default: Add your name here
26 | VpcCIDR:
27 | default: IP range for the new VPC
28 | PublicSubnet1CIDR:
29 | default: IP range for the first public subnet
30 | PublicSubnet2CIDR:
31 | default: IP range for the second public subnet
32 | PrivateSubnet1CIDR:
33 | default: IP range for the first private subnet
34 | PrivateSubnet2CIDR:
35 | default: IP range for the second private subnet
36 |
37 |
38 | Parameters:
39 |
40 | EnvironmentName:
41 | Description: This name will be prefixed to resource names and will make easier for you to know what are your resources.
42 | Type: String
43 | AllowedPattern : ".+"
44 |
45 | VpcCIDR:
46 | Description: Please enter the IP range (CIDR notation) for this VPC.
47 | Type: String
48 | Default: 10.192.0.0/16
49 |
50 | PublicSubnet1CIDR:
51 | Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone.
52 | Type: String
53 | Default: 10.192.10.0/24
54 |
55 | PublicSubnet2CIDR:
56 | Description: Please enter the IP range (CIDR notation) for the public subnet in the second Availability Zone.
57 | Type: String
58 | Default: 10.192.11.0/24
59 |
60 | PrivateSubnet1CIDR:
61 | Description: Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone.
62 | Type: String
63 | Default: 10.192.20.0/24
64 |
65 | PrivateSubnet2CIDR:
66 | Description: Please enter the IP range (CIDR notation) for the private subnet in the second Availability Zone.
67 | Type: String
68 | Default: 10.192.21.0/24
69 |
70 | Resources:
71 |
72 | VPC:
73 | Type: AWS::EC2::VPC
74 | Properties:
75 | EnableDnsHostnames: 'true'
76 | CidrBlock: !Ref VpcCIDR
77 | Tags:
78 | - Key: Name
79 | Value: !Sub ${EnvironmentName}-containers-workshop-vpc
80 |
81 | InternetGateway:
82 | Type: AWS::EC2::InternetGateway
83 | Properties:
84 | Tags:
85 | - Key: Name
86 | Value: !Sub ${EnvironmentName}-containers-workshop-vpc-ig
87 |
88 | InternetGatewayAttachment:
89 | Type: AWS::EC2::VPCGatewayAttachment
90 | Properties:
91 | InternetGatewayId: !Ref InternetGateway
92 | VpcId: !Ref VPC
93 |
94 | PublicSubnet1:
95 | Type: AWS::EC2::Subnet
96 | Properties:
97 | VpcId: !Ref VPC
98 | AvailabilityZone: !Select [ 0, !GetAZs '' ]
99 | CidrBlock: !Ref PublicSubnet1CIDR
100 | MapPublicIpOnLaunch: true
101 | Tags:
102 | - Key: Name
103 | Value: !Sub ${EnvironmentName}-containers-workshop-public-subnet-az1
104 |
105 | PublicSubnet2:
106 | Type: AWS::EC2::Subnet
107 | Properties:
108 | VpcId: !Ref VPC
109 | AvailabilityZone: !Select [ 1, !GetAZs '' ]
110 | CidrBlock: !Ref PublicSubnet2CIDR
111 | MapPublicIpOnLaunch: true
112 | Tags:
113 | - Key: Name
114 | Value: !Sub ${EnvironmentName}-containers-workshop-public-subnet-az2
115 |
116 | PrivateSubnet1:
117 | Type: AWS::EC2::Subnet
118 | Properties:
119 | VpcId: !Ref VPC
120 | AvailabilityZone: !Select [ 0, !GetAZs '' ]
121 | CidrBlock: !Ref PrivateSubnet1CIDR
122 | MapPublicIpOnLaunch: false
123 | Tags:
124 | - Key: Name
125 | Value: !Sub ${EnvironmentName}-containers-workshop-private-subnet-az1
126 |
127 | PrivateSubnet2:
128 | Type: AWS::EC2::Subnet
129 | Properties:
130 | VpcId: !Ref VPC
131 | AvailabilityZone: !Select [ 1, !GetAZs '' ]
132 | CidrBlock: !Ref PrivateSubnet2CIDR
133 | MapPublicIpOnLaunch: false
134 | Tags:
135 | - Key: Name
136 | Value: !Sub ${EnvironmentName}-containers-workshop-private-subnet-az2
137 |
138 | NatGateway1EIP:
139 | Type: AWS::EC2::EIP
140 | DependsOn: InternetGatewayAttachment
141 | Properties:
142 | Domain: vpc
143 |
144 | NatGateway2EIP:
145 | Type: AWS::EC2::EIP
146 | DependsOn: InternetGatewayAttachment
147 | Properties:
148 | Domain: vpc
149 |
150 | NatGateway1:
151 | Type: AWS::EC2::NatGateway
152 | Properties:
153 | AllocationId: !GetAtt NatGateway1EIP.AllocationId
154 | SubnetId: !Ref PublicSubnet1
155 |
156 | NatGateway2:
157 | Type: AWS::EC2::NatGateway
158 | Properties:
159 | AllocationId: !GetAtt NatGateway2EIP.AllocationId
160 | SubnetId: !Ref PublicSubnet2
161 |
162 | PublicRouteTable:
163 | Type: AWS::EC2::RouteTable
164 | Properties:
165 | VpcId: !Ref VPC
166 | Tags:
167 | - Key: Name
168 | Value: !Sub ${EnvironmentName}-containers-workshop-public-routes
169 |
170 | DefaultPublicRoute:
171 | Type: AWS::EC2::Route
172 | DependsOn: InternetGatewayAttachment
173 | Properties:
174 | RouteTableId: !Ref PublicRouteTable
175 | DestinationCidrBlock: 0.0.0.0/0
176 | GatewayId: !Ref InternetGateway
177 |
178 | PublicSubnet1RouteTableAssociation:
179 | Type: AWS::EC2::SubnetRouteTableAssociation
180 | Properties:
181 | RouteTableId: !Ref PublicRouteTable
182 | SubnetId: !Ref PublicSubnet1
183 |
184 | PublicSubnet2RouteTableAssociation:
185 | Type: AWS::EC2::SubnetRouteTableAssociation
186 | Properties:
187 | RouteTableId: !Ref PublicRouteTable
188 | SubnetId: !Ref PublicSubnet2
189 |
190 |
191 | PrivateRouteTable1:
192 | Type: AWS::EC2::RouteTable
193 | Properties:
194 | VpcId: !Ref VPC
195 | Tags:
196 | - Key: Name
197 | Value: !Sub ${EnvironmentName}-containers-workshop-private-routes-az1
198 | DefaultPrivateRoute1:
199 | Type: AWS::EC2::Route
200 | Properties:
201 | RouteTableId: !Ref PrivateRouteTable1
202 | DestinationCidrBlock: 0.0.0.0/0
203 | NatGatewayId: !Ref NatGateway1
204 | PrivateSubnet1RouteTableAssociation:
205 | Type: AWS::EC2::SubnetRouteTableAssociation
206 | Properties:
207 | RouteTableId: !Ref PrivateRouteTable1
208 | SubnetId: !Ref PrivateSubnet1
209 | PrivateRouteTable2:
210 | Type: AWS::EC2::RouteTable
211 | Properties:
212 | VpcId: !Ref VPC
213 | Tags:
214 | - Key: Name
215 | Value: !Sub ${EnvironmentName}-containers-workshop-private-routes-az2
216 | DefaultPrivateRoute2:
217 | Type: AWS::EC2::Route
218 | Properties:
219 | RouteTableId: !Ref PrivateRouteTable2
220 | DestinationCidrBlock: 0.0.0.0/0
221 | NatGatewayId: !Ref NatGateway2
222 | PrivateSubnet2RouteTableAssociation:
223 | Type: AWS::EC2::SubnetRouteTableAssociation
224 | Properties:
225 | RouteTableId: !Ref PrivateRouteTable2
226 | SubnetId: !Ref PrivateSubnet2
227 | NoIngressSecurityGroup:
228 | Type: AWS::EC2::SecurityGroup
229 | Properties:
230 | GroupName: "no-ingress-sg"
231 | GroupDescription: "Security group with no ingress rule"
232 | VpcId: !Ref VPC
233 | Cloud9Instance:
234 | Type: AWS::Cloud9::EnvironmentEC2
235 | Properties:
236 | Description: Cloud9 environment created for the Containers on AWS workshop.
237 | AutomaticStopTimeMinutes: 15
238 | InstanceType: t2.small
239 | Name: !Sub ${EnvironmentName}-containers-workshop-cloud9-instance
240 | SubnetId: !Ref PublicSubnet1
241 | DependsOn: PublicSubnet1
242 |
243 | Outputs:
244 | Cloud9URL:
245 | Description: URL used to access the Cloud9 environment
246 | Value: !Join [ "", ["https://", !Ref "AWS::Region", ".console.aws.amazon.com/cloud9/ide/", !Ref "Cloud9Instance", "?region=", !Ref "AWS::Region"] ]
247 | Subnet:
248 | Description: A public subnet where the load generator instance will be placed.
249 | Value: !Ref PublicSubnet1
250 | Export:
251 | Name: containers-workshop-public-subnet
252 | VPC:
253 | Description: The VPC created to the workshop.
254 | Value: !Ref VPC
255 | Export:
256 | Name: containers-workshop-vpc
257 |
--------------------------------------------------------------------------------
/01-EnvironmentSetup/cloudformation/containers-workshop-without-cloud9.yaml:
--------------------------------------------------------------------------------
1 | Description:
2 | This template deploys a VPC, with a pair of public and private subnets spread across two Availability Zones. It deploys an Internet Gateway, with a default route on the public subnets. It deploys a pair of NAT Gateways (one in each AZ), and default routes for them in the private subnets. It also deploys a Cloud9 instance in the Public Subnet (AZ1).
3 |
4 |
5 | Metadata:
6 | AWS::CloudFormation::Interface:
7 | ParameterGroups:
8 | -
9 | Label:
10 | default: "Resource Naming"
11 | Parameters:
12 | - EnvironmentName
13 | -
14 | Label:
15 | default: "Network Configurations"
16 | Parameters:
17 | - VpcCIDR
18 | - PublicSubnet1CIDR
19 | - PublicSubnet2CIDR
20 | - PrivateSubnet1CIDR
21 | - PrivateSubnet2CIDR
22 |
23 | ParameterLabels:
24 | EnvironmentName:
25 | default: Add your name here
26 | VpcCIDR:
27 | default: IP range for the new VPC
28 | PublicSubnet1CIDR:
29 | default: IP range for the first public subnet
30 | PublicSubnet2CIDR:
31 | default: IP range for the second public subnet
32 | PrivateSubnet1CIDR:
33 | default: IP range for the first private subnet
34 | PrivateSubnet2CIDR:
35 | default: IP range for the second private subnet
36 |
37 |
38 | Parameters:
39 |
40 | EnvironmentName:
41 | Description: This name will be prefixed to resource names and will make easier for you to know what are your resources.
42 | Type: String
43 | AllowedPattern : ".+"
44 |
45 | VpcCIDR:
46 | Description: Please enter the IP range (CIDR notation) for this VPC.
47 | Type: String
48 | Default: 10.192.0.0/16
49 |
50 | PublicSubnet1CIDR:
51 | Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone.
52 | Type: String
53 | Default: 10.192.10.0/24
54 |
55 | PublicSubnet2CIDR:
56 | Description: Please enter the IP range (CIDR notation) for the public subnet in the second Availability Zone.
57 | Type: String
58 | Default: 10.192.11.0/24
59 |
60 | PrivateSubnet1CIDR:
61 | Description: Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone.
62 | Type: String
63 | Default: 10.192.20.0/24
64 |
65 | PrivateSubnet2CIDR:
66 | Description: Please enter the IP range (CIDR notation) for the private subnet in the second Availability Zone.
67 | Type: String
68 | Default: 10.192.21.0/24
69 |
70 | Resources:
71 |
72 | VPC:
73 | Type: AWS::EC2::VPC
74 | Properties:
75 | EnableDnsHostnames: 'true'
76 | CidrBlock: !Ref VpcCIDR
77 | Tags:
78 | - Key: Name
79 | Value: !Sub ${EnvironmentName}-containers-workshop-vpc
80 |
81 | InternetGateway:
82 | Type: AWS::EC2::InternetGateway
83 | Properties:
84 | Tags:
85 | - Key: Name
86 | Value: !Sub ${EnvironmentName}-containers-workshop-vpc-ig
87 |
88 | InternetGatewayAttachment:
89 | Type: AWS::EC2::VPCGatewayAttachment
90 | Properties:
91 | InternetGatewayId: !Ref InternetGateway
92 | VpcId: !Ref VPC
93 |
94 | PublicSubnet1:
95 | Type: AWS::EC2::Subnet
96 | Properties:
97 | VpcId: !Ref VPC
98 | AvailabilityZone: !Select [ 0, !GetAZs '' ]
99 | CidrBlock: !Ref PublicSubnet1CIDR
100 | MapPublicIpOnLaunch: true
101 | Tags:
102 | - Key: Name
103 | Value: !Sub ${EnvironmentName}-containers-workshop-public-subnet-az1
104 |
105 | PublicSubnet2:
106 | Type: AWS::EC2::Subnet
107 | Properties:
108 | VpcId: !Ref VPC
109 | AvailabilityZone: !Select [ 1, !GetAZs '' ]
110 | CidrBlock: !Ref PublicSubnet2CIDR
111 | MapPublicIpOnLaunch: true
112 | Tags:
113 | - Key: Name
114 | Value: !Sub ${EnvironmentName}-containers-workshop-public-subnet-az2
115 |
116 | PrivateSubnet1:
117 | Type: AWS::EC2::Subnet
118 | Properties:
119 | VpcId: !Ref VPC
120 | AvailabilityZone: !Select [ 0, !GetAZs '' ]
121 | CidrBlock: !Ref PrivateSubnet1CIDR
122 | MapPublicIpOnLaunch: false
123 | Tags:
124 | - Key: Name
125 | Value: !Sub ${EnvironmentName}-containers-workshop-private-subnet-az1
126 |
127 | PrivateSubnet2:
128 | Type: AWS::EC2::Subnet
129 | Properties:
130 | VpcId: !Ref VPC
131 | AvailabilityZone: !Select [ 1, !GetAZs '' ]
132 | CidrBlock: !Ref PrivateSubnet2CIDR
133 | MapPublicIpOnLaunch: false
134 | Tags:
135 | - Key: Name
136 | Value: !Sub ${EnvironmentName}-containers-workshop-private-subnet-az2
137 |
138 | NatGateway1EIP:
139 | Type: AWS::EC2::EIP
140 | DependsOn: InternetGatewayAttachment
141 | Properties:
142 | Domain: vpc
143 |
144 | NatGateway2EIP:
145 | Type: AWS::EC2::EIP
146 | DependsOn: InternetGatewayAttachment
147 | Properties:
148 | Domain: vpc
149 |
150 | NatGateway1:
151 | Type: AWS::EC2::NatGateway
152 | Properties:
153 | AllocationId: !GetAtt NatGateway1EIP.AllocationId
154 | SubnetId: !Ref PublicSubnet1
155 |
156 | NatGateway2:
157 | Type: AWS::EC2::NatGateway
158 | Properties:
159 | AllocationId: !GetAtt NatGateway2EIP.AllocationId
160 | SubnetId: !Ref PublicSubnet2
161 |
162 | PublicRouteTable:
163 | Type: AWS::EC2::RouteTable
164 | Properties:
165 | VpcId: !Ref VPC
166 | Tags:
167 | - Key: Name
168 | Value: !Sub ${EnvironmentName}-containers-workshop-public-routes
169 |
170 | DefaultPublicRoute:
171 | Type: AWS::EC2::Route
172 | DependsOn: InternetGatewayAttachment
173 | Properties:
174 | RouteTableId: !Ref PublicRouteTable
175 | DestinationCidrBlock: 0.0.0.0/0
176 | GatewayId: !Ref InternetGateway
177 |
178 | PublicSubnet1RouteTableAssociation:
179 | Type: AWS::EC2::SubnetRouteTableAssociation
180 | Properties:
181 | RouteTableId: !Ref PublicRouteTable
182 | SubnetId: !Ref PublicSubnet1
183 |
184 | PublicSubnet2RouteTableAssociation:
185 | Type: AWS::EC2::SubnetRouteTableAssociation
186 | Properties:
187 | RouteTableId: !Ref PublicRouteTable
188 | SubnetId: !Ref PublicSubnet2
189 |
190 |
191 | PrivateRouteTable1:
192 | Type: AWS::EC2::RouteTable
193 | Properties:
194 | VpcId: !Ref VPC
195 | Tags:
196 | - Key: Name
197 | Value: !Sub ${EnvironmentName}-containers-workshop-private-routes-az1
198 | DefaultPrivateRoute1:
199 | Type: AWS::EC2::Route
200 | Properties:
201 | RouteTableId: !Ref PrivateRouteTable1
202 | DestinationCidrBlock: 0.0.0.0/0
203 | NatGatewayId: !Ref NatGateway1
204 | PrivateSubnet1RouteTableAssociation:
205 | Type: AWS::EC2::SubnetRouteTableAssociation
206 | Properties:
207 | RouteTableId: !Ref PrivateRouteTable1
208 | SubnetId: !Ref PrivateSubnet1
209 | PrivateRouteTable2:
210 | Type: AWS::EC2::RouteTable
211 | Properties:
212 | VpcId: !Ref VPC
213 | Tags:
214 | - Key: Name
215 | Value: !Sub ${EnvironmentName}-containers-workshop-private-routes-az2
216 | DefaultPrivateRoute2:
217 | Type: AWS::EC2::Route
218 | Properties:
219 | RouteTableId: !Ref PrivateRouteTable2
220 | DestinationCidrBlock: 0.0.0.0/0
221 | NatGatewayId: !Ref NatGateway2
222 | PrivateSubnet2RouteTableAssociation:
223 | Type: AWS::EC2::SubnetRouteTableAssociation
224 | Properties:
225 | RouteTableId: !Ref PrivateRouteTable2
226 | SubnetId: !Ref PrivateSubnet2
227 | NoIngressSecurityGroup:
228 | Type: AWS::EC2::SecurityGroup
229 | Properties:
230 | GroupName: "no-ingress-sg"
231 | GroupDescription: "Security group with no ingress rule"
232 | VpcId: !Ref VPC
233 |
234 | Outputs:
235 | Subnet:
236 | Description: A public subnet where the load generator instance will be placed.
237 | Value: !Ref PublicSubnet1
238 | Export:
239 | Name: containers-workshop-public-subnet
240 | VPC:
241 | Description: The VPC created to the workshop.
242 | Value: !Ref VPC
243 | Export:
244 | Name: containers-workshop-vpc
245 |
--------------------------------------------------------------------------------
/01-EnvironmentSetup/images/cloud9_editor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/01-EnvironmentSetup/images/cloud9_editor.png
--------------------------------------------------------------------------------
/01-EnvironmentSetup/images/cloud9_files.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/01-EnvironmentSetup/images/cloud9_files.png
--------------------------------------------------------------------------------
/01-EnvironmentSetup/images/cloud9_main_screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/01-EnvironmentSetup/images/cloud9_main_screen.png
--------------------------------------------------------------------------------
/01-EnvironmentSetup/images/cloud9_terminal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/01-EnvironmentSetup/images/cloud9_terminal.png
--------------------------------------------------------------------------------
/01-EnvironmentSetup/images/cloudformation_output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/01-EnvironmentSetup/images/cloudformation_output.png
--------------------------------------------------------------------------------
/01-EnvironmentSetup/images/containers-on-aws-workshop-vpc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/01-EnvironmentSetup/images/containers-on-aws-workshop-vpc.png
--------------------------------------------------------------------------------
/01-EnvironmentSetup/images/environment_setup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/01-EnvironmentSetup/images/environment_setup.png
--------------------------------------------------------------------------------
/01-EnvironmentSetup/images/launch_stack_button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/01-EnvironmentSetup/images/launch_stack_button.png
--------------------------------------------------------------------------------
/02-CreatingDockerImage/README.md:
--------------------------------------------------------------------------------
1 | # Creating your Docker image
2 |
3 | 
4 |
5 |
6 | ## Quick jump:
7 |
8 | * [1. Tutorial overview](/02-CreatingDockerImage#1-tutorial-overview)
9 | * [2. Creating your first image](/02-CreatingDockerImage#2-creating-your-first-image)
10 | * [3. Setting up the IAM Roles](/02-CreatingDockerImage#3-setting-up-the-iam-roles)
11 | * [4. Configuring the AWS CLI](/02-CreatingDockerImage#4-configuring-the-aws-cli)
12 | * [5. Creating the image repository with ECR](/02-CreatingDockerImage#5-creating-the-image-repository-with-ecr)
13 | * [6. Pushing our tested images to ECR](/02-CreatingDockerImage#6-pushing-our-tested-images-to-ecr)
14 |
15 | ## 1. Tutorial overview
16 |
17 | This tutorial is going to drive you through the process of creating your first Docker image, running this image locally and pushing it to a image repository. If you are going to execute this lab in the Clou9 environment, you can jump to [2. Creating your first image](/02-CreatingDockerImage#2-creating-your-first-image).
18 |
19 | >This Docker image will have a very simple web application that you can find in the `00-Application/app` directory.
20 |
21 | In this tutorial, we assume that you completed the [Setup Environment tutorial](/01-EnvironmentSetup) and:
22 |
23 | * [Have a working AWS account]()
24 | * [Have a working Github account]()
25 | * [Have the AWS CLI installed]()
26 |
27 | To check if you have the AWS CLI installed and configured:
28 |
29 | $ aws --version
30 |
31 | This should return something like:
32 |
33 | $ aws --version
34 | aws-cli/1.14.9 Python/2.7.13 Linux/4.9.81-35.56.amzn1.x86_64 botocore/1.8.13
35 |
36 | > Note that to run this tutorial, you need to have the most recent version of AWS CLI installed.
37 |
38 | To check if you have Docker installed:
39 |
40 | $ docker -v
41 |
42 | This should return something like:
43 |
44 | Docker version 17.12.0-ce, build 3dfb8343b139d6342acfd9975d7f1068b5b1c3d3
45 |
46 | >If you after running the `docker -v` command you don't get this output, please follow the install instructions in [this link](/01-SetupEnvironment#install-docker).
47 |
48 | If you have completed these steps, you are good to go!
49 |
50 | ## 2. Creating your first image
51 |
52 | The following steps should be executed on your own computer or Cloud9 instance, if you chose it.
53 |
54 | If you haven't executed the `git clone` command present in the [Setup Environment](/01-SetupEnvironment#5-cloning-the-workshop-repository) chapter, do it now using the following command:
55 |
56 | $ git clone https://github.com/bemer/containers-on-aws-workshop.git
57 |
58 | Now we are going to build and test our containers locally. If you've never worked with Docker before, there are a few basic commands that we'll use in this workshop, but you can find a more thorough list in the [Docker "Getting Started" documentation](https://docs.docker.com/engine/getstarted/).
59 |
60 | In this step, we are going to build a *Docker image* with a simple web application. The application that we will be using is available on the directory `00-Application` inside the project folder. In this case, lets's navigate to the `00-Application` directory:
61 |
62 | $ cd containers-on-aws-workshop/00-Application/
63 |
64 | Take a look on the contents of this directory. You will see that there is a directory called `app/` and also a file named `Dockerfile`. We will be using this `Dockerfile` to package our web application. In order to do that, run the following command inside the `00-Application` directory:
65 |
66 | $ docker build -t containers-workshop-app .
67 |
68 | This should output steps that look something like this:
69 |
70 | Sending build context to Docker daemon 9.295MB
71 | Step 1/9 : FROM node:alpine
72 | ---> 5ce79d7a9aad
73 | Step 2/9 : COPY app/ /app
74 | ---> 5db182714408
75 | Step 3/9 : WORKDIR /app
76 | Removing intermediate container 0fed50590e13
77 | ---> 8b89b65c5c67
78 | Step 4/9 : RUN npm install --global gulp && npm install gulp
79 | ---> Running in f86ae7a1e8bb
80 |
81 | If the container builds successfully, the output should end with something like this:
82 |
83 | Successfully built 0c50204fc662
84 | Successfully tagged containers-workshop-app:latest
85 |
86 | To run your container:
87 |
88 | $ docker run -d -p 8080:80 containers-workshop-app
89 |
90 | To check if your container is running:
91 |
92 | $ docker ps
93 |
94 | This should return a list of all the currently running containers. In this example, it should just return a single container, the one that we just started:
95 |
96 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
97 | 1255ca3087f5 containers-workshop-app "node server.js" Less than a second ago Up 1 second 0.0.0.0:80->8080/tcp, 8080/tcp nifty_snyder
98 |
99 |
100 |
101 | To test the application, you can use the Cloud9 `Preview Running Application` feature. In Cloud9, click in `Preview` > `Preview Running Application`
102 |
103 | 
104 |
105 | If everything went fine, you should see your web application:
106 |
107 | 
108 |
109 |
110 |
111 | ## 3. Setting up the IAM roles
112 |
113 | **This step is only needed if you are doing the workshop using your own computer. If you are using the Cloud9 environment, you can go ahead to the step [5. Creating the image repository with ECR](/02-CreatingDockerImage#5-creating-the-image-repository-with-ecr)**
114 |
115 | In order to work with the AWS CLI, you'll need an IAM role with the proper permissions set up. To do this, we'll create both an IAM Group, and an IAM user.
116 |
117 | To create the group, navigate to the [IAM console](https://console.aws.amazon.com/iam/home?region=us-east-1#/home), and select **Groups** > **Create New Group**. Name the group "**containers-workshop-group**". From the list of managed policies, add the following policies:
118 |
119 | * AmazonEC2ContainerRegistryFullAccess
120 | * AmazonEC2ContainerServiceFullAccess
121 |
122 | This is how your group permissions should like after the creation:
123 |
124 | 
125 |
126 | Once you've created your group, you need to create a new user and attach this new user to this group. In order to do so, on the IAM console, click in **Users** on the left side of the screen, and them click in the button **Add user**.
127 |
128 | The user name will be **containers-workshop-user**. Don't forget to select the **Programmatic access** and the **AWS Management Console access** in the `Access type` just like in the following picture:
129 |
130 | 
131 |
132 | Now, click in **Next: permissions** and in the **Add user to group** screen, select the group `containers-workshop-group` that we created before:
133 |
134 | 
135 |
136 | >NOTE: If you already have more groups created in your account, you can use the `Search` on the IAM console to find the group that you created before, just like in the picture.
137 |
138 | Click in **Next: Review** and check if is everything fine with your user creation. The screen should be similar to this one:
139 |
140 | 
141 |
142 | In this screen, click in **Create user**.
143 |
144 | When the wizard finishes, make sure to download and save your access key and secret key. You'll need them in the next step.
145 |
146 | >NOTE: The Secret access key is presented only once, during the user creation. If you loose this information, you will need to create a new Access and Secret keys in order to authenticate with this user.
147 |
148 | ## 4. Configuring the AWS CLI
149 |
150 | **This step is only needed if you are doing the workshop using your own computer. If you are using the Cloud9 environment, you can go ahead to the step [5. Creating the image repository with ECR](/02-CreatingDockerImage#5-creating-the-image-repository-with-ecr)**
151 |
152 |
153 | If you've never configured the AWS CLI, the easiest way is by running the command:
154 |
155 | $ aws configure
156 |
157 | This should drop you into a setup wizard. In this wizard, complete each field with the informations generated in the user creation step:
158 |
159 | $ aws configure
160 | AWS Access Key ID [****************K2JA]:
161 | AWS Secret Access Key [****************Oqx+]:
162 | Default region name [us-east-1]:
163 | Default output format [json]:
164 |
165 | If you already have a profile setup with the AWS CLI, you can also add a new profile to your credentials file. In order to add another profile, edit your credentials (usually located in *~/.aws/credentials*) and add a new profile called "**containers-workshop**". After adding this new profile, your credentials file will be like this:
166 |
167 | [default]
168 | aws_access_key_id = AKIABCDMYKEYEXAMPLE1
169 | aws_secret_access_key = CAFESECRETACCESSKEYEXAMPLE001
170 |
171 | [containers-workshop]
172 | aws_access_key_id = AKIABCDMYKEYEXAMPLE2
173 | aws_secret_access_key = CAFESECRETACCESSKEYEXAMPLE002
174 |
175 |
176 | You can test that your IAM user has the correct permissions, and that your CLI is setup to connect to your AWS account by running the command to obtain an ECR authentication token. This will allow us to pull the Docker image to our repository in the next step:
177 |
178 | $ aws ecr get-login --region YOUR_REGION_HERE --no-include-email
179 |
180 | This should output something like:
181 |
182 | $ docker login -u AWS -p AQECAHhwm0YaISJeRtJm5n1G6uqeekXuoXXPe5UFce9Rq8/14wAAAy0wggMpBgkqhkiG9w0BBwagggMaM
183 | IIDFgIBADCCAw8GCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM+76slnFaYrrZwLJyAgEQgIIC4LJKIDmvEDtJyr7jO661//6sX6cb2je
184 | D/RP0IA03wh62YxFKqwRMk8gjOAc89ICxlNxQ6+cvwjewi+8/W+9xbv5+PPWfwGSAXQJSHx3IWfrbca4WSLXQf2BDq0CTtDc0+payiDdsX
185 | dR8gzvyM7YWIcKzgcRVjkcjfLJpXemQ9liPWe4HKp+D57zCcBvgUk131xCiwPzbmGTZ+xtE1GPK0tgNH3t9N5+XA2BYYhXQzkTGISVGGL6
186 | Wo1tiERz+WA2aRKE+Sb+FQ7YDDRDtOGj4MwZakdMnOZDcwu3uUfrURXdJVddTEdS3jfo3d7yVWhmXPet+3qwkISstIxG+V6IIzQyhtq3BX
187 | W/I7pwZB9ln/mDNlJVRh9Ps2jqoXUXg/j/shZxBPm33LV+MvUqiEBhkXa9cz3AaqIpc2gXyXYN3xgJUV7OupLVq2wrGQZWPVoBvHPwrt/D
188 | KsNs28oJ67L4kTiRoufye1KjZQAi3FIPtMLcUGjFf+ytxzEPuTvUk4Xfoc4A29qp9v2j98090Qx0CHD4ZKyj7bIL53jSpeeFDh9EXubeqp
189 | XQTXdMzBZoBcC1Y99Kk4/nKprty2IeBvxPg+NRzg+1e0lkkqUu31oZ/AgdUcD8Db3qFjhXz4QhIZMGFogiJcmo=
190 | https://XXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com
191 |
192 |
193 | > The '-e' option has been deprecated in the `docker login` command and was removed in docker version 17.06 and later. You must specify --no-include-email if you're using docker version 17.06 or later. The default behavior is to include the '-e' flag in the 'docker login' output.
194 |
195 | >NOTE: If you already had the credentials file and just added a new profile in it, don't forget to use the `--profile container-workshop` in the end of the command. This is needed because every time that you run a command using the awscli, it is going to use the `default` profile, so if we want to use a different one, we need to specify when running the command.
196 |
197 |
198 | ## 5. Creating the image repository with ECR
199 |
200 | Before we can build and push our images, we need somewhere to push them to. In this case, we're going to create just one repository in [ECR](https://aws.amazon.com/ecr/).
201 |
202 | To create a repository, navigate to the [ECR console](https://console.aws.amazon.com/ecr). If this is the first time that you are accessing the ECR console, you will see the **Get Started** button in the top right corner. Click in it:
203 |
204 | 
205 |
206 |
207 | Name your first repository **containers-workshop-app**:
208 |
209 | 
210 |
211 | Once you've created the repository, you will be redirected to the ECR main screen. You will be able to see your newly created repository:
212 |
213 | 
214 |
215 | Now, access your repository by clicking in its name. Now, click in the button **View push commands** in the top right corner. It will display a list of commands that you will need to use to push your Docker images. These commands will be like this:
216 |
217 | 
218 |
219 | ## 6. Pushing our tested images to ECR
220 |
221 | Now that we've tested our images locally, we need to tag them again, and push them to ECR. This will allow us to use them in `Task definitions` that can be deployed to an ECS cluster.
222 |
223 | You'll need your push commands that you saw during registry creation. If you've misplaced your push commands, you can find them again by going back to the repository (**ECR Console** > **Repositories** > Select the repository you want to see the commands for > **View Push Commands**.
224 |
225 | The first thing that we need to do, is authenticate our Docker client to the ECR. To do this, we need get the `docker login` command with the repository informations. To get this informations, run the following command:
226 |
227 | $ aws ecr get-login --no-include-email
228 |
229 | The output of this command is the `docker login` command that we wil need to run. It is going to be similar to:
230 |
231 | docker login -u AWS -p eyJwYXlsb2FkIjoiQXowb3lmSVNpa2dCeUF0UCt3UjRyN3JqZ2w0ZVFqbjMwQXBFY2szVkRQRUx6KzRMb3REUHhLTlowYk9ncWZYelhwclhXdW1vWm5GVzJPVi9LSDhaRlVsTUtxaGVPMWU2RzV6Njg2QlAraXVDSklPMXdZVTNpNTBLVkR2dnUyaVZ2SkRZUEdmM3BLR0IvSG9WQWFFZmJJVFRJNkZPODVOQWRvcEpHYnJhYmNGQXYvckVGQ0FLa1pkQ1k1NkNNTmcwNFlOek1lanpKLzQyUjZwMlV2ZjgxUVBaTm1ubWZYZE11VHA0MHQ2OGRJdDBuQi9acXZZVkN6MXVzSlJBVFUwK1A4UlNSOXlyL0N3T3lvQWlkUlFDdDlUc3Z1SHVwZGhOeHNkTHVNc1RRcDZvYS9obzFWVXhiN0RJYmhrcWEwdlVIREhtS2t0OTFpUnFGcFV5aVBhYk80eTVGaXlzOU15NkN5QlIzZlI4U2lOUDlmaW9tb2hvMklYYkdZeHpsYXNKK0FvTGFkU2xhYUFxRkRzeGpPaEJRL1ZlTWlNL2Z3bHhDYytuMUdrK29LT1lsZm5LTS9RdUdNcVdXTkJpN1VxUncyN3p4VjJCR3NPT05NaXVMemlQUlhyWXhucVpxTDh6b2JpN25KQy96UXFsRERqdExPTW9UMGdiSmo1bWloTXVqdm4vWWZYRDVqQnAxWTRSNW5YcCtwQ2Q4Z0NSQKSJFXlKT0hUZUJuM21VZFR0N2EzdmhxNWoyL0RtdFJxYVpPNUpSMm9GWjY5UmJYUUFUSStLMDBVZ1lMMFpZVHcycXorbGVZYlh0YzlxK2FTM3krSm53L2FNZVNiUGtoOWJuU01CZDQvSFcvemcxUElsRlhvOEZpTG1ZakppNEpRcHJIa2czemk0ektOOS9NL3pOaXVXSXp1a3Ezb05QZjMrUndZSmptdy9mbFd3OEJGLzJoejJJVXVhbENkWkYzdldRaUhRNEt3YjBYNVFidXdvZTVZOWwyNEJZcVBMdEh4V0xrUUFuS2NVUkEvVTNVSlpLaEVVZXlMV28vSFBYWmxUSK820WUVMU25hNTVUWTJqa0VCcXBhaTEyQTJyTGwwM0tjUjY1VzNyZU05RUVUMmswTmJhZVNWZmNkQ28rUE95dUxCSHJTS2RIVHozbzNuVzE2SlhtaTdOWlRSMlBjMkFCOEExQTNXN01zaGJGcjRqbUs1a1UySWI2cnRjeWcrU2g2Zm0xYWhpQlRueXJrbzlpZGhGanVWbU1GOHppL29jZ3JBTG80TjExOGlvejZwNkxSWmhdVMmdmUWI5UnFGRkXKSjJRVXdFcHBqWXhtSzRLQ0RwTWF4NVhGM1czT1c1MjM1ejV3emR1ZGxwclg5TWdGbmY2Q3ljdjA2YlFEa25LeVZVK2VOQXZqUkZlWndhZGJKeTZtMzdRYkI4MllNN25VVmREVmhtOXpKV0dEUlNQVWpGSzYrLCJkYXRha2V5IjoiQVFFQkFIaHdtMFlhSVNKZVJ0Sm01bjFHNnVxZWVrWHVvWFhQZTVVRmNlOVJxOC8xNHdBQUFINHdmQVlKS29aSWh2Y05BUWNHb0c4d2JRSUJBREJvQmdrcWhraUc5dzBCQndFd0hnWUpZSVpJQVdVREJBRXVNQkVFREtQbEE5b1VnVUpyY3JkOFFRSUJFSUE3MHJETXcwMFJUc0R4eDBCOEN2NXJTK25waW5iUEw4WG9UeUpubmxnbWhGTFkwcGo3WGg4ZEpxMHlkSXpNWGhYT2xxb2ZFUFU4UVk4UkZkRT0iLCJ2ZXJzaW9uIjoiMiIsInR5cGUiOiJEQVRBX0tFWSIsImV4cGlyYXRpb24iOjE1MjE4ODIxOTZ9 https://XXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com
232 |
233 | To login to ECR, copy this output and execute it as a linux command. The output will be the following:
234 |
235 | WARNING! Using --password via the CLI is insecure. Use --password-stdin.
236 | Login Succeeded
237 |
238 |
239 | >NOTE: If you are running it in a linux terminal, you can just run the command like this `aws ecr get-login --no-include-email` which will tell your shell to execute the output of the first command.
240 |
241 | If you are unable to login to ECR, check your IAM user group permissions.
242 |
243 | Now, let's tag our image locally and them push our image to the ECR repository. Use the following commands:
244 |
245 | $ docker tag containers-workshop-app:latest XXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/containers-workshop-app:latest
246 | $ docker push XXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/containers-workshop-app:latest
247 |
248 | >NOTE: Remember to replace the `XXXXXXXXX` with your account ID. This information will be presented to you in the ECR screen with the Docker push commands.
249 |
250 | > Why `:latest`? This is the actual image tag. In most production environments, you'd tag images for different schemes: for example, you might tag the most up-to-date image with `:latest`, and all other versions of the same container with a commit SHA from a CI job. If you push an image without a specific tag, it will default to `:latest`, and untag the previous image with that tag. For more information on Docker tags, see the Docker [documentation](https://docs.docker.com/engine/getstarted/step_six/).
251 |
252 |
253 | This step will take some minutes. When the command finishes, you should see something like this:
254 |
255 | The push refers to a repository [XXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/containers-workshop-app]
256 | 9ef5219507db: Pushed
257 | b3d18e8f520f: Pushed
258 | a83b4d2ff3a0: Pushed
259 | 2f5b0990636a: Pushed
260 | c9748fbf541d: Pushed
261 | b3968bc26fbd: Pushed
262 | aa4e47c45116: Pushed
263 | 788ce2310e2f: Pushed
264 | latest: digest: sha256:38588bb240b57d123522ab3d23cec642907a99f1379445fbea27dafc58608 size: 1988
265 |
266 |
267 | You can see your pushed images by viewing the repository in the AWS Console. Alternatively, you can use the CLI:
268 |
269 | $ aws ecr list-images --repository-name=containers-workshop-app
270 | {
271 | "imageIds": [
272 | {
273 | "imageTag": "latest",
274 | "imageDigest": "sha256:38588bb240b57d123522ab3d23107cec6438d7a99f1379445fbea27dafc58608"
275 | }
276 | ]
277 | }
278 |
279 |
280 |
281 | [][back-to-menu] [][continue-workshop]
282 |
283 | [back-to-menu]: https://github.com/bemer/containers-on-aws-workshop
284 | [continue-workshop]: /03-DeployEcsCluster
285 |
--------------------------------------------------------------------------------
/02-CreatingDockerImage/images/add_user_to_group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/02-CreatingDockerImage/images/add_user_to_group.png
--------------------------------------------------------------------------------
/02-CreatingDockerImage/images/container.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/02-CreatingDockerImage/images/container.png
--------------------------------------------------------------------------------
/02-CreatingDockerImage/images/creating_repository.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/02-CreatingDockerImage/images/creating_repository.png
--------------------------------------------------------------------------------
/02-CreatingDockerImage/images/creating_user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/02-CreatingDockerImage/images/creating_user.png
--------------------------------------------------------------------------------
/02-CreatingDockerImage/images/ecr_main_screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/02-CreatingDockerImage/images/ecr_main_screen.png
--------------------------------------------------------------------------------
/02-CreatingDockerImage/images/getting_started_ecr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/02-CreatingDockerImage/images/getting_started_ecr.png
--------------------------------------------------------------------------------
/02-CreatingDockerImage/images/iam_group_permissions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/02-CreatingDockerImage/images/iam_group_permissions.png
--------------------------------------------------------------------------------
/02-CreatingDockerImage/images/preview_application.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/02-CreatingDockerImage/images/preview_application.png
--------------------------------------------------------------------------------
/02-CreatingDockerImage/images/push_commands.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/02-CreatingDockerImage/images/push_commands.png
--------------------------------------------------------------------------------
/02-CreatingDockerImage/images/review_user_creation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/02-CreatingDockerImage/images/review_user_creation.png
--------------------------------------------------------------------------------
/02-CreatingDockerImage/images/web_application.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/02-CreatingDockerImage/images/web_application.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/README.md:
--------------------------------------------------------------------------------
1 | # Running an ECS Cluster
2 |
3 | 
4 |
5 | **Quick jump:**
6 |
7 | * [1. Tutorial overview](/03-DeployEcsCluster#1-tutorial-overview)
8 | * [2. Creating the Cluster](/03-DeployEcsCluster#2-creating-the-cluster)
9 | * [3. Creating the ALB](/03-DeployEcsCluster#3-creating-the-alb)
10 | * [4. Creating the Task Definition](/03-DeployEcsCluster#4-creating-the-task-definition)
11 | * [5. Creating the Service](/03-DeployEcsCluster#5-creating-the-service)
12 | * [6. Testing our service deployments from the console and the ALB](/03-DeployEcsCluster#6-testing-our-service-deployments-from-the-console-and-the-alb)
13 |
14 | ## 1. Tutorial overview
15 |
16 | This tutorial will guide you through the creation of an ECS Cluster and the deployment of the container with a simple application created in the previous lab.
17 |
18 | In order to run this tutorial, you must have completed the following steps:
19 |
20 | * [Setup Environment](/01-SetupEnvironment)
21 | * [Creating your Docker image](/02-CreatingDockerImage)
22 |
23 |
24 | ## 2. Creating the Cluster
25 |
26 | Once you've signed into your AWS account, navigate to the [ECS console](https://console.aws.amazon.com/ecs). This URL will redirect you to the ECS interface on N. Virginia region. If this is your fist time using ECS, you will see the *Clusters* screen without any clusters in it:
27 |
28 | 
29 |
30 | Let's create our first ECS Cluster. Click in the button **Create cluster**, select the **EC2 Linux + Networking** cluster template and click in `Next Step`:
31 |
32 | 
33 |
34 | You will then be asked to input information about your new cluster. In the *Configure cluster* screen, keep the default values to the fields, changing just these ones:
35 |
36 | ### Configure cluster
37 | * Cluster name: `containers-workshop-ecs-cluster`
38 |
39 | ### Instance configuration
40 | * EC2 instance type: `t2.micro`
41 |
42 | ### Networking
43 | * VPC: Select the VPC `containers-workshop-vpc` created in the [01-Setup Environments](/01-SetupEnvironment) step
44 | * Subnets: Select the `containers-workshop-private-subnet-az1` and `containers-workshop-private-subnet-az2` subnets in your VPC
45 |
46 | And then click in **Create**.
47 |
48 | >In this tutorial we are not covering the creation of a Key Pair to access your EC2 instances. If you want to access your instances for troubleshooting purposes or even to just see how the ECS agent works you will need to create a Key Pair and then select it in the `Key pair` option. You can see how to create a new Key Pair in [this link](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html).
49 |
50 | Note that this wizard is also going to create a security group for you allowing access in the port 80 (TCP).
51 |
52 | After changing all these parameters and putting the needed information, click in the button **Create** in the end of the screen.
53 |
54 | When the creation process finishes, you will see the following screen:
55 |
56 | 
57 |
58 | You can then click in the button **View Cluster** to see your cluster. The ECS Cluster screen will be like this:
59 |
60 | 
61 |
62 |
63 | ## 3. Creating the ALB
64 |
65 | Now that we've created our cluster, we need an [Application Load Balancer (ALB)](https://aws.amazon.com/elasticloadbalancing/applicationloadbalancer/) to route traffic to our endpoints. Compared to a traditional load balancer, an ALB lets you direct traffic between different endpoints. In our example, we'll use the enpoint `/app`.
66 |
67 | To create the ALB:
68 |
69 | Navigate to the [EC2 Service Console](https://console.aws.amazon.com/ec2), and select **Load Balancers** from the left-hand menu. Click in **Create Load Balancer**. Inside the `Application Load Balancer`, click in **Create**:
70 |
71 | 
72 |
73 | Name your ALB `containers-workshop-alb` and add an HTTP listener on port 80:
74 |
75 | 
76 |
77 | In this same screen, under **Availability Zones** select the VPC `containers-workshop-vpc` previously created and select the two public subnets:
78 |
79 | 
80 |
81 |
82 | After adding the information about your Availability Zones, click in **Next: Configure Security Settings**.
83 |
84 | When clicking in next, you should see a message saying that your load balancer is not using any secure listener. We can just skip this screen, clicking in **Next: Configure Security Groups**.
85 |
86 | >NOTE: In a production environment, you should also have a secure listener on port 443. This will require an SSL certificate, which can be obtained from [AWS Certificate Manager](https://aws.amazon.com/certificate-manager/), or from your registrar/any CA. For the purposes of this workshop, we will only create the insecure HTTP listener. DO NOT RUN THIS IN PRODUCTION.
87 |
88 | Let's now create a security group to be used by your ALB. In the *Step 3: Configure Security Groups* screen, let's select the option `Create a new security group`. Change the **Security group name** to `containers-workshop-alb-sg` and create a rule allowing all traffic in the port `80`:
89 |
90 | 
91 |
92 | Them, click in **Next: Configure Routing**.
93 |
94 | During this initial setup, we're just adding a dummy health check on `/`. We'll add specific health checks for our ECS service endpoint when registering it with the ALB. Let's change only the the **Name** to `dummy`:
95 |
96 | 
97 |
98 | Click in **Next: Register Targets** and then in **Next: Review**. If your values look correct, click **Create**:
99 |
100 | 
101 |
102 |
103 | After creating your ALB, you need to update the security group rule so your ALB can access the EC2 instances where your containers will run. In order to identify what is the security group applied to your instances, you can access the ECS console, select the cluster `containers-workshop-ecs-cluster` and then select the tab **ECS Instances**. You will see that you have one instance running. Then, click in the ECS Instance ID:
104 |
105 | 
106 |
107 | >NOTE: in this screen, you will find two different ID's. One of them is related to the `Container Instance`, which will show you all the tasks running in this specific instance as well as some data from the EC2 Instance. The other ID is the `EC2 Instance` ID, that will redirect you to the EC2 console, where you can manage the EC2 instance.
108 |
109 | In the EC2 service dashboard, you will see all the information about your instance. In this screen, click in the security group name. This name is going to be similar to **EC2ContainerService-containers-workshop-ecs-cluster-EcsSecurityGroup-12SD646C23L1H**:
110 |
111 | 
112 |
113 | In this screen, with the Security Group selected, click in the tab **Inbound** and then in **Edit**. Here, we will have a rule previously create allowing traffic in the port 80 from anywhere. Let's change this rule, in order to allow all traffic coming from the ALB security group to our EC2 instance. Start changing the `Type` to `All Traffic` and in the field `Source` start typing `sg-`. You will see a list with all the security groups created in your AWS account. Select the security group `containers-workshop-alb-sg` previously created and click in **Save**:
114 |
115 | 
116 |
117 | The final rules in your instance Security Group should look like this:
118 |
119 | 
120 |
121 |
122 | At this point, your EC2 instances will be able to receive traffic from the ALB.
123 |
124 | >NOTE: When creating this rule we are allowing all the traffic from the ALB to the instances. We are doing that because when working with ECS we can use a dynamic port mapping feature in order to run more containers with the same image in the same EC2 instance, so when starting our task, we will not specify any port to run our application and the ECS will do it for us. Since we don't know what is the port that the Docker daemon will expose, we need to allow all traffic to have our application accessible by the ALB.
125 |
126 |
127 |
128 | ## 4. Creating the Task Definition
129 |
130 | When working with ECS to run our applications, there are a few concepts that we need to understand. The first of these concepts is about what is a `Task`. Basically, a task is a subset of containers that we need to execute in order to have our application running. The `Tasks` are defined in a configuration called `Task Definition`.
131 |
132 | A `Task Definition` is where you will specify your task. Things like the Docker Image version, the amount of CPU and memory that each container will need, what ports needs to be mapped, data volumes, environment variables and other informations are going to be specified in the Task Definition.
133 |
134 | The first thing that we will need, is the information about the image that we want to use. In this case, we are going to use the image created in the [Creating Your Docker Image](/02-CreatingDockerImage) tutorial. To get the image URI, navigate to the [ECR page](https://console.aws.amazon.com/ecr) and click in `Repositories`. You will see the repository named `containers-workshop-app`. In this screen, you will also see that there is a `Repository URI`. Take note of this URI:
135 |
136 | 
137 |
138 |
139 | To create a Task Definition, in the [ECS Page](https://console.aws.amazon.com/ecs) click in the `Task Definitions` menu, and then click in **Create new Task Definition**. Select EC2 as the *Launch type compatibility* and click in **Next step**:
140 |
141 | 
142 |
143 | Let's add now the information about this task definition. Name your task `containers-workshop-ecs-task-def` and under **Task Role** select `None`:
144 |
145 | 
146 |
147 | In the **Task execution IAM role** select `Create new role` and under **Task size** add `128` in the **Task memory (MiB)** field:
148 |
149 | 
150 |
151 | >NOTE: If this is not your first ECS Cluster, you should already have an IAM Role created. In this case, you should select the previously created IAM Role.
152 |
153 |
154 | The next step is to add the information about our container. Click in the **Add container** button, under **Container Definitions**. The name of the container will be `containers-workshop-app`. In the **Image** field, add the URI that you got before, pointing to your image.
155 |
156 | Under **Port mappings** add `0` in the **Host port** field and `80` in the *Container port*.
157 |
158 | 
159 |
160 |
161 | A few things to note here:
162 |
163 | - We've specified a specific container image, including the `:latest` tag. Although it's not important for this demo, in a production environment where you were creating Task Definitions programmatically from a CI/CD pipeline, Task Definitions could include a specific SHA, or a more accurate tag.
164 |
165 | - Under **Port Mappings**, we've specified a **Container Port** (80), but left **Host Port** as 0. This was intentional, and is used to facilitate dynamic port allocation. This means that we don't need to map the Container Port to a specific Host Port in our Container Definition - instead, we can let the ALB dynamically allocate a port during the task placement. To learn more about port allocation, check out the [ECS documentation here](http://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_PortMapping.html).
166 |
167 | Once you've specified your Port Mappings, scroll down and add a log driver. There are a few options here, but for this demo, select **Auto-configure CloudWatch Logs**:
168 |
169 | 
170 |
171 | Once you've added your log driver, click in **Add** to add the container in your task definition, and finally click in **Create** in the `Task Definition` screen.
172 |
173 |
174 | ## 5. Creating the Service
175 |
176 | Now that we have the description of everything we need to run our application in the `Task Definition`, the next step is to run our container using Amazon ECS. Let's do it by creating a `Service`.
177 |
178 | In ECS, a `Service` allows you to run and maintain a specified number (the "desired count") of instances of a task definition simultaneously in an Amazon ECS cluster. If any of your tasks should fail or stop for any reason, the Amazon ECS service scheduler launches another instance of your task definition to replace it and maintain the desired count of tasks in the service. You can find more information about ECS Services in the [ECS documentation](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_services.html).
179 |
180 | Navigate back to the [Clusters screen](https://console.aws.amazon.com/ecs/) on the ECS console, and click in the cluster name `containers-workshop-ecs-cluster` previously created.
181 |
182 | >If you don't have a cluster named **containers-workshop-ecs-cluster**, create one following the procedures in [Creating the cluster](/03-DeployEcsCluster#2-creating-the-cluster).
183 |
184 | In the details page of the **containers-workshop-ecs-cluster** , click in the button **Create**, in the `Services` tab:
185 |
186 | 
187 |
188 | Select `EC2` as the `Launch Type`, and choose the Task Definition created in the previous section. For the purposes of this demo, we'll only start one copy of this task.
189 |
190 | >In a production environment, you will always want more than one copy of each task running for reliability and availability.
191 |
192 | Name your service `containers-workshop-ecs-service`.
193 |
194 | You can keep the default **AZ Balanced Spread** for the Task Placement Policy. To learn more about the different Task Placement Policies, see the [documentation](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement-strategies.html), or this [blog post](https://aws.amazon.com/blogs/compute/introducing-amazon-ecs-task-placement-policies/).
195 |
196 | 
197 |
198 | Click in **Next**.
199 |
200 | Under **Service discovery (optional)** uncheck **Enable service discovery integration**.
201 |
202 | Now, under `Load balancing`, select `Application Load Balancer`. Let's configure the integration between the ECS Service and the Application Load Balancer, so we will be able to access the application using the ALB. Select `Create new role` under `Service IAM role` and under`Container to load balance`, select the container `containers-workshop-app:0:80`. Click in **Add to load balancer**:
203 |
204 | 
205 |
206 | This final step allows you to configure the container with the ALB. When we created our ALB, we only added a listener for HTTP:80. Select this from the dropdown as the value for **Listener**. For **Target Group Name**, enter a value that will make sense to you later, like `containers-workshop-ecs-target`. For **Path Pattern**, the value should be `/*`. In the **Evaluation order**, add the number `1`.
207 |
208 | Finally, **Health check path**, use the value `/`.
209 |
210 | 
211 |
212 | If the values look correct, click **Next Step**.
213 |
214 | Since we will not use Auto Scaling in this tutorial, in the `Set Auto Scaling` screen, just click in **Next Step** and after reviewing your configurations, click in **Create Service**.
215 |
216 |
217 | ## 6. Testing our service deployments from the console and the ALB
218 |
219 | You can see service level events from the ECS console. This includes deployment events. You can see if your service was deployed and registered properly with the ALB by looking at the service's **Events** tab:
220 |
221 | 
222 |
223 | We can also test from the ALB itself. To find the DNS A record for your ALB, navigate to the EC2 Console > **Load Balancers** > **Select your Load Balancer**. Under **Description**, you can find details about your ALB, including a section for **DNS Name**. Enter this value in your browser:
224 |
225 | 
226 |
227 | You can see that the ALB routes traffic appropriately based on the path (`/`) we specified when we registered the container
228 |
229 |
230 |
231 | [][back-to-menu] [][continue-workshop]
232 |
233 | [back-to-menu]: https://github.com/bemer/containers-on-aws-workshop
234 | [continue-workshop]: /04-DeployFargate
235 |
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/add_container_to_alb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/add_container_to_alb.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/alb_app_response.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/alb_app_response.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/alb_creation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/alb_creation.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/cluster_created.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/cluster_created.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/cluster_screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/cluster_screen.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/cluster_template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/cluster_template.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/clusters_screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/clusters_screen.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/configure_alb_routing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/configure_alb_routing.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/configure_container_alb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/configure_container_alb.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/container_def.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/container_def.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/create_alb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/create_alb.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/create_alb_sg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/create_alb_sg.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/create_service.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/create_service.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/create_task_def.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/create_task_def.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/create_task_iam.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/create_task_iam.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/ec2_security_group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/ec2_security_group.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/ecs_instance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/ecs_instance.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/ecs_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/ecs_logo.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/final_sg_configuration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/final_sg_configuration.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/image_uri.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/image_uri.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/select_alb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/select_alb.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/select_subnets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/select_subnets.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/service_creation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/service_creation.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/setup_logdriver.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/setup_logdriver.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/sg_configuration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/sg_configuration.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/steady_state_service.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/steady_state_service.png
--------------------------------------------------------------------------------
/03-DeployEcsCluster/images/task_compatibility.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/03-DeployEcsCluster/images/task_compatibility.png
--------------------------------------------------------------------------------
/04-DeployFargate/README.md:
--------------------------------------------------------------------------------
1 | # Deploying an application with AWS Fargate
2 |
3 | 
4 |
5 |
6 | **Quick jump:**
7 |
8 | * [1. Tutorial overview](/04-DeployFargate#1-tutorial-overview)
9 | * [2. Creating the Cluster](/04-DeployFargate#2-creating-the-cluster)
10 | * [3. Creating the Task Definition](/04-DeployFargate#3-creating-the-task-definition)
11 | * [4. Deploying the application](/04-DeployFargate#4-deploying-the-application)
12 | * [5. Accessing the application](/04-DeployFargate#5-accessing-the-application)
13 | * [6. Conclusion](/04-DeployFargate#6-conclusion)
14 |
15 |
16 | ## 1. Tutorial overview
17 |
18 | This tutorial will walk you through a web application deployment using AWS Fargate. This is the same application that we used for the ECS Cluster with EC2. This means that we won't need to create and build another Docker image. We will also use the same image and ECR respoitory.
19 |
20 | After concluding this tutorial, you will have an application running in AWS Fargate.
21 |
22 | ## 2. Creating the Cluster
23 |
24 | We will create a new cluster just for the Fargate tasks, however, a single ECS cluster supports both EC2 and Fargate tasks.
25 |
26 | Let's create a new cluster to deploy our containers. In your AWS account Management Console, navigate to the [ECS Console](https://console.aws.amazon.com/ecs/).
27 |
28 | Click in **Create cluster** and in the following screen select the **Networking only** cluster template. Click in **Next step**:
29 |
30 | 
31 |
32 | For the **Cluster name** use `containers-workshop-fargate-cluster` and click in **Create**:
33 |
34 | 
35 |
36 | ## 3. Creating the Task Definition
37 |
38 | To create a Task Definition, at the left side of the ECS Console menu, click in **Task Definitions**. Click in **Create new Task Definition**. Select `FARGATE` as the **Launch type compatibility** and click in **Next steps**:
39 |
40 | 
41 |
42 | In the **Task Definition Name** type `containers-workshop-fargate-task-def`. For *Task Role* choose `None`.
43 |
44 | 
45 |
46 | Under **Task execution role** choose `ecsTaskEcecutionRole`, if that role is not listed, choose `Create new role`.
47 |
48 | Under **Task memory (GB)** select `0.5GB`. For **Task CPU (vCPU)** select `0.25 vCPU`.
49 |
50 | Click in **Add container**:
51 |
52 | 
53 |
54 | For **Container name** type the name `containers-workshop-app`. And add the same ECR URL using in the previous modules of this workshop in the **Image** field. Under **Port mappings** type `80` and leave `tcp` as the protocol. Click in **Add**:
55 |
56 | 
57 |
58 | Click in **Create**.
59 |
60 | ## 4. Deploying the application
61 |
62 | Now that we have our task definition, let's create a task itself to see our container running with no servers to manage.
63 |
64 | Go back to the ECS Console and select the cluster that you created for this tutorial. Click on the **Task** tab and then click in **Run new task**
65 |
66 | 
67 |
68 | In the **Run Task** screen, for **Launch type** select `FARGATE`. For **Task Definition** select the Task Definition that you created in the previous step. For **Cluster** select the cluster `containers-workshop-fargate-cluster`:
69 |
70 | 
71 |
72 | Under **Cluster VPC**, select the VPC `containers-workshop-vpc` and the both `containers-workshop-public-subnets` as your **Subnets**. Select `ENABLED` in the **Auto-assign public IP** option. After selecting everything, click in **Run Task**:
73 |
74 | 
75 |
76 | ## 5. Accessing the application
77 |
78 | After running your task, go back to the ECS Console. Select the cluster and click on the Tasks tab. You'll see a task in the `PENDING` status.
79 |
80 | 
81 |
82 | A Fargate task can take around 30 seconds to a minute before changing its status to `RUNNING`. That's because, for each new task, an ENI is created in your VPC with an IP from the subnet you chose, and then, it's attached to the Fargate task.
83 |
84 | 
85 |
86 | To test your app, you need to get the public IP associated with your task. In order to do so, in you Fargate Cluster, click in `Tasks`. You should see your task with the status running:
87 |
88 | 
89 |
90 | Click in your Task ID (the first field of the screen) and you will be redirected to the Task Details page. You will find the public IP under the `Network` section:
91 |
92 | 
93 |
94 | Copy and paste the IP address in your browser. The final URL should look like this: http://34.229.126.241
95 |
96 | 
97 |
98 | ## 6. Conclusion
99 |
100 | You have successfully deployed an application with AWS Fargate and Docker containers. This is how you deploy a serverless container app on AWS.
101 |
102 | Now, take a moment to spend some time navigating in the AWS Fargate. Here is a list of a few thing that you can try:
103 |
104 | * Finding the container logs;
105 | * Deploying a new version of this application;
106 | * Adding an Application Load-Balancer to your task definition;
107 | * Deploying other containers using AWS Fargate (you can use the container you created on the previous tutorial).
108 |
109 |
110 |
111 | [][back-to-menu] [][continue-workshop]
112 |
113 | [back-to-menu]: https://github.com/bemer/containers-on-aws-workshop
114 | [continue-workshop]: /05-ContinuousDelivery
115 |
--------------------------------------------------------------------------------
/04-DeployFargate/images/aws_fargate_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/04-DeployFargate/images/aws_fargate_logo.png
--------------------------------------------------------------------------------
/04-DeployFargate/images/cluster_configuration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/04-DeployFargate/images/cluster_configuration.png
--------------------------------------------------------------------------------
/04-DeployFargate/images/cluster_template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/04-DeployFargate/images/cluster_template.png
--------------------------------------------------------------------------------
/04-DeployFargate/images/fargate_container.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/04-DeployFargate/images/fargate_container.png
--------------------------------------------------------------------------------
/04-DeployFargate/images/fargate_public_ip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/04-DeployFargate/images/fargate_public_ip.png
--------------------------------------------------------------------------------
/04-DeployFargate/images/fargate_tasks_screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/04-DeployFargate/images/fargate_tasks_screen.png
--------------------------------------------------------------------------------
/04-DeployFargate/images/final_fargate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/04-DeployFargate/images/final_fargate.png
--------------------------------------------------------------------------------
/04-DeployFargate/images/pending_task.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/04-DeployFargate/images/pending_task.png
--------------------------------------------------------------------------------
/04-DeployFargate/images/run_new_task.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/04-DeployFargate/images/run_new_task.png
--------------------------------------------------------------------------------
/04-DeployFargate/images/run_new_task_conf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/04-DeployFargate/images/run_new_task_conf.png
--------------------------------------------------------------------------------
/04-DeployFargate/images/run_new_task_conf_vpc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/04-DeployFargate/images/run_new_task_conf_vpc.png
--------------------------------------------------------------------------------
/04-DeployFargate/images/running_task.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/04-DeployFargate/images/running_task.png
--------------------------------------------------------------------------------
/04-DeployFargate/images/task_compatibility.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/04-DeployFargate/images/task_compatibility.png
--------------------------------------------------------------------------------
/04-DeployFargate/images/task_configuration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/04-DeployFargate/images/task_configuration.png
--------------------------------------------------------------------------------
/04-DeployFargate/images/task_size.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/04-DeployFargate/images/task_size.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/README.md:
--------------------------------------------------------------------------------
1 | # 5. Creating a Continuous Delivery Pipeline with Code services and Amazon ECS
2 |
3 | 
4 |
5 | ## Quick jump:
6 |
7 | * [1. Tutorial overview](/05-ContinuousDelivery#1-tutorial-overview)
8 | * [2. Creating a Source stage](/05-ContinuousDelivery#2-creating-a-source-stage)
9 | * [3. Creating a Build stage](/05-ContinuousDelivery#3-creating-a-build-stage)
10 | * [4. Configuring a Continuous Delivery pipeline](/05-ContinuousDelivery#4-configuring-a-continuous-delivery-pipeline)
11 | * [5. Testing our pipeline](/05-ContinuousDelivery#5-testing-our-pipeline)
12 |
13 | ## 1. Tutorial overview
14 |
15 | So far we've been deploying our containers into ECS manually. On a production environment, changes that happens on code or on the container image itself should be builded, tested and deployed, all automatically. This process is commonly known as Continuous Delivery (CD).
16 |
17 | To support us on this task, we must create a Continuous Delivery pipeline that will orchestrate different stages of our pipeline. For this workshop our pipeline will have three stages:
18 |
19 | **a) a Source stage**: the Git repository branch where all the changes should be promoted to a production environment. We will use AWS CodeCommit as the Git repository;
20 |
21 | **b) a Build stage**: automatically pulls the content from the Git repository, builds and tags the Docker image, and pushes the new version to Amazon ECR. We will use AWS CodeBuild for this job;
22 |
23 | **c) a Deployment stage**: automatically deploys the new version of our application that is on Amazon ECR into Amazon ECS. The Amazon ECS itself will be responsible for deploying it without any downtime;
24 |
25 | Since we already have the Deployment stage working, we only need to create the Source stage and the Build stage, and later, figure out how to connect all those stages to finally form an actual Continuous Delivery pipeline.
26 |
27 | Let's begin with the Source stage.
28 |
29 | ## 2. Creating a Source stage
30 |
31 | In the AWS Management Console, type on the search field `Commit` and select **CodeCommit** from the drop down list.
32 |
33 | 
34 |
35 | If this is your first time using CodeCommit, click in **Get started**.
36 |
37 | 
38 |
39 | Otherwise click **Create repository**.
40 |
41 | 
42 |
43 | In **Respoitory name** type `containers-workshop-repository`. Leave **Description** blank and click in **Create repository**.
44 |
45 | 
46 |
47 | In **Configure email notifications** just click in **Skip**.
48 |
49 | Now follow the steps that appear in **Steps to clone your repository**
50 |
51 | 
52 |
53 | git config --global credential.helper '!aws codecommit credential-helper $@'
54 | git config --global credential.UseHttpPath true
55 | git clone https://git-codecommit.us-east-2.amazonaws.com/v1/repos/containers-workshop-repository
56 |
57 | The output should be something like:
58 |
59 | $ Cloning into 'containers-workshop-repository'...
60 | $ warning: You appear to have cloned an empty repository.
61 | $ Admin:~/environment $
62 |
63 | Aditionally you'll also need to type the following commands with your email and a username. This is just to identify who commited a new change to the repository:
64 |
65 | git config --global user.email "YOUREMAIL@HERE.COM"
66 | git config --global user.name "USERNAME"
67 |
68 | At this point, you should have two folders: `containers-on-aws-workshop` and `containers-workshop-repository`. Now we need to copy our application to the CodeCommit repository. First, go to the folder where your application resides
69 |
70 | cd /home/ec2-user/environment/containers-on-aws-workshop/00-Application/
71 |
72 | Copy everything to the folder that was created when you cloned the empty repository from CodeCommit
73 |
74 | cp -r * /home/ec2-user/environment/containers-workshop-repository/
75 |
76 | Go to the folder where we will synchronize (push) with the CodeCommit repository
77 |
78 | cd /home/ec2-user/environment/containers-workshop-repository/
79 |
80 | Now let's push our application to the repository
81 |
82 | git add .
83 | git commit -m "My first commit"
84 |
85 | The output should be something like:
86 |
87 | $ [master 4956fb4] My first commit
88 | $ 62 files changed, 20787 insertions(+)
89 | $ create mode 100644 Dockerfile
90 | $ create mode 100644 app/LICENSE
91 | $ create mode 100644 app/css/coming-soon.css
92 | $ create mode 100644 app/gulpfile.js
93 | $ create mode 100644 app/img/AWS_logo_RGB_REV.png
94 | $ create mode 100644 app/img/bg-mobile-fallback.png
95 | $ ...
96 |
97 | Finally
98 |
99 | git push origin master
100 |
101 | The output should be something like:
102 |
103 | $ Counting objects: 77, done.
104 | $ Compressing objects: 100% (73/73), done.
105 | $ Writing objects: 100% (77/77), 4.27 MiB | 7.42 MiB/s, done.
106 | $ Total 77 (delta 5), reused 0 (delta 0)
107 | $ To https://git-codecommit.us-east-2.amazonaws.com/v1/repos/containers-workshop-repository
108 | $ * [new branch] master -> master
109 |
110 | We can also list the files through the CodeCommit interface:
111 |
112 | 
113 |
114 | ## 3. Creating a Build stage
115 |
116 | Before we create our CodeBuild environment, we need to upload the YAML file with all the build commands and specifications. This file will be read by CodeBuild everytime a new build must be done.
117 |
118 | In Cloud9, click in **File > New File**
119 |
120 | 
121 |
122 | Paste the following code in the new file, and change the `REPOSITORY_URI` with the URI of your ECR repository
123 |
124 | ```
125 | version: 0.2
126 |
127 | phases:
128 | pre_build:
129 | commands:
130 | - echo Logging in to Amazon ECR...
131 | - aws --version
132 | - $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
133 | - REPOSITORY_URI=XXXXXXXXXXXX.dkr.ecr.us-east-2.amazonaws.com/containers-workshop-app
134 | - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
135 | - IMAGE_TAG=${COMMIT_HASH:=latest}
136 | build:
137 | commands:
138 | - echo Build started on `date`
139 | - echo Building the Docker image...
140 | - docker build -t $REPOSITORY_URI:latest .
141 | - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
142 | post_build:
143 | commands:
144 | - echo Build completed on `date`
145 | - echo Pushing the Docker images...
146 | - docker push $REPOSITORY_URI:latest
147 | - docker push $REPOSITORY_URI:$IMAGE_TAG
148 | - echo Writing image definitions file...
149 | - printf '[{"name":"containers-workshop-app","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
150 | artifacts:
151 | files: imagedefinitions.json
152 | ```
153 |
154 | Save the file by selecting **File > Save** in Cloud9. Name it as `buildspec.yml` in the `containers-workshop-repository` folder
155 |
156 | 
157 |
158 | At this point, your repository folder should contain an `app` folder, a `buildspec.yml` file and a `Dockerfile` file. Let's push to our repository
159 |
160 | git add buildspec.yml
161 | git commit -m "Adding the build specifications file"
162 | git push origin master
163 |
164 | The `buildpsec.yml` shoudld be listed now
165 |
166 | 
167 |
168 | Now we have everything that we need to create our Build environment. In the AWS Management Console, click in **Services**, type in the search field `Build` and then select **CodeBuild** from the drop down list
169 |
170 | 
171 |
172 | If this is your first time using CodeBuild, click in **Get started**
173 |
174 | 
175 |
176 | Otherwise, click in **Create build project**
177 |
178 | 
179 |
180 | Change only what's defined below:
181 |
182 | **Project name**: `containers-workshop-build`
183 |
184 | **Source provider**: `AWS CodeCommit`
185 |
186 | **Repository**: `containers-workshop-repository`
187 |
188 | **Environment image**: `Managed image`
189 |
190 | **Operating system**: `Ubuntu`
191 |
192 | **Runtime(s)**: `Standard`
193 |
194 | **Image**: `aws/codebuild/standard:1.0`
195 |
196 | **Privileged**: Check this checkbox
197 |
198 | **Service role**: make sure `New service role` is selected. In `Role name`, if the role name is not already filled, type `codebuild-containers-workshop-build-service-role`
199 |
200 | >NOTE: take note of your role name because you will need to modify its permissions later on
201 |
202 | Expand **Additional configuration**
203 |
204 | **Environment variables**: let's create two env vars:
205 |
206 | In `Name` type `REPOSITORY_URI`, in `Value` type your ECR URI.
207 |
208 | In `Name` type `AWS_DEFAULT_REGION`, in `Value` type the region code where your ECR repository resides (e.g. `us-east-1` for N. Virginia, `us-east-2` for Ohio...).
209 |
210 | Click **Continue** and then click in **Create build project**. Your build project should be listed now:
211 |
212 | 
213 |
214 | If we try and test our build now, it will fail. There are two reasons for that:
215 |
216 | 1) The service CodeBuild doesn't have permissions to read anything from our CodeCommit repository;
217 |
218 | 2) The IAM role associated with the CodeBuild environment has only permissions to input logs in the CloudWatch logs (that's the default permissions created by the CodeBuild service role).
219 |
220 | Let's fix these.
221 |
222 | First, let's change the ECR repository permisions. In the AWS Management Console, click in **Services** > in the search field type `ecr` and select **ECR** from the drop down list
223 |
224 | 
225 |
226 | Expand the left side menu and click in **Repositories**. Click in the ECR repository that we are using (`containers-workshop-app`)
227 |
228 | On the left side menu, click **Permissions** and click in **Edit**
229 |
230 | 
231 |
232 | Click in **Add statement**
233 |
234 | For **Statement name** type `Codebuild permission`
235 |
236 | For **Effect** select `Allow`
237 |
238 | For **Service principal - optional** type `codebuild.amazonaws.com`
239 |
240 | For **Actions** select the following actions: `ecr:GetDownloadUrlForLayer`, `ecr:PutImage`, `ecr:CompleteLayerUpload`, `ecr:BatchGetImage`, `ecr:InitiateLayerUpload`, `ecr:BatchCheckLayerAvailability`, `ecr:UploadLayerPart`
241 |
242 | 
243 |
244 | Click in **Save**
245 |
246 | You permissions should look exactly like this:
247 |
248 | 
249 |
250 | Next step, we need to change de IAM role associated with our CodeBuild environment. In the AWS Management Console, go to **Services** > in the search field type `iam` and select **IAM** from the drop down list
251 |
252 | 
253 |
254 | On the left side menu, click in **Roles**. This will list all the roles in your account.
255 |
256 | Type the role name in the search field. Click in the IAM role that appears.
257 |
258 | 
259 |
260 | In the **Permissions** tab click in **Attach policies**
261 |
262 | 
263 |
264 | In the serch field type `registry` and select `AmazonEC2ContainerRegistryPowerUser`. Click in **Attach policy**
265 |
266 | 
267 |
268 | Your permissions should look like this:
269 |
270 | 
271 |
272 | Now let's go ahead and configure our test build.
273 |
274 | On the AWS Management Console, click in **Services** > in the search field type `build` and select **CodeBuild** from the drop down list.
275 |
276 | In **CodeBuild**, on the left side, click in **Build projects**. Select your project by clicking in the radio button and then click in **Start build**
277 |
278 | For **Branch** select `master`. Leave everything else with the default configuration and click in **Start build**
279 |
280 | 
281 |
282 | The build phase might take a while to finish. Once its completed, you should see all the **Phase details** as `Succeeded`.
283 |
284 | 
285 |
286 | ## 4. Configuring a Continuous Delivery pipeline
287 |
288 | Now that our Source (CodeCommit), Build (CodeBuild) and Deploy (ECS) stages are done, we need a tool to orchestrate and connect all of them. To achieve this we will use AWS CodePipeline.
289 |
290 | AWS CodePipeline already has the concepts of Stages (Source, Build, Test, Deploy, Approval, Invoke). All we need to do is to create a pipeline, and for each stage, choose the correlated service. For example, when configuring the Source stage, we will choose our CodeCommit respository. And so on...
291 |
292 | Le'ts start with the Source Stage:
293 |
294 | On the AWS Management Console, click in **Services** > in search field type `pipeline` and select **CodePipeline** from the drop down list.
295 |
296 | 
297 |
298 | If this is your first time using CodePipeline, click in **Get started**.
299 |
300 | 
301 |
302 | Otherwise click in **Create pipeline**
303 |
304 | 
305 |
306 | In **Pipeline name** type `containers-workshop-pipeline` and click in **Next**
307 |
308 | 
309 |
310 | For **Source provider** select **CodeCommit**
311 |
312 | 
313 |
314 | For **Repository name** select the respository created for this workshop `containers-workshop-repository`
315 |
316 | For **Branch name** select `master`
317 |
318 | Click in **Next**
319 |
320 | 
321 |
322 | We are now configuring the Buid Stage:
323 |
324 | For **Build provider** select **CodeBuild**
325 |
326 | 
327 |
328 | For **Project name** select `containers-workshop-build` and click in **Next**
329 |
330 | 
331 |
332 | Finally, it's time to configure the last stage of our pipeline: the Deploy Stage.
333 |
334 | For **Deployment provider** select **Amazon ECS**
335 |
336 | 
337 |
338 | For **Cluster name** select `containers-workshop-ecs-cluster`
339 |
340 | For **Service name** select `containers-workshop-ecs-service`
341 |
342 | For **Image filename** type `imagedefinitions.json`
343 |
344 | Click in **Next**
345 |
346 | Click in **Create pipeline**.
347 |
348 | You should see now that AWS CodePiepline will automatically start the pipeline.
349 |
350 | 
351 |
352 | The whole process should take around 10 minutes. All three stages should be completed as `Succeeded`.
353 |
354 | >NOTE: If your pipeline fails, one of the potential reasons could be a permission issue. Check if the IAM Role created by your CodePipeline has ECS full permissions by going to Services > IAM > Roles. Type in the search bar the name of the role and click on it. In **Permissions policies** check if the policy attached to it has "ecs:*". If not, click in **Attach policies** and search for `AmazonECS_FullAccess`. Select it and click in **Attach policy**.
355 |
356 |
357 | 
358 |
359 |
360 | If you go to the URL of your app you won't see any changes because we didn't change anything. So now, let's do exactly that. Let's change something on our app to see the modification being deployed automatically.
361 |
362 | ## 5. Testing our pipeline
363 |
364 | Go to your Cloud9 enviroment. On the left side menu, expand `MyCloud9Instance > containers-workshop-repository > app`
365 |
366 | Right click in the `index.html` > Open
367 |
368 | 
369 |
370 | A new tab will open. In line 37, before `This application is running inside a container!`, add the following text: `This is the version 2!`. Should look like this:
371 |
372 | 
373 |
374 | Save it (Ctrl+S or Command+S)
375 |
376 | Now let's commit our change to the CodeCommit repository. Go to the Terminal tab and type
377 |
378 | cd /home/ec2-user/environment/containers-workshop-repository/app
379 | git add index.html
380 | git commit -m "Changing the text"
381 | git push
382 |
383 |
384 | Watch the CodePipeline being executed. You will see in a minute or so, the Source stage changing to `In Progress`. Wait until the Staging source is done.
385 |
386 |
387 | 
388 |
389 |
390 | Go to your app URL and see the new text!
391 |
392 |
393 |
394 | [][back-to-menu] [][continue-workshop]
395 |
396 | [back-to-menu]: https://github.com/bemer/containers-on-aws-workshop
397 | [continue-workshop]: /06-AutoScaling
398 |
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/buildspec_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/buildspec_list.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/buildspec_save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/buildspec_save.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/ci_cd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/ci_cd.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/cloud9_edit_html.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/cloud9_edit_html.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/cloud9_new_file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/cloud9_new_file.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/cloud9_open_index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/cloud9_open_index.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codebuild.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codebuild.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codebuild_create_project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codebuild_create_project.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codebuild_find_iam_role.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codebuild_find_iam_role.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codebuild_get_started.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codebuild_get_started.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codebuild_list_project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codebuild_list_project.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codebuild_succeeded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codebuild_succeeded.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codebuild_test_project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codebuild_test_project.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codecommit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codecommit.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codecommit_clone_repository.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codecommit_clone_repository.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codecommit_create_repository.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codecommit_create_repository.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codecommit_create_repository_II.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codecommit_create_repository_II.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codecommit_get_started.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codecommit_get_started.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codecommit_list_files.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codecommit_list_files.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codepipeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codepipeline.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codepipeline_create.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codepipeline_create.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codepipeline_create_build.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codepipeline_create_build.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codepipeline_create_build_ii.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codepipeline_create_build_ii.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codepipeline_deploy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codepipeline_deploy.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codepipeline_deploy_ii.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codepipeline_deploy_ii.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codepipeline_final_test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codepipeline_final_test.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codepipeline_get_started.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codepipeline_get_started.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codepipeline_iam.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codepipeline_iam.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codepipeline_next.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codepipeline_next.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codepipeline_repository_ii.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codepipeline_repository_ii.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codepipeline_running.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codepipeline_running.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codepipeline_source.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codepipeline_source.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/codepipeline_succeeded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/codepipeline_succeeded.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/ecr_actions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/ecr_actions.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/ecr_actions_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/ecr_actions_back.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/ecr_add_permissions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/ecr_add_permissions.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/ecr_add_permissions_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/ecr_add_permissions_back.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/ecr_review_permissions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/ecr_review_permissions.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/ecr_select.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/ecr_select.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/iam.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/iam.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/iam_attach_policies.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/iam_attach_policies.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/iam_filter_role.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/iam_filter_role.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/iam_permissions_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/iam_permissions_list.png
--------------------------------------------------------------------------------
/05-ContinuousDelivery/images/iam_registry_policy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/05-ContinuousDelivery/images/iam_registry_policy.png
--------------------------------------------------------------------------------
/06-AutoScaling/README.md:
--------------------------------------------------------------------------------
1 | # Configuring Service Auto Scaling on Amazon ECS
2 |
3 | 
4 |
5 | ## Quick jump:
6 |
7 | * [1. Tutorial overview](/06-AutoScaling#1-tutorial-overview)
8 | * [2. Configuring the Service Auto Scaling](/06-AutoScaling#2-configuring-the-service-auto-scaling)
9 | * [3. Generating Load](/06-AutoScaling#3-generating-load)
10 | * [4. Scaling your environment](/06-AutoScaling#4-scaling-your-environment)
11 |
12 | ## 1. Tutorial overview
13 |
14 | At this moment, you should be able to run your application inside a container and deploy it on ECS as a *service*, but as you probably noticed, we didn't create any rule or used any tool to automatically scale the number of containers running in our cluster.
15 |
16 | When working with Amazon ECS, we can also take advantage of Auto Scaling features, that will allow us to add more containers of a specific task definition according to some metrics that are already available. In this part of our workshop, we will create some Auto Scaling rules with our service, in order to keep our application available even during access peaks.
17 |
18 | ## 2. Configuring the Service Auto Scaling
19 |
20 | When we talk about scaling on ECS, we need to keep in mind that there are two things to be scaled during an event or an access peak: the **number of tasks** of a given service and the **number of instances** within your ECS cluster. In this workshop we are going to cover the auto scaling configuration for the tasks only. If you wish to learn more about EC2 Auto Scaling, you can get more information in [this link](https://aws.amazon.com/pt/autoscaling/).
21 |
22 | Let's get started.
23 |
24 | In the AWS Management Console, go to ECS. On the left side menu, click in **Clusters** and click in the cluster `containers-workshop-ecs-cluster`. Find the **Services** tab, select the service `containers-workshop-ecs-service` and click in **Update**:
25 |
26 | 
27 |
28 | Now, in the `Configure service` screen, just click in **Next step**. Click in `Next step` again under `Configure network` screen. You will reach the `Set Auto Scaling` screen. Here is where we are going to make the first changes.
29 |
30 | Under `Service Auto Scaling`, select the option `Configure Service Auto Scaling to adjust your service’s desired count`. Now, use the following values on the fields:
31 |
32 | **Minimum number of tasks**: 1
33 |
34 | **Desired number of tasks**: 1
35 |
36 | **Maximum number of tasks**: 5
37 |
38 | 
39 |
40 | After adding this information, let's add a new `scaling policy`, which will execute the scaling actions in your cluster based in some specific metrics. Click in the button `Add scaling policy`.
41 |
42 | In this screen, give your policy the name `containers-workshop-ecs-scaling-policy`. In this workshop, we are going to scale the tasks every time the metric `ECSServiceAverageCPUUtilization` reaches 10%. Add the value `10` in `Target value`, change the `Scale-out cooldown period` and the `Scale-in cooldown period` to `30`.
43 |
44 | >NOTE: We are using lower values just to see the scaling in action very quickly, and also, we will be generating load using just one EC2 instance. In a real world scenario, you might want to use higher values to scale your application.
45 |
46 | Leave the other parameters with the default values and then click in `Save`:
47 |
48 | 
49 |
50 | After saving the policy, click in `Next step`, review your configurations and then click in `Update Service`.
51 |
52 | You can check the `Auto Scaling` configurations of your service by clicking in the service `containers-workshop-ecs-service` under your cluster, and then selecting the tab `Auto Scaling`:
53 |
54 | 
55 |
56 | ## 3. Generating Load
57 |
58 | Now that we have our Service Auto Scaling configured, we need to generate load in order to scale the number of running tasks in our cluster. To do so, we will be using an open source tool called `Locust`. You can find more information about Locust in [their documentation](https://docs.locust.io/en/stable/).
59 |
60 | Since the focus of this workshop is understanding how to run containers on AWS, we will provide you a CloudFormation template that will create an EC2 instance, install and configure Locust in it.
61 |
62 | You can use one of the following templates to provision the load testing stack in your account.
63 |
64 | >NOTE: You must deploy this CloudFormation template in the same region where you created your VPC otherwise it will not work.
65 |
66 | |Deploy | Region |
67 | |:---:|:---:|
68 | |[][us-east-1-load-testing] | US East (N. Virginia)|
69 | |[][us-east-2-load-testing] | US East (Ohio)|
70 | |[][us-west-2-load-testing] | US West (Oregon)|
71 | |[][eu-west-1-load-testing] | EU (Ireland)|
72 | |[][ap-southeast-1-load-testing] | Asia Pacific (Singapore)|
73 |
74 |
75 | When provisioning the template, you will be asked to input some information. For the `HTTP Location` parameter, you can add you public IP Address or just leave it as the default.
76 |
77 | Since we will be generating a large ammount of load, it's recommended that you use a large instance type. We are setting the default as `m5.xlarge`.
78 |
79 | In order to provision the EC2 instance, you will need to have a keypar created under your EC2 console. If you are using a new account and don't have a keypar created, you can follow [this link](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html#having-ec2-create-your-key-pair) to learn how to create it.
80 |
81 | Under `Load Balancer URL`, you should add the hostname of your Load Balancer. This is the same name that you used to access your application in the step [04-Deploy ECS Cluster](/04-DeployEcsCluster#6-testing-our-service-deployments-from-the-console-and-the-alb).
82 |
83 | 
84 |
85 | Then, click in `Next` and in the Options screen, click in `Next` again. Under the Review screen, validate your configurations and click in `Create`.
86 |
87 | After creating your new Stack, you should see a URL that point to your EC2 instance with the Locust installed:
88 |
89 | 
90 |
91 | Click in this URL and you will be redirected to the Locust page in your instance. In this screen, you can see that the `HOST` is pointing to your Load Balancer hostname. Now, under `Number of users to simulate` you can add `20000` and under `Hatch rate` add `500`:
92 |
93 | 
94 |
95 | After configuring Locust, you can click in `Start swarming`.
96 |
97 | This will start to simulate 20000 users accessing your application. You can follow the results in the following screen:
98 |
99 | 
100 |
101 | ## 4. Scaling your environment
102 |
103 | After generating load against your application, you should be able to see it scaling after a few seconds. Go to you `containers-workshop-ecs-cluster` and click in the service `containers-workshop-ecs-service`. Go to the `Events` tab and you will find the message saying that the desired count of tasks have changed:
104 |
105 | 
106 |
107 |
108 |
109 | [][back-to-menu]
110 |
111 | [back-to-menu]: https://github.com/bemer/containers-on-aws-workshop
112 |
113 |
114 | [us-east-1-load-testing]: https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=containers-workshop-load-testing&templateURL=https://s3.amazonaws.com/containers-on-aws-workshop-vpc/load_test_instance.json
115 | [us-east-2-load-testing]: https://console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks/new?stackName=containers-workshop-load-testing&templateURL=https://s3.amazonaws.com/containers-on-aws-workshop-vpc/load_test_instance.json
116 | [us-west-2-load-testing]: https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?stackName=containers-workshop-load-testing&templateURL=https://s3.amazonaws.com/containers-on-aws-workshop-vpc/load_test_instance.json
117 | [eu-west-1-load-testing]: https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?stackName=containers-workshop-load-testing&templateURL=https://s3.amazonaws.com/containers-on-aws-workshop-vpc/load_test_instance.json
118 | [ap-southeast-1-load-testing]: https://console.aws.amazon.com/cloudformation/home?region=ap-southeast-1#/stacks/new?stackName=containers-workshop-load-testing&templateURL=https://s3.amazonaws.com/containers-on-aws-workshop-vpc/load_test_instance.json
119 |
--------------------------------------------------------------------------------
/06-AutoScaling/cloudformation/load_test_instance.json:
--------------------------------------------------------------------------------
1 | {
2 | "AWSTemplateFormatVersion" : "2010-09-09",
3 |
4 | "Description" : "This template deploys a instance and installs and configures the locust.io in order to generate load against the ECS cluster to scale out the service.",
5 |
6 | "Parameters" : {
7 | "KeyName": {
8 | "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instance",
9 | "Type": "AWS::EC2::KeyPair::KeyName",
10 | "ConstraintDescription" : "must be the name of an existing EC2 KeyPair."
11 | },
12 |
13 | "InstanceType" : {
14 | "Description" : "Locust.io EC2 instance type",
15 | "Type" : "String",
16 | "Default" : "m5.xlarge",
17 | "AllowedValues" : [ "m5.large", "m5.xlarge", "m5.2xlarge", "m5.4xlarge", "m5.12xlarge", "m5.24xlarge"],
18 | "ConstraintDescription" : "must be a valid EC2 instance type."
19 | },
20 |
21 | "HTTPLocation" : {
22 | "Description" : "The IP address range that can be used to access the EC2 instances",
23 | "Type": "String",
24 | "MinLength": "9",
25 | "MaxLength": "18",
26 | "Default": "0.0.0.0/0",
27 | "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
28 | "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
29 | },
30 |
31 | "LoadBalancerURL": {
32 | "Description" : "URL of your load balancer",
33 | "Type" : "String"
34 | }
35 | },
36 |
37 | "Mappings" : {
38 | "AWSInstanceType2Arch" : {
39 | "t1.micro" : { "Arch" : "PV64" },
40 | "t2.nano" : { "Arch" : "HVM64" },
41 | "t2.micro" : { "Arch" : "HVM64" },
42 | "t2.small" : { "Arch" : "HVM64" },
43 | "t2.medium" : { "Arch" : "HVM64" },
44 | "t2.large" : { "Arch" : "HVM64" },
45 | "m1.small" : { "Arch" : "PV64" },
46 | "m1.medium" : { "Arch" : "PV64" },
47 | "m1.large" : { "Arch" : "PV64" },
48 | "m1.xlarge" : { "Arch" : "PV64" },
49 | "m2.xlarge" : { "Arch" : "PV64" },
50 | "m2.2xlarge" : { "Arch" : "PV64" },
51 | "m2.4xlarge" : { "Arch" : "PV64" },
52 | "m3.medium" : { "Arch" : "HVM64" },
53 | "m3.large" : { "Arch" : "HVM64" },
54 | "m3.xlarge" : { "Arch" : "HVM64" },
55 | "m3.2xlarge" : { "Arch" : "HVM64" },
56 | "m5.large" : { "Arch" : "HVM64" },
57 | "m5.xlarge" : { "Arch" : "HVM64" },
58 | "m5.2xlarge" : { "Arch" : "HVM64" },
59 | "m5.4xlarge" : { "Arch" : "HVM64" },
60 | "m5.12xlarge" : { "Arch" : "HVM64" },
61 | "m5.24xlarge" : { "Arch" : "HVM64" },
62 | "c1.medium" : { "Arch" : "PV64" },
63 | "c1.xlarge" : { "Arch" : "PV64" },
64 | "c3.large" : { "Arch" : "HVM64" },
65 | "c3.xlarge" : { "Arch" : "HVM64" },
66 | "c3.2xlarge" : { "Arch" : "HVM64" },
67 | "c3.4xlarge" : { "Arch" : "HVM64" },
68 | "c3.8xlarge" : { "Arch" : "HVM64" },
69 | "c4.large" : { "Arch" : "HVM64" },
70 | "c4.xlarge" : { "Arch" : "HVM64" },
71 | "c4.2xlarge" : { "Arch" : "HVM64" },
72 | "c4.4xlarge" : { "Arch" : "HVM64" },
73 | "c4.8xlarge" : { "Arch" : "HVM64" },
74 | "g2.2xlarge" : { "Arch" : "HVMG2" },
75 | "g2.8xlarge" : { "Arch" : "HVMG2" },
76 | "r3.large" : { "Arch" : "HVM64" },
77 | "r3.xlarge" : { "Arch" : "HVM64" },
78 | "r3.2xlarge" : { "Arch" : "HVM64" },
79 | "r3.4xlarge" : { "Arch" : "HVM64" },
80 | "r3.8xlarge" : { "Arch" : "HVM64" },
81 | "i2.xlarge" : { "Arch" : "HVM64" },
82 | "i2.2xlarge" : { "Arch" : "HVM64" },
83 | "i2.4xlarge" : { "Arch" : "HVM64" },
84 | "i2.8xlarge" : { "Arch" : "HVM64" },
85 | "d2.xlarge" : { "Arch" : "HVM64" },
86 | "d2.2xlarge" : { "Arch" : "HVM64" },
87 | "d2.4xlarge" : { "Arch" : "HVM64" },
88 | "d2.8xlarge" : { "Arch" : "HVM64" },
89 | "hi1.4xlarge" : { "Arch" : "HVM64" },
90 | "hs1.8xlarge" : { "Arch" : "HVM64" },
91 | "cr1.8xlarge" : { "Arch" : "HVM64" },
92 | "cc2.8xlarge" : { "Arch" : "HVM64" }
93 | },
94 |
95 | "AWSInstanceType2NATArch" : {
96 | "t1.micro" : { "Arch" : "NATPV64" },
97 | "t2.nano" : { "Arch" : "NATHVM64" },
98 | "t2.micro" : { "Arch" : "NATHVM64" },
99 | "t2.small" : { "Arch" : "NATHVM64" },
100 | "t2.medium" : { "Arch" : "NATHVM64" },
101 | "t2.large" : { "Arch" : "NATHVM64" },
102 | "m1.small" : { "Arch" : "NATPV64" },
103 | "m1.medium" : { "Arch" : "NATPV64" },
104 | "m1.large" : { "Arch" : "NATPV64" },
105 | "m1.xlarge" : { "Arch" : "NATPV64" },
106 | "m2.xlarge" : { "Arch" : "NATPV64" },
107 | "m2.2xlarge" : { "Arch" : "NATPV64" },
108 | "m2.4xlarge" : { "Arch" : "NATPV64" },
109 | "m3.medium" : { "Arch" : "NATHVM64" },
110 | "m3.large" : { "Arch" : "NATHVM64" },
111 | "m3.xlarge" : { "Arch" : "NATHVM64" },
112 | "m3.2xlarge" : { "Arch" : "NATHVM64" },
113 | "m5.large" : { "Arch" : "NATHVM64" },
114 | "m5.xlarge" : { "Arch" : "NATHVM64" },
115 | "m5.2xlarge" : { "Arch" : "NATHVM64" },
116 | "m5.4xlarge" : { "Arch" : "NATHVM64" },
117 | "m5.12xlarge" : { "Arch" : "NATHVM64" },
118 | "m5.24xlarge" : { "Arch" : "NATHVM64" },
119 | "c1.medium" : { "Arch" : "NATPV64" },
120 | "c1.xlarge" : { "Arch" : "NATPV64" },
121 | "c3.large" : { "Arch" : "NATHVM64" },
122 | "c3.xlarge" : { "Arch" : "NATHVM64" },
123 | "c3.2xlarge" : { "Arch" : "NATHVM64" },
124 | "c3.4xlarge" : { "Arch" : "NATHVM64" },
125 | "c3.8xlarge" : { "Arch" : "NATHVM64" },
126 | "c4.large" : { "Arch" : "NATHVM64" },
127 | "c4.xlarge" : { "Arch" : "NATHVM64" },
128 | "c4.2xlarge" : { "Arch" : "NATHVM64" },
129 | "c4.4xlarge" : { "Arch" : "NATHVM64" },
130 | "c4.8xlarge" : { "Arch" : "NATHVM64" },
131 | "g2.2xlarge" : { "Arch" : "NATHVMG2" },
132 | "g2.8xlarge" : { "Arch" : "NATHVMG2" },
133 | "r3.large" : { "Arch" : "NATHVM64" },
134 | "r3.xlarge" : { "Arch" : "NATHVM64" },
135 | "r3.2xlarge" : { "Arch" : "NATHVM64" },
136 | "r3.4xlarge" : { "Arch" : "NATHVM64" },
137 | "r3.8xlarge" : { "Arch" : "NATHVM64" },
138 | "i2.xlarge" : { "Arch" : "NATHVM64" },
139 | "i2.2xlarge" : { "Arch" : "NATHVM64" },
140 | "i2.4xlarge" : { "Arch" : "NATHVM64" },
141 | "i2.8xlarge" : { "Arch" : "NATHVM64" },
142 | "d2.xlarge" : { "Arch" : "NATHVM64" },
143 | "d2.2xlarge" : { "Arch" : "NATHVM64" },
144 | "d2.4xlarge" : { "Arch" : "NATHVM64" },
145 | "d2.8xlarge" : { "Arch" : "NATHVM64" },
146 | "hi1.4xlarge" : { "Arch" : "NATHVM64" },
147 | "hs1.8xlarge" : { "Arch" : "NATHVM64" },
148 | "cr1.8xlarge" : { "Arch" : "NATHVM64" },
149 | "cc2.8xlarge" : { "Arch" : "NATHVM64" }
150 | }
151 | ,
152 | "AWSRegionArch2AMI" : {
153 | "us-east-1" : {"PV64" : "ami-2a69aa47", "HVM64" : "ami-97785bed", "HVMG2" : "ami-0a6e3770"},
154 | "us-west-2" : {"PV64" : "ami-7f77b31f", "HVM64" : "ami-f2d3638a", "HVMG2" : "ami-ee15a196"},
155 | "us-west-1" : {"PV64" : "ami-a2490dc2", "HVM64" : "ami-824c4ee2", "HVMG2" : "ami-0da4a46d"},
156 | "eu-west-1" : {"PV64" : "ami-4cdd453f", "HVM64" : "ami-d834aba1", "HVMG2" : "ami-af8013d6"},
157 | "eu-west-2" : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-403e2524", "HVMG2" : "NOT_SUPPORTED"},
158 | "eu-west-3" : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-8ee056f3", "HVMG2" : "NOT_SUPPORTED"},
159 | "eu-central-1" : {"PV64" : "ami-6527cf0a", "HVM64" : "ami-5652ce39", "HVMG2" : "ami-1d58ca72"},
160 | "ap-northeast-1" : {"PV64" : "ami-3e42b65f", "HVM64" : "ami-ceafcba8", "HVMG2" : "ami-edfd658b"},
161 | "ap-northeast-2" : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-863090e8", "HVMG2" : "NOT_SUPPORTED"},
162 | "ap-northeast-3" : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-83444afe", "HVMG2" : "NOT_SUPPORTED"},
163 | "ap-southeast-1" : {"PV64" : "ami-df9e4cbc", "HVM64" : "ami-68097514", "HVMG2" : "ami-c06013bc"},
164 | "ap-southeast-2" : {"PV64" : "ami-63351d00", "HVM64" : "ami-942dd1f6", "HVMG2" : "ami-85ef12e7"},
165 | "ap-south-1" : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-531a4c3c", "HVMG2" : "ami-411e492e"},
166 | "us-east-2" : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-f63b1193", "HVMG2" : "NOT_SUPPORTED"},
167 | "ca-central-1" : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-a954d1cd", "HVMG2" : "NOT_SUPPORTED"},
168 | "sa-east-1" : {"PV64" : "ami-1ad34676", "HVM64" : "ami-84175ae8", "HVMG2" : "NOT_SUPPORTED"},
169 | "cn-north-1" : {"PV64" : "ami-77559f1a", "HVM64" : "ami-cb19c4a6", "HVMG2" : "NOT_SUPPORTED"},
170 | "cn-northwest-1" : {"PV64" : "ami-80707be2", "HVM64" : "ami-3e60745c", "HVMG2" : "NOT_SUPPORTED"}
171 | }
172 |
173 | },
174 |
175 | "Resources" : {
176 | "EC2Instance" : {
177 | "Type" : "AWS::EC2::Instance",
178 | "Properties" : {
179 | "SubnetId": { "Fn::ImportValue" : "containers-workshop-public-subnet" },
180 | "InstanceType" : { "Ref" : "InstanceType" },
181 | "SecurityGroupIds" : [ { "Fn::GetAtt" : [ "InstanceSecurityGroup", "GroupId" ] } ],
182 | "KeyName" : { "Ref" : "KeyName" },
183 | "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
184 | { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
185 | "Tags" : [
186 | {
187 | "Key" : "Name",
188 | "Value" : "containers-workshop-loadtest"
189 | }
190 | ],
191 | "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
192 | "#!/bin/bash -xe\n",
193 | "yum update -y && yum install -y python python-pip\n",
194 | "python -m pip install locustio\n",
195 | "ulimit -n 65535\n",
196 | "cat > /home/ec2-user/locustfile.py < /tmp/file-created.txt\n"
224 | ]]}} },
225 | "CreationPolicy": {
226 | "ResourceSignal": {
227 | "Timeout": "PT5M"
228 | }
229 | }
230 | },
231 |
232 | "InstanceSecurityGroup" : {
233 | "Type" : "AWS::EC2::SecurityGroup",
234 | "Properties" : {
235 | "VpcId" : { "Fn::ImportValue" : "containers-workshop-vpc" },
236 | "GroupDescription" : "Enable HTTP access via port 80",
237 | "SecurityGroupIngress" : [ {
238 | "IpProtocol" : "tcp",
239 | "FromPort" : "80",
240 | "ToPort" : "80",
241 | "CidrIp" : { "Ref" : "HTTPLocation"}
242 | } ]
243 | }
244 | }
245 | },
246 |
247 | "Outputs" : {
248 | "LoadTestingURL" : {
249 | "Description" : "URL to your instance with Locust",
250 | "Value" : { "Fn::Join" : ["", [
251 | "http://",
252 | { "Fn::GetAtt" : [ "EC2Instance", "PublicDnsName" ] },
253 | "/"
254 | ]]}
255 | }
256 | }
257 | }
258 |
--------------------------------------------------------------------------------
/06-AutoScaling/images/auto_scaling.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/06-AutoScaling/images/auto_scaling.png
--------------------------------------------------------------------------------
/06-AutoScaling/images/ecs_scaling_policy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/06-AutoScaling/images/ecs_scaling_policy.png
--------------------------------------------------------------------------------
/06-AutoScaling/images/load_test_cfn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/06-AutoScaling/images/load_test_cfn.png
--------------------------------------------------------------------------------
/06-AutoScaling/images/load_test_output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/06-AutoScaling/images/load_test_output.png
--------------------------------------------------------------------------------
/06-AutoScaling/images/locust_main_screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/06-AutoScaling/images/locust_main_screen.png
--------------------------------------------------------------------------------
/06-AutoScaling/images/locust_test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/06-AutoScaling/images/locust_test.png
--------------------------------------------------------------------------------
/06-AutoScaling/images/number_of_tasks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/06-AutoScaling/images/number_of_tasks.png
--------------------------------------------------------------------------------
/06-AutoScaling/images/scaling_message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/06-AutoScaling/images/scaling_message.png
--------------------------------------------------------------------------------
/06-AutoScaling/images/service_auto_scaling.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/06-AutoScaling/images/service_auto_scaling.png
--------------------------------------------------------------------------------
/06-AutoScaling/images/update_service.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/06-AutoScaling/images/update_service.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Welcome to the Containers On AWS Workshop
4 |
5 | Hello and welcome to the Containers On AWS Workshop! Please, read the instructions bellow carefully.
6 |
7 | ## 1. It's all about containers!
8 |
9 | We will walk you through the very basics of containers: from installing and configuring Docker, running containers locally, deploying them on AWS container services like Elastic Container Services (ECS), till implementing a Continuous Delivery pipeline for your container and help you configure Auto Scaling for your containerized app.
10 |
11 | ## 2. If you are using a Windows machine
12 |
13 | We strongly recommend you spinning up a Cloud9 environment. Optionally, you can spin up an EC2 instance with Amazon Linux.
14 |
15 | If you choose Cloud9, all you have to do is jump to [01-EnvironmentSetup](https://github.com/bemer/containers-on-aws-workshop/tree/master/01-EnvironmentSetup).
16 |
17 | If you want to run on a EC2 instance, the following links will guide you through the instance creation process and how to access it:
18 |
19 | * [Creating a Linux EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EC2_GetStarted.html)
20 | * [Accessing a Linux EC2 instance from a Windows machine](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/putty.html)
21 |
22 | ## 3. We strongly recommend you running this workshop in the following order:
23 |
24 | * [1. Environment Setup](/01-EnvironmentSetup)
25 | * [2. Creating Your Docker Image](/02-CreatingDockerImage)
26 | * [3. Deploying An ECS Cluster](/03-DeployEcsCluster)
27 | * [4. Deploying An Application with AWS Fargate](/04-DeployFargate)
28 | * [5. Creating a Continuous Delivery Pipeline with Code services and Amazon ECS](/05-ContinuousDelivery)
29 | * [6. Configuring Service Auto Scaling on Amazon ECS](/06-AutoScaling)
30 |
31 | ## 4. Enough of jibber jabber...
32 |
33 | You can start the Containers on AWS workshop by clicking in the following link:
34 |
35 | [][start_workshop]
36 |
37 | [start_workshop]: /01-EnvironmentSetup
38 |
--------------------------------------------------------------------------------
/images/back_to_menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/images/back_to_menu.png
--------------------------------------------------------------------------------
/images/containers-on-aws-worshop-logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/images/containers-on-aws-worshop-logo.jpg
--------------------------------------------------------------------------------
/images/continue_workshop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/images/continue_workshop.png
--------------------------------------------------------------------------------
/images/start_workshop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bemer/containers-on-aws-workshop/58453fe5096ec58de57a297fd78102806d299dac/images/start_workshop.png
--------------------------------------------------------------------------------