diff --git a/docs/colima-and-docker.md b/docs/colima-and-docker.md new file mode 100644 index 0000000..5042e2e --- /dev/null +++ b/docs/colima-and-docker.md @@ -0,0 +1,55 @@ +# Colima vs Docker Desktop + +## What is Colima? + +Colima is an open-source tool for running **containers** and **virtualized environments** on macOS and Linux. It creates lightweight virtual machines (VMs) to run containers, providing a Docker-compatible environment without the overhead of Docker Desktop. + +Colima supports both **Docker** and **containerd** runtimes, allowing you to choose the container runtime that best fits your needs. + +### Example: Starting Colima with Specific Resources + +To start Colima with a specified configuration: + +```bash +colima start --memory 8 --cpu 4 --disk 20 +``` + +Here, you're allocating 8GB of memory, 4 CPUs, and 20GB of disk space to the virtual machine. +While Colima manages the virtual environment, it still requires a container runtime (such as Docker, containerd, or Podman) to handle the actual container operations. + +## What is Docker Runtime? + +The Docker runtime encompasses all the tools necessary to run a Docker container. It operates using a client-server architecture, consisting of: + +- **Docker CLI (client)**: Allows users to interact with Docker via commands. +- **Docker Daemon (dockerd) (server)**: The core service that runs in the background, responsible for managing containers, images, networks, and volumes. +- **Docker API**: Enables communication between the Docker client and daemon, allowing for remote operations and container management. + +The Docker daemon (`dockerd`) is responsible for the container lifecycle (e.g., starting, stopping, restarting containers). + +## Docker Engine vs Docker Desktop vs Docker Runtime + +- **Docker Engine**: The core runtime responsible for managing containers. It includes the Docker Daemon (`dockerd`) and containerd. Docker Engine can run containers on Linux-based systems natively or through virtualized environments on macOS or Windows. + +- **Docker Desktop**: A full suite of tools for running Docker on macOS and Windows. It includes Docker Engine, a GUI, Kubernetes integration, Docker CLI, and other utilities. Docker Desktop simplifies container management on macOS and Windows but has higher resource usage. + +- **Docker Runtime**: Refers to the lower-level components that allow containers to run, such as Docker Engine or containerd. It does not include higher-level tools like the Docker CLI or GUI. + +## Is Colima a Drop-in Replacement for Docker Desktop? + +Colima is an alternative to Docker Desktop, but it’s not a complete drop-in replacement. While it provides a lightweight environment for running containers on macOS and Linux, it lacks the full GUI and Kubernetes integration found in Docker Desktop. + +That said, Colima can run containers with Docker CLI, making it a great option for those who prefer the command line or need a more resource-efficient environment. + +### Why choose Colima over Docker Desktop? + +- **Free and Open-Source**: Colima is entirely open-source, while Docker Desktop requires a paid license for commercial use. +- **Smaller Footprint**: Colima uses fewer resources compared to Docker Desktop, making it a better option for users looking for a lightweight solution. + +## Conclusion + +- **Docker Engine** is the core runtime for running containers, while **Docker Desktop** is a suite that includes Docker Engine, a GUI, and other tools. +- **Colima** provides a resource-efficient alternative for running Docker containers and VMs, but lacks some of the extra features (e.g., GUI) found in Docker Desktop. +- Colima is a great open-source option if you need a lightweight, cost-effective solution for running containers, especially on macOS or Linux. + +For users seeking a more minimal setup without Docker Desktop’s overhead, **Colima** offers a streamlined and efficient choice. diff --git a/docs/images-gettings-started/tldr.gif b/docs/images-gettings-started/tldr.gif new file mode 100644 index 0000000..32f7f70 Binary files /dev/null and b/docs/images-gettings-started/tldr.gif differ diff --git a/infra/container-api-prod.bicep b/infra/container-api-prod.bicep index 422963c..d22f59f 100644 --- a/infra/container-api-prod.bicep +++ b/infra/container-api-prod.bicep @@ -8,7 +8,7 @@ param managedIdentityName string = 'bds-prod-managedidentity' param keyVaultName string = 'bds-prod-keyvault' @description('The name of the container environment.') -param containerName string = 'bds-prod-containerenv-api' +param containerEnvName string = 'bds-prod-containerenv-api' @description('The name of the container app.') param containerAppName string = 'bds-prod-containerapp-api' @@ -16,6 +16,9 @@ param containerAppName string = 'bds-prod-containerapp-api' @description('The name of the Log Analytics workspace.') param logAnalyticsWorkspaceName string = 'bds-prod-loganalytics' +@description('The name of the VNet.') +param vnetName string = 'bds-prod-vnet' + @description('The name of the ACR login server.') param acrServer string @@ -30,28 +33,86 @@ param acrPassword string param containerImage string module containerEnv 'modules/containerEnv.bicep' = { - name: containerName + name: containerEnvName params: { - containerAppEnvironmentName: containerName + vnetName: vnetName + containerAppEnvironmentName: containerEnvName location: location logAnalyticsWorkspaceName: logAnalyticsWorkspaceName } } -module containerApp 'modules/containerApp.bicep' = { +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { + name: managedIdentityName +} + +resource containerApp 'Microsoft.App/containerApps@2023-08-01-preview' = { name: containerAppName - params: { - location: location - managedIdentityName: managedIdentityName - keyVaultName: keyVaultName - containerAppName: containerAppName - containerAppEnvironmentId: containerEnv.outputs.id - acrLoginServer: acrServer - acrUsername: acrUsername - acrPassword: acrPassword - containerImage: containerImage - targetPort: 5001 + location: location + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + managedEnvironmentId: containerEnv.outputs.id + configuration: { + activeRevisionsMode: 'Multiple' + ingress: { + external: true + targetPort: 5001 + allowInsecure: false + customDomains: [ + { + bindingType: 'SniEnabled' + certificateId: 'surveyapi.bouvetapps.io-bds-prod-250120104816' + name: 'surveyapi.bouvetapps.io' + } + ] + } + registries: [ + { + server: acrServer + passwordSecretRef: 'container-registry-password' + username: acrUsername + } + ] + secrets: [ + { + name: 'container-registry-password' + value: acrPassword + } + { + name: 'sql-server-connection-string' // github workflow will fail if this does not exist. + keyVaultUrl: 'https://${keyVaultName}.vault.azure.net/secrets/sql-server-connection-string' + identity: managedIdentity.id + } + ] + } + template: { + containers: [ + { + name: containerAppName + image: '${acrServer}/backend-image:${containerImage}' + resources: { + cpu: json('0.5') + memory: '1Gi' + } + env: [ + { + name: 'ConnectionString' + secretRef: 'sql-server-connection-string' + } + ] + } + ] + scale: { + minReplicas: 0 + maxReplicas: 2 + } + } } } -output fqdn string = containerApp.outputs.fqdn +output fqdn string = containerApp.properties.configuration.ingress.fqdn diff --git a/infra/container-api-test.bicep b/infra/container-api-test.bicep index 74bb48e..4822e28 100644 --- a/infra/container-api-test.bicep +++ b/infra/container-api-test.bicep @@ -8,7 +8,7 @@ param managedIdentityName string = 'bds-test-managedidentity' param keyVaultName string = 'bds-test-keyvault' @description('The name of the container environment.') -param containerName string = 'bds-test-containerenv-api' +param containerEnvName string = 'bds-test-containerenv-api' @description('The name of the container app.') param containerAppName string = 'bds-test-containerapp-api' @@ -16,6 +16,9 @@ param containerAppName string = 'bds-test-containerapp-api' @description('The name of the Log Analytics workspace.') param logAnalyticsWorkspaceName string = 'bds-test-loganalytics' +@description('The name of the VNet.') +param vnetName string = 'bds-test-vnet' + @description('The name of the ACR login server.') param acrServer string @@ -30,9 +33,10 @@ param acrPassword string param containerImage string module containerEnv 'modules/containerEnv.bicep' = { - name: containerName + name: containerEnvName params: { - containerAppEnvironmentName: containerName + vnetName: vnetName + containerAppEnvironmentName: containerEnvName location: location logAnalyticsWorkspaceName: logAnalyticsWorkspaceName } diff --git a/infra/container-frontend-prod.bicep b/infra/container-frontend-prod.bicep index 86e1e3b..c73fbe5 100644 --- a/infra/container-frontend-prod.bicep +++ b/infra/container-frontend-prod.bicep @@ -16,6 +16,9 @@ param acrServer string @description('The name of the ACR username.') param acrUsername string +@description('The name of the VNet.') +param vnetName string = 'bds-prod-vnet' + @secure() @description('The name of the ACR password.') param acrPassword string @@ -26,24 +29,63 @@ param containerImage string module containerEnv 'modules/containerEnv.bicep' = { name: containerName params: { + vnetName: vnetName containerAppEnvironmentName: containerName location: location logAnalyticsWorkspaceName: logAnalyticsWorkspaceName } } -module containerApp 'modules/containerAppFrontend.bicep' = { +resource containerApp 'Microsoft.App/containerApps@2023-08-01-preview' = { name: containerAppName - params: { - location: location - containerAppName: containerAppName - containerAppEnvironmentId: containerEnv.outputs.id - acrLoginServer: acrServer - acrUsername: acrUsername - acrPassword: acrPassword - containerImage: containerImage - targetPort: 3000 + location: location + properties: { + managedEnvironmentId: containerEnv.outputs.id + configuration: { + activeRevisionsMode: 'Multiple' + ingress: { + external: true + targetPort: 3000 + allowInsecure: false + customDomains: [ + { + bindingType: 'SniEnabled' + certificateId: 'survey.bouvetapps.io-bds-prod-250120105916' + name: 'survey.bouvetapps.io' + } + ] + } + secrets: [ + { + name: 'container-registry-password' + value: acrPassword + } + ] + registries: [ + { + server: acrServer + passwordSecretRef: 'container-registry-password' + username: acrUsername + } + ] + } + template: { + containers: [ + { + name: containerAppName + image: containerImage + resources: { + cpu: json('0.5') + memory: '1Gi' + } + } + ] + scale: { + minReplicas: 0 + maxReplicas: 2 + } + } } } -output fqdn string = containerApp.outputs.fqdn +output fqdn string = containerApp.properties.configuration.ingress.fqdn diff --git a/infra/container-frontend-test.bicep b/infra/container-frontend-test.bicep index 5d724f3..90089d9 100644 --- a/infra/container-frontend-test.bicep +++ b/infra/container-frontend-test.bicep @@ -10,6 +10,9 @@ param containerAppName string = 'bds-test-containerapp-frontend' @description('The name of the Log Analytics workspace.') param logAnalyticsWorkspaceName string = 'bds-test-loganalytics' +@description('The name of the VNet.') +param vnetName string = 'bds-test-vnet' + @description('The name of the ACR login server.') param acrServer string @@ -26,6 +29,7 @@ param containerImage string module containerEnv 'modules/containerEnv.bicep' = { name: containerName params: { + vnetName: vnetName containerAppEnvironmentName: containerName location: location logAnalyticsWorkspaceName: logAnalyticsWorkspaceName diff --git a/infra/main-prod.bicep b/infra/main-prod.bicep index 7f34fc2..e0484c6 100644 --- a/infra/main-prod.bicep +++ b/infra/main-prod.bicep @@ -19,6 +19,18 @@ param sqlDBName string = 'bds-prod-sqldb' @description('The username for the SQL Server.') param sqlServerUsername string = 'bdsadmin' +@description('The name of the VNet') +param vnetName string = 'bds-prod-vnet' + +@description('The name of the subnet') +param subnetName string = 'bds-prod-subnet' + +@description('The name of the private endpoint') +param sqlPrivateEndpointName string = 'bds-prod-privateendpoint-sqlserver' + +@description('The name of the private endpoint connection') +param sqlServerConnectionName string = 'bds-prod-sqlserver-connection' + @secure() @description('The administrator password used for the sql server instance created.') param sqlServerPassword string @@ -43,6 +55,10 @@ module keyVault 'modules/keyVault.bicep' = { module sqlServer 'modules/sqlServer.bicep' = { name: serverName params: { + vnetName: vnetName + subnetName: subnetName + sqlPrivateEndpointName: sqlPrivateEndpointName + sqlServerConnectionName: sqlServerConnectionName serverName: serverName sqlDBName: sqlDBName location: location diff --git a/infra/main-test.bicep b/infra/main-test.bicep index ce3d9ed..bb57a8e 100644 --- a/infra/main-test.bicep +++ b/infra/main-test.bicep @@ -19,6 +19,18 @@ param sqlDBName string = 'bds-test-sqldb' @description('The username for the SQL Server.') param sqlServerUsername string = 'bdsadmin' +@description('The name of the VNet') +param vnetName string = 'bds-test-vnet' + +@description('The name of the subnet') +param subnetName string = 'bds-test-subnet' + +@description('The name of the private endpoint') +param sqlPrivateEndpointName string = 'bds-test-privateendpoint-sqlserver' + +@description('The name of the private endpoint connection') +param sqlServerConnectionName string = 'bds-test-sqlserver-connection' + @secure() @description('The administrator password used for the sql server instance created.') param sqlServerPassword string @@ -43,6 +55,10 @@ module keyVault 'modules/keyVault.bicep' = { module sqlServer 'modules/sqlServer.bicep' = { name: serverName params: { + vnetName: vnetName + subnetName: subnetName + sqlPrivateEndpointName: sqlPrivateEndpointName + sqlServerConnectionName: sqlServerConnectionName serverName: serverName sqlDBName: sqlDBName location: location diff --git a/infra/modules/containerAppFrontend.bicep b/infra/modules/containerAppFrontend.bicep index f8c77f3..998e8ad 100644 --- a/infra/modules/containerAppFrontend.bicep +++ b/infra/modules/containerAppFrontend.bicep @@ -61,8 +61,8 @@ resource containerApp 'Microsoft.App/containerApps@2023-08-01-preview' = { } ] scale: { - minReplicas: 1 - maxReplicas: 3 + minReplicas: 0 + maxReplicas: 2 } } } diff --git a/infra/modules/containerEnv.bicep b/infra/modules/containerEnv.bicep index e50326d..6124922 100644 --- a/infra/modules/containerEnv.bicep +++ b/infra/modules/containerEnv.bicep @@ -7,6 +7,13 @@ param location string @description('Log analytics workspace name') param logAnalyticsWorkspaceName string +@description('The name of the VNet') +param vnetName string + +resource vnet 'Microsoft.Network/virtualNetworks@2023-04-01' existing = { + name: vnetName +} + resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2023-09-01' = { name: logAnalyticsWorkspaceName location: location @@ -21,6 +28,9 @@ resource env 'Microsoft.App/managedEnvironments@2023-08-01-preview' = { name: containerAppEnvironmentName location: location properties: { + vnetConfiguration: { + infrastructureSubnetId: vnet.properties.subnets[0].id + } appLogsConfiguration: { destination: 'log-analytics' logAnalyticsConfiguration: { diff --git a/infra/modules/sqlServer.bicep b/infra/modules/sqlServer.bicep index b120ff3..7a9308e 100644 --- a/infra/modules/sqlServer.bicep +++ b/infra/modules/sqlServer.bicep @@ -7,6 +7,18 @@ param sqlDBName string @description('The location for the SQL Server.') param location string +@description('The name of the VNet') +param vnetName string + +@description('The name of the subnet') +param subnetName string + +@description('The name of the private endpoint') +param sqlPrivateEndpointName string + +@description('The name of the private endpoint connection') +param sqlServerConnectionName string + @description('The administrator login for the SQL Server.') param administratorLogin string @@ -33,8 +45,51 @@ resource sqlDB 'Microsoft.Sql/servers/databases@2022-05-01-preview' = { capacity: 1 family: 'Gen5' } - properties:{ + properties: { autoPauseDelay: 60 minCapacity: 1 } } + +resource vnet 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: vnetName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + '10.0.0.0/23' + ] + } + subnets: [ + { + name: subnetName + properties: { + addressPrefix: '10.0.0.0/23' + } + } + ] + } +} + +resource sqlPrivateEndpoint 'Microsoft.Network/privateEndpoints@2024-05-01' = { + name: sqlPrivateEndpointName + location: location + properties: { + subnet: { + id: vnet.properties.subnets[0].id + } + privateLinkServiceConnections: [ + { + name: sqlServerConnectionName + properties: { + privateLinkServiceConnectionState: { + status: 'Approved' + description: 'Private endpoint for SQL server' + } + privateLinkServiceId: sqlServer.id + groupIds: ['sqlServer'] + } + } + ] + } +}