Once the Cycle Store is running on ASP.NET Core 3.1, it is no longer tied to Windows or IIS. ASP.NET Core applications run on the cross-platform Kestrel web server, which means they can run inside a Linux Docker container — a significant operational improvement over the original .NET Framework version. Containerization brings reproducible builds, environment parity between development and production, and straightforward deployment to AWS managed container services.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/aws-samples/legacy-cycle-store-mvc-app/llms.txt
Use this file to discover all available pages before exploring further.
Why Containerize?
Running the application in a Docker container provides several advantages over the legacy IIS-hosted deployment model:- Portable deployment — the image encapsulates the application, its runtime, and all dependencies. It runs identically on a developer laptop, a CI/CD pipeline, and an AWS production environment.
- Consistent environment — eliminates “works on my machine” issues caused by differences in installed .NET Framework versions, IIS configuration, or Windows patches.
- AWS-native scaling — container images deploy directly to Amazon Elastic Container Service (ECS) on Fargate, Amazon Elastic Kubernetes Service (EKS), or AWS App Runner, all of which provide automatic scaling without managing EC2 instances.
- No IIS dependency — the legacy app required Windows Server with IIS installed and configured. The containerized ASP.NET Core app uses Kestrel and runs on any Linux host.
- Immutable releases — each build produces a versioned, immutable image tag pushed to Amazon ECR. Rolling back means redeploying a previous tag — no manual patching of server configuration.
Dockerfile
The Cycle Store uses a multi-stage Docker build. The first stage uses the full .NET SDK image to compile and publish the application. The second stage uses the smaller ASP.NET Core runtime image to create the final deployable image, keeping the image size minimal by excluding the SDK and build tooling.Dockerfile in the root of the ASP.NET Core project directory (alongside the .csproj file). The dotnet publish step compiles all referenced projects and produces a self-contained output folder — the second stage copies only that output, so no source code is present in the final image.
This page covers the containerization approach planned for Part 3 of the modernization series. The complete container deployment guide — including ECS task definitions, ALB configuration, and auto-scaling — will be published in a separate repository that builds on the ASP.NET Core migration completed in Part 2.
Environment Variables
The containerized application must not have the database connection string baked into its image.appsettings.json is committed to source control and embedded in the image, so it should contain only non-sensitive defaults or placeholder values. At runtime, pass the real connection string as an environment variable.
ASP.NET Core’s configuration system automatically maps environment variables to IConfiguration keys. Double underscores (__) act as hierarchy separators, so ConnectionStrings__CycleStore maps to ConnectionStrings:CycleStore in appsettings.json:
Configuration.GetConnectionString("CycleStore") in Startup.cs — no code changes are required to support environment variable overrides. The configuration system resolves values in priority order: environment variables override appsettings.json, so the runtime variable always wins.
Build and Run Locally
Before pushing to AWS, verify the image builds correctly and can reach the RDS instance from your local machine.Build the Docker image
Run the following command from the directory containing the Docker executes both stages. The first run takes longer because it restores NuGet packages; subsequent builds use the cached restore layer unless the
Dockerfile. The -t flag tags the image with a name and version:.csproj changes.Run the container with the connection string
Start a container from the image, injecting the RDS connection string as an environment variable. Map container port 80 to local port 8080:Setting
ASPNETCORE_ENVIRONMENT=Development enables the developer exception page if the app fails to start, making connection errors easier to diagnose.Push to Amazon ECR
Amazon Elastic Container Registry (ECR) is a fully managed Docker registry integrated with AWS IAM for authentication. Once the image is in ECR, it can be referenced by ECS, EKS, or App Runner deployment configurations.Create an ECR repository
Create a private repository for the Cycle Store image. Replace The command returns the repository URI in the format
<region> and <account-id> with your values:<account-id>.dkr.ecr.<region>.amazonaws.com/cyclestore. Note this URI — you will use it in the next steps.Authenticate Docker to ECR
Retrieve a temporary authentication token and configure the Docker daemon to use it. The token expires after 12 hours:
Tag the local image with the ECR repository URI
Tag the image you built locally with the full ECR repository URI:
RDS Connectivity from Container
TheCYCLE_STORE RDS instance is deployed by the CloudFormation template provided in this repository. For ease of initial setup, the template configures the RDS Security Group to allow inbound traffic on port 1433 (SQL Server) from 0.0.0.0/0 — any IP address.
When running the containerized application in a local Docker environment, this permissive rule is what allows your container to reach the RDS instance over the public internet.
For ECS deployments in the same VPC as the RDS instance, update the RDS Security Group inbound rule to allow traffic from the ECS task Security Group ID rather than 0.0.0.0/0. The container connects to the RDS private DNS endpoint instead of the public endpoint, and no traffic leaves the VPC.