From 54d29c41c6f6e840ddc5be3a57551921548de748 Mon Sep 17 00:00:00 2001 From: Ash Davies <3853061+DrizzlyOwl@users.noreply.github.com> Date: Mon, 25 Nov 2024 11:37:16 +0000 Subject: [PATCH] Switch to Azure Linux base image (#609) * Reduces the overall final image size by using Azure Linux * Offers maximum compatibility with Azure infrastructure * Uses arbitrary user instead of 'root' * Supported by Microsoft --- Dockerfile | 68 +++++++++++++++-------------- terraform/README.md | 1 + terraform/container-apps-hosting.tf | 1 + terraform/locals.tf | 1 + terraform/variables.tf | 6 +++ 5 files changed, 45 insertions(+), 32 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5b640072d..bdf16345b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,9 @@ -# Stage 1 -ARG ASPNET_IMAGE_TAG=8.0-bookworm-slim -FROM mcr.microsoft.com/dotnet/sdk:8.0 as build -WORKDIR /build +# Set the major version of dotnet +ARG DOTNET_VERSION=8.0 -ENV DEBIAN_FRONTEND=noninteractive +# Build the app using the dotnet SDK +FROM "mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION}-azurelinux3.0" AS build +WORKDIR /build COPY ./Dfe.Academies.Academisation.Core/ ./Dfe.Academies.Academisation.Core/ COPY ./Dfe.Academies.Academisation.Data/ ./Dfe.Academies.Academisation.Data/ @@ -14,34 +14,38 @@ COPY ./Dfe.Academies.Academisation.IDomain/ ./Dfe.Academies.Academisation.IDomai COPY ./Dfe.Academies.Academisation.IService/ ./Dfe.Academies.Academisation.IService/ COPY ./Dfe.Academies.Academisation.Service/ ./Dfe.Academies.Academisation.Service/ COPY ./Dfe.Academies.Academisation.WebApi/ ./Dfe.Academies.Academisation.WebApi/ -COPY ./Dfe.Academies.Academisation.sln/ ./Dfe.Academies.Academisation.sln +COPY ./Dfe.Academies.Academisation.sln ./Dfe.Academies.Academisation.sln +# Mount GitHub Token as a Docker secret so that NuGet Feed can be accessed RUN --mount=type=secret,id=github_token dotnet nuget add source --username USERNAME --password $(cat /run/secrets/github_token) --store-password-in-clear-text --name github "https://nuget.pkg.github.com/DFE-Digital/index.json" -RUN dotnet restore Dfe.Academies.Academisation.WebApi -RUN dotnet build Dfe.Academies.Academisation.WebApi - -RUN dotnet new tool-manifest -RUN dotnet tool install dotnet-ef --version 8.0.8 - -RUN dotnet ef migrations script --output /app/SQL/DbMigrationScript.sql --idempotent -p /build/Dfe.Academies.Academisation.Data -s /build/Dfe.Academies.Academisation.WebApi -c AcademisationContext - -RUN dotnet publish Dfe.Academies.Academisation.WebApi -c Release -o /app - -COPY ./script/webapi-docker-entrypoint.sh /app/docker-entrypoint.sh - -ARG ASPNET_IMAGE_TAG -FROM "mcr.microsoft.com/dotnet/aspnet:${ASPNET_IMAGE_TAG}" AS final -LABEL org.opencontainers.image.source=https://github.com/DFE-Digital/academies-academisation-api - -RUN apt-get update -RUN apt-get install curl gnupg -y -RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - -RUN curl https://packages.microsoft.com/config/debian/11/prod.list | tee /etc/apt/sources.list.d/msprod.list -RUN apt-get update -RUN ACCEPT_EULA=Y apt-get install msodbcsql18 mssql-tools18 unixodbc-dev -y -COPY --from=build /app /app +RUN ["dotnet", "restore", "Dfe.Academies.Academisation.WebApi"] +RUN ["dotnet", "build", "Dfe.Academies.Academisation.WebApi", "--no-restore", "-c", "Release"] +RUN ["dotnet", "publish", "Dfe.Academies.Academisation.WebApi", "--no-build", "-o", "/app"] + +RUN ["dotnet", "new", "tool-manifest"] +RUN ["dotnet", "tool", "install", "dotnet-ef", "--version", "8.0.11"] +RUN ["mkdir", "-p", "/app/SQL"] +RUN ["dotnet", "restore", "Dfe.Academies.Academisation.WebApi"] +RUN ["dotnet", "build", "Dfe.Academies.Academisation.WebApi", "--no-restore"] +RUN ["dotnet", "ef", "migrations", "script", "--output", "/app/SQL/DbMigrationScript.sql", "--idempotent", "-p", "/build/Dfe.Academies.Academisation.Data", "-s", "/build/Dfe.Academies.Academisation.WebApi", "-c", "AcademisationContext", "--no-build"] +RUN ["touch", "/app/SQL/DbMigrationScriptOutput.txt"] + +# Install SQL tools to allow migrations to be run +FROM "mcr.microsoft.com/dotnet/aspnet:${DOTNET_VERSION}-azurelinux3.0" AS base +RUN curl "https://packages.microsoft.com/config/rhel/9/prod.repo" | tee /etc/yum.repos.d/mssql-release.repo +ENV ACCEPT_EULA=Y +RUN ["tdnf", "update"] +RUN ["tdnf", "install", "-y", "mssql-tools18"] +RUN ["tdnf", "clean", "all"] + +# Build a runtime environment +FROM base AS runtime WORKDIR /app -RUN chmod +x ./docker-entrypoint.sh -ENV ASPNETCORE_HTTP_PORTS=80 -EXPOSE 80/tcp +LABEL org.opencontainers.image.source="https://github.com/DFE-Digital/academies-academisation-api" +COPY --from=build /app /app +COPY ./script/webapi-docker-entrypoint.sh /app/docker-entrypoint.sh +RUN ["chmod", "+x", "/app/docker-entrypoint.sh"] +RUN ["touch", "/app/SQL/DbMigrationScriptOutput.txt"] +RUN chown "$APP_UID" "/app/SQL" -R +USER $APP_UID diff --git a/terraform/README.md b/terraform/README.md index b1e6ee248..bcb6c0294 100644 --- a/terraform/README.md +++ b/terraform/README.md @@ -170,6 +170,7 @@ No resources. | [container\_command](#input\_container\_command) | Container command | `list(any)` | n/a | yes | | [container\_health\_probe\_path](#input\_container\_health\_probe\_path) | Specifies the path that is used to determine the liveness of the Container | `string` | n/a | yes | | [container\_min\_replicas](#input\_container\_min\_replicas) | Container min replicas | `number` | `1` | no | +| [container\_port](#input\_container\_port) | Container port | `number` | `8080` | no | | [container\_scale\_http\_concurrency](#input\_container\_scale\_http\_concurrency) | When the number of concurrent HTTP requests exceeds this value, then another replica is added. Replicas continue to add to the pool up to the max-replicas amount. | `number` | `10` | no | | [container\_secret\_environment\_variables](#input\_container\_secret\_environment\_variables) | Container secret environment variables | `map(string)` | n/a | yes | | [dns\_mx\_records](#input\_dns\_mx\_records) | DNS MX records to add to the DNS Zone |
map(
object({
ttl : optional(number, 300),
records : list(
object({
preference : number,
exchange : string
})
)
})
)
| `{}` | no | diff --git a/terraform/container-apps-hosting.tf b/terraform/container-apps-hosting.tf index 6ac4449b2..a07411e57 100644 --- a/terraform/container-apps-hosting.tf +++ b/terraform/container-apps-hosting.tf @@ -19,6 +19,7 @@ module "azure_container_apps_hosting" { container_secret_environment_variables = local.container_secret_environment_variables container_scale_http_concurrency = local.container_scale_http_concurrency container_min_replicas = local.container_min_replicas + container_port = local.container_port enable_health_insights_api = local.enable_health_insights_api health_insights_api_cors_origins = local.health_insights_api_cors_origins health_insights_api_ipv4_allow_list = local.health_insights_api_ipv4_allow_list diff --git a/terraform/locals.tf b/terraform/locals.tf index 54a5f40ee..3d85d8cf2 100644 --- a/terraform/locals.tf +++ b/terraform/locals.tf @@ -14,6 +14,7 @@ locals { container_secret_environment_variables = var.container_secret_environment_variables container_scale_http_concurrency = var.container_scale_http_concurrency container_min_replicas = var.container_min_replicas + container_port = var.container_port enable_event_hub = var.enable_event_hub enable_logstash_consumer = var.enable_logstash_consumer eventhub_export_log_analytics_table_names = var.eventhub_export_log_analytics_table_names diff --git a/terraform/variables.tf b/terraform/variables.tf index 30193ba9a..0e0cc929e 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -414,3 +414,9 @@ variable "cdn_frontdoor_vdp_destination_hostname" { type = string default = "vdp.security.education.gov.uk" } + +variable "container_port" { + description = "Container port" + type = number + default = 8080 +}