Deploying New Container Using AWS App2Container
Tags: aws, dotnet, docker, app2container
Published: 2022-07-07 03:19:08

In our last article, we went through the containerization of a running application. The last step of this process is to deploy the container.  The default approach is to deploy a container image to ECR and then create the CloudFormation templates to run that image in Amazon ECS using Fargate. If you would prefer to deploy to Amazon EKS instead, you will need to go to the _deployment.json_ file in the output directory. This editable file contains the default settings for the application, ECR, ECS, and EKS. We will walk through each of the major areas in turn.

The first section is responsible for defining the application and is shown below.

```
"a2CTemplateVersion": "1.0",
"applicationId": "iis-tradeyourtools-6bc0a317",
"imageName": "iis-tradeyourtools-6bc0a317",
"exposedPorts": [
       {
              "localPort": 80,
              "protocol": "http"
       }
],
"environment": [],
```

The _applicationId_ and the _imageName_ are values we have seen before when going through App2Containers. The _exposedPorts_ value should contain all of the IIS ports configured for the application. The one used in the example was not configured for HTTPS, but if it was there would be another entry for that value. The environment value allows you to enter any environment variables as key/value pairs that may be used by the application. Unfortunately, App2Container is not able to determine those because it does its analysis on running code rather than the code base. In our example, there are no environmental variables that are necessary.

_**Note** – If you aren’t sure whether there are environment variables that your application may access, you can see which variables are available by going into the **System -> Advanced system settings -> Environment variables**. This will provide you with a list of available variables and you can evaluate those as to their relevance to your application._

The next section is quite small and contains the ECR configuration. The ECR repository that will be created is named with the _imageName_ from above and then versioned with the value in the _ecrRepoTag_ as shown below.

```
"ecrParameters": {
       "ecrRepoTag": "latest"
},
```

We are using the value _latest_ as our version tag.

There are two remaining sections in the deployment.json file. The first is the ECS setup information with the second being the EKS setup information. We will first look at the ECS section. This entire section is listed below.

```
"ecsParameters": {
       "createEcsArtifacts": true,
       "ecsFamily": "iis-tradeyourtools-6bc0a317",
       "cpu": 2,
       "memory": 4096,
       "dockerSecurityOption": "",
       "enableCloudwatchLogging": false,
       "publicApp": true,
       "stackName": "a2c-iis-tradeyourtools-6bc0a317-ECS",
       "resourceTags": [
              {
                     "key": "example-key",
                     "value": "example-value"
              }
       ],
       "reuseResources": {
              "vpcId": "vpc-f4e4d48c",
              "reuseExistingA2cStack": {
                     "cfnStackName": "",
                     "microserviceUrlPath": ""
              },
              "sshKeyPairName": "",
              "acmCertificateArn": ""
       },
       "gMSAParameters": {
              "domainSecretsArn": "",
              "domainDNSName": "",
              "domainNetBIOSName": "",
              "createGMSA": false,
              "gMSAName": ""
       },
       "deployTarget": "FARGATE",
       "dependentApps": []
},
```

The most important value here is _createEcsArtifacts_, which if set to true means that deploying with App2Container will deploy the image into ECS. The next ones to look at are _cpu_ and _memory_. These values are only used for Linux containers. In our case, these values do not matter because this is a Windows container. The next two values, _dockerSecurityOption_ and _enableCloudwatchLogging_ are only changed in special cases, so they will generally stay at their default values. The next value, _publicApp_, determines whether the application will be configured into a public subnet with a public endpoint. This is set to _true_ because this is our hoped-for behavior. The next value, _stackName_, defines the name of the CloudFormation stack while the value after that, _resourceTags_, are the custom tags that should be added to the ECS task definition. There is a default set of key/values in the file, but those will not be used if kept in; only keys that are not defined as **example-key** will be added.

The next section, _reuseResources_, is where you can configure whether you wish to use any pre-existing resources, namely VPC – which is added to the vpcId value. When left blank, as shown below, App2Container will create a new VPC.

```
"reuseResources": {
     "vpcId": "",
     "reuseExistingA2cStack": {
            "cfnStackName": "",
            "microserviceUrlPath": ""
     },
     "sshKeyPairName": "",
     "acmCertificateArn": ""
}
```

Running the deployment with these settings will result in a brand new VPC being created. This means that, by default, you wouldn’t be able to connect in or out of the VPC without making changes to the VPC. If, however, you have an already existing VPC that your want to use, update the _vpcId_ key with the ID of the appropriate VPC.

_**Note**: App2Container requires that the included VPS has a routing table that is associated with at least two subnets and an internet gateway. The CloudFormation template for the ECS service requires this so that there is a route from your service to the internet from at least two different AZs for availability. Currently, there is no way for you to define these subnets. You will receive a **Resource creation failures: PublicLoadBalancer: At least two subnets in two different Availability Zones must be specified** message if your VPC is not set up properly._

You can also choose to reuse an existing stack created by App2Container. Doing this will ensure that the application is deployed into the already existing VPC and that the URL for the new application is added to the already created Application Load Balancer rather than being added to a new ALB.

The next value, _sshKeyPairName_, is the name of the EC2 key pair used for the instances on which your container runs. Using this rather defeats the point of using containers, so we left it blank as well. The last value, _acmCertificateArn_, is for the AWS Certificate Manager ARN that you want to use if you are enabling HTTPS on the created ALB. This parameter is required if you use an HTTPS endpoint for your ALB, and remember as we went over earlier this means that the request being forwarded into the application will be on port 80 and unencrypted because this would have been handled in the ALB.

The next set of configuration values are part of the _gMSAParameters_ section. This becomes important to manage if your application relies upon group Managed Service Account (gMSA) Active Directory groups. This can only be used if deploying to EC2 and not Fargate (more on this later). These individual values are:

- _domainSecretsArn_ – The AWS Secrets Manager ARN containing the domain credentials required to join the ECS nodes to Active Directory.
- _domainDNSName_ – The DNS Name of the Active Directory the ECS nodes will join.
- _domainNetBIOSName_ – The NetBIOS name of the Active Directory to join.
- _createGMSA_ – A flag determining whether to create the gMSA Active Directory security group and account using the name supplied in the gMSAName field.
- _gMSAName_ – The name of the Active Directory account the container should use for access.

There are two fields remaining, _deployTarget_ and _dependentApps_. For deployTarget there are two valid values for .NET applications running on Windows; _fargate_ and _ec2_. You can only deploy to Fargate if your container is Windows 2019 or more recent. This would only be possible if your worker machine, the one you used for containerizing, was running Windows 2019+. Also, you cannot deploy to Fargate if you are using gMSA.

The value _dependentApps_ is interesting, as it handles those applications that AWS defines as “complex Windows applications”. We won’t go into it in more detail here, but you can go to [https://docs.aws.amazon.com/app2container/latest/UserGuide/summary-complex-win-apps.html](https://docs.aws.amazon.com/app2container/latest/UserGuide/summary-complex-win-apps.html) if you are interested in learning more about these types of applications.
 
The next section in the deployment.json file is _eksParameters_. You will see that much of these parameters are the same as what we went over when talking about the ECS parameters. The only differences are the _createEksArtifacts_ parameter, which needs to be set to true if deploying to EKS, and in the gMSA section, the _gMSAName_ parameter has inexplicably been changed to _gMSAAccountName_.

Once you have the deployment file set as desired, you next deploy the container:

```
PS C:\App2Container> app2container generate app-deployment --application-id APPID --deploy
```

This process takes several minutes, and you should get an output like Figure 1. The gold arrow points to the URL where you can go see your deployed application – go ahead and look at it to confirm that it has been successfully deployed and is running.

![Figure 1. Output from generating an application deployment in App2Container](https://i0.wp.com/billthevestguy.com/wp-content/uploads/2022/07/image-5.png)_Figure 1. Output from generating an application deployment in App2Container_

Logging in to the AWS console and going to Amazon ECR will show you the ECR repository that was created to store your image as shown in Figure 2.

![Figure 2. Verifying the new container image is available in ECR](https://i0.wp.com/billthevestguy.com/wp-content/uploads/2022/07/image-6.png)_Figure 2. Verifying the new container image is available in ECR_

Once everything has been deployed and verified, you can poke around in ECS to see how it is all put together. Remember though, if you are looking to make modifications it is highly recommended that you use the CloudFormation templates, make the changes there, and then re-upload them as a new version. That way you will be able to easily redeploy as needed and not worry about losing any changes that you may have added. You can either alter the templates in the CloudFormation section of the console or you can find the templates in your App2Container working directory, update those, and then use those to update the stack.