├── .dockerignore
├── .gitignore
├── WebApi
├── Program.cs
├── appsettings.Development.json
├── appsettings.json
├── nuget.config
├── WebApi.csproj
├── Dockerfile
└── Properties
│ └── launchSettings.json
├── WebApiChiseled
├── Program.cs
├── appsettings.Development.json
├── appsettings.json
├── nuget.config
├── Dockerfile
├── WebApi.csproj
└── Properties
│ └── launchSettings.json
├── GrpcApi
├── appsettings.Development.json
├── appsettings.json
├── nuget.config
├── Protos
│ └── greet.proto
├── Services
│ └── GreeterService.cs
├── Properties
│ └── launchSettings.json
├── Program.cs
├── GrpcApi.csproj
└── Dockerfile
├── OpenSslEmbedding
├── Program.cs
├── nuget.config
├── OpenSslEmbedding.csproj
├── Dockerfile
└── Dockerfile.nossl
├── NpgCli
├── nuget.config
├── Program.cs
├── Dockerfile.noicu
├── Dockerfile
└── NpgCli.csproj
├── EmbeddedICU
├── nuget.config
├── Program.cs
├── EmbeddedICU.csproj
└── Dockerfile
├── NpgCliSlim
├── nuget.config
├── Program.cs
├── Dockerfile.noicu
├── Dockerfile
└── NpgCliSlim.csproj
├── CompressionEmbedding
├── nuget.config
├── Dockerfile
├── CompressionEmbedding.csproj
└── Program.cs
├── InvariantGlobalization
├── nuget.config
├── Program.cs
├── Dockerfile
└── InvariantGlobalization.csproj
├── GrpcApiClient
├── Protos
│ └── greet.proto
├── GrpcApiClient.csproj
└── Program.cs
├── NativeAOTDocker.sln
├── calc.fsx
└── README.md
/.dockerignore:
--------------------------------------------------------------------------------
1 | bin/
2 | obj/
3 | out/
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | bin/
2 | obj/
3 | out/
4 | certs/
5 |
--------------------------------------------------------------------------------
/WebApi/Program.cs:
--------------------------------------------------------------------------------
1 | var builder = WebApplication.CreateBuilder(args);
2 | var app = builder.Build();
3 |
4 | app.MapGet("/", () => "Hello World!");
5 |
6 | app.Run();
7 |
--------------------------------------------------------------------------------
/WebApiChiseled/Program.cs:
--------------------------------------------------------------------------------
1 | var builder = WebApplication.CreateBuilder(args);
2 | var app = builder.Build();
3 |
4 | app.MapGet("/", () => "Hello World!");
5 |
6 | app.Run();
7 |
--------------------------------------------------------------------------------
/GrpcApi/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/WebApi/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/WebApiChiseled/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/WebApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | },
8 | "AllowedHosts": "*"
9 | }
10 |
--------------------------------------------------------------------------------
/WebApiChiseled/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | },
8 | "AllowedHosts": "*"
9 | }
10 |
--------------------------------------------------------------------------------
/GrpcApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | },
8 | "AllowedHosts": "*",
9 | "Kestrel": {
10 | "EndpointDefaults": {
11 | "Protocols": "Http2"
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/OpenSslEmbedding/Program.cs:
--------------------------------------------------------------------------------
1 | Console.WriteLine("Querying first website:");
2 | using var client = new HttpClient();
3 | var content = await client.GetStringAsync("http://info.cern.ch/");
4 | Console.WriteLine(content);
5 |
6 | Console.WriteLine("Querying website over HTTPS:");
7 | content = await client.GetStringAsync("https://smallsrv.com/");
8 | Console.WriteLine(content.Substring(0, 300));
9 |
--------------------------------------------------------------------------------
/GrpcApi/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/NpgCli/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/WebApi/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/EmbeddedICU/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/NpgCliSlim/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/WebApiChiseled/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/GrpcApi/Protos/greet.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | option csharp_namespace = "GrpcApi";
4 |
5 | package greet;
6 |
7 | // The greeting service definition.
8 | service Greeter {
9 | // Sends a greeting
10 | rpc SayHello (HelloRequest) returns (HelloReply);
11 | }
12 |
13 | // The request message containing the user's name.
14 | message HelloRequest {
15 | string name = 1;
16 | }
17 |
18 | // The response message containing the greetings.
19 | message HelloReply {
20 | string message = 1;
21 | }
22 |
--------------------------------------------------------------------------------
/OpenSslEmbedding/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/CompressionEmbedding/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/InvariantGlobalization/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/GrpcApiClient/Protos/greet.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | option csharp_namespace = "GrpcApiClient";
4 |
5 | package greet;
6 |
7 | // The greeting service definition.
8 | service Greeter {
9 | // Sends a greeting
10 | rpc SayHello (HelloRequest) returns (HelloReply);
11 | }
12 |
13 | // The request message containing the user's name.
14 | message HelloRequest {
15 | string name = 1;
16 | }
17 |
18 | // The response message containing the greetings.
19 | message HelloReply {
20 | string message = 1;
21 | }
22 |
--------------------------------------------------------------------------------
/CompressionEmbedding/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
2 | WORKDIR /app
3 | RUN apk add clang binutils musl-dev build-base zlib-static
4 | COPY nuget.config .
5 | COPY CompressionEmbedding.csproj .
6 | RUN dotnet restore --runtime linux-musl-x64 CompressionEmbedding.csproj
7 |
8 | COPY . .
9 | RUN dotnet publish -c Release -r linux-musl-x64 -o out CompressionEmbedding.csproj
10 |
11 | FROM scratch AS runtime
12 | WORKDIR /app
13 | COPY --from=build /app/out/CompressionEmbedding /app/
14 | ENTRYPOINT ["/app/CompressionEmbedding"]
15 |
--------------------------------------------------------------------------------
/InvariantGlobalization/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Globalization;
2 |
3 | Console.WriteLine("There no globalization");
4 |
5 | Console.WriteLine("Enter you name:");
6 | var greeting = Console.ReadLine();
7 | Console.WriteLine($"Hello {greeting}!");
8 | double num = 5.2;
9 |
10 | var parsed = int.TryParse("-120", NumberStyles.Integer, CultureInfo.InvariantCulture, out var reversedOffset);
11 | Console.WriteLine($"Parsed -120 invariant culture: {parsed}, result is {reversedOffset}");
12 | Console.WriteLine($"Number 5.2 with invariant culture {num.ToString("F2")}");
13 |
--------------------------------------------------------------------------------
/NpgCliSlim/Program.cs:
--------------------------------------------------------------------------------
1 | using Npgsql;
2 |
3 | var connectionString = Environment.GetEnvironmentVariable("ConnectionString") ?? "Host=localhost:32768;Username=postgres;Password=postgrespw";
4 | Console.WriteLine("Connecting using connection string "+ connectionString);
5 | using var conn = new NpgsqlSlimDataSourceBuilder(connectionString).Build();
6 |
7 | await using (var cmd = conn.CreateCommand("SELECT 5"))
8 | await using (var reader = await cmd.ExecuteReaderAsync())
9 | {
10 | while (await reader.ReadAsync())
11 | Console.WriteLine(reader.GetInt32(0));
12 | }
13 |
--------------------------------------------------------------------------------
/InvariantGlobalization/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
2 | WORKDIR /app
3 | RUN apk add clang binutils musl-dev build-base zlib-static
4 | COPY nuget.config .
5 | COPY InvariantGlobalization.csproj .
6 | RUN dotnet restore --runtime linux-musl-x64 InvariantGlobalization.csproj
7 |
8 | COPY . .
9 | RUN dotnet publish -c Release -r linux-musl-x64 -o out InvariantGlobalization.csproj
10 |
11 | FROM scratch AS runtime
12 | WORKDIR /app
13 | COPY --from=build /app/out/InvariantGlobalization /app/
14 | ENTRYPOINT ["/app/InvariantGlobalization"]
15 |
--------------------------------------------------------------------------------
/NpgCli/Program.cs:
--------------------------------------------------------------------------------
1 | using Npgsql;
2 |
3 | var connectionString = Environment.GetEnvironmentVariable("ConnectionString") ?? "Host=localhost:32768;Username=postgres;Password=postgrespw";
4 | Console.WriteLine("Connecting using connection string "+ connectionString);
5 | await using var conn = new NpgsqlConnection(connectionString);
6 | await conn.OpenAsync();
7 |
8 | await using (var cmd = new NpgsqlCommand("SELECT 5", conn))
9 | await using (var reader = await cmd.ExecuteReaderAsync())
10 | {
11 | while (await reader.ReadAsync())
12 | Console.WriteLine(reader.GetInt32(0));
13 | }
14 |
--------------------------------------------------------------------------------
/WebApiChiseled/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0-noble AS build
2 | WORKDIR /app
3 | COPY nuget.config .
4 | COPY WebApi.csproj .
5 | RUN dotnet restore --runtime linux-x64 WebApi.csproj
6 |
7 | COPY . .
8 | RUN apt update && apt-get install -y clang zlib1g-dev
9 | RUN dotnet publish -c Release -r linux-x64 -o out WebApi.csproj
10 |
11 | FROM mcr.microsoft.com/dotnet/nightly/runtime-deps:9.0-noble-chiseled AS runtime
12 | WORKDIR /app
13 | COPY --from=build /app/out/WebApi /app/
14 | ENV ASPNETCORE_URLS="http://+"
15 | EXPOSE 443
16 | EXPOSE 80
17 | ENTRYPOINT ["/app/WebApi"]
18 |
--------------------------------------------------------------------------------
/EmbeddedICU/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Globalization;
2 |
3 | Console.WriteLine("With globalizations");
4 |
5 | Console.WriteLine("Enter you name:");
6 | var greeting = Console.ReadLine();
7 | Console.WriteLine($"Hello {greeting}!");
8 | double num = 5.2;
9 |
10 | var parsed = int.TryParse("-120", NumberStyles.Integer, CultureInfo.InvariantCulture, out var reversedOffset);
11 | Console.WriteLine($"Parsed -120 invariant culture: {parsed}, result is {reversedOffset}");
12 | Console.WriteLine($"Number 5.2 in ru-RU locale {num.ToString("F2", System.Globalization.CultureInfo.GetCultureInfo("ru-ru"))}");
13 |
--------------------------------------------------------------------------------
/GrpcApi/Services/GreeterService.cs:
--------------------------------------------------------------------------------
1 | using Grpc.Core;
2 | using GrpcApi;
3 |
4 | namespace GrpcApi.Services;
5 |
6 | public class GreeterService : Greeter.GreeterBase
7 | {
8 | private readonly ILogger _logger;
9 | public GreeterService(ILogger logger)
10 | {
11 | _logger = logger;
12 | }
13 |
14 | public override Task SayHello(HelloRequest request, ServerCallContext context)
15 | {
16 | return Task.FromResult(new HelloReply
17 | {
18 | Message = "Hello " + request.Name
19 | });
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/WebApiChiseled/WebApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | true
8 | false
9 | true
10 | true
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/GrpcApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "http": {
4 | "commandName": "Project",
5 | "dotnetRunMessages": true,
6 | "launchBrowser": false,
7 | "applicationUrl": "http://localhost:5163",
8 | "environmentVariables": {
9 | "ASPNETCORE_ENVIRONMENT": "Development"
10 | }
11 | },
12 | "https": {
13 | "commandName": "Project",
14 | "dotnetRunMessages": true,
15 | "launchBrowser": false,
16 | "applicationUrl": "https://localhost:7077;http://localhost:5163",
17 | "environmentVariables": {
18 | "ASPNETCORE_ENVIRONMENT": "Development"
19 | }
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/GrpcApi/Program.cs:
--------------------------------------------------------------------------------
1 | using GrpcApi.Services;
2 |
3 | var builder = WebApplication.CreateBuilder(args);
4 |
5 | // Additional configuration is required to successfully run gRPC on macOS.
6 | // For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682
7 |
8 | // Add services to the container.
9 | builder.Services.AddGrpc();
10 |
11 | var app = builder.Build();
12 |
13 | // Configure the HTTP request pipeline.
14 | app.MapGrpcService();
15 | app.MapGet("/", () => "Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
16 |
17 | app.Run();
18 |
--------------------------------------------------------------------------------
/CompressionEmbedding/CompressionEmbedding.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | true
8 | true
9 | true
10 | true
11 | true
12 | true
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/InvariantGlobalization/InvariantGlobalization.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | true
8 | true
9 | true
10 | true
11 | true
12 | true
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/EmbeddedICU/EmbeddedICU.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | true
8 | true
9 | true
10 | false
11 | true
12 | true
13 | true
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/WebApi/WebApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | true
8 | true
9 | false
10 | true
11 | true
12 | true
13 | true
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/NpgCli/Dockerfile.noicu:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
2 | WORKDIR /app
3 | # these RUN lines below is optimization for current experiment to account for the fact that I have multiple similar configuration
4 | # best practices of Docker building imply that I put all dependencies in single line
5 | RUN apk add clang binutils musl-dev build-base zlib-static
6 | RUN apk add cmake
7 | RUN apk add openssl-dev openssl-libs-static
8 | COPY nuget.config .
9 | COPY NpgCli.csproj .
10 | RUN dotnet restore --runtime linux-musl-x64 NpgCli.csproj
11 |
12 | COPY . .
13 | RUN dotnet publish -c Release -r linux-musl-x64 -o out NpgCli.csproj /p:InvariantGlobalization=true
14 |
15 | FROM scratch AS runtime
16 | WORKDIR /app
17 | COPY --from=build /app/out/NpgCli /app/
18 | ENTRYPOINT ["/app/NpgCli"]
19 |
--------------------------------------------------------------------------------
/NpgCliSlim/Dockerfile.noicu:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
2 | WORKDIR /app
3 | # these RUN lines below is optimization for current experiment to account for the fact that I have multiple similar configuration
4 | # best practices of Docker building imply that I put all dependencies in single line
5 | RUN apk add clang binutils musl-dev build-base zlib-static
6 | RUN apk add cmake
7 | RUN apk add openssl-dev openssl-libs-static
8 | COPY nuget.config .
9 | COPY NpgCliSlim.csproj .
10 | RUN dotnet restore --runtime linux-musl-x64 NpgCliSlim.csproj
11 |
12 | COPY . .
13 | RUN dotnet publish -c Release -r linux-musl-x64 -o out NpgCliSlim.csproj /p:InvariantGlobalization=true
14 |
15 | FROM scratch AS runtime
16 | WORKDIR /app
17 | COPY --from=build /app/out/NpgCliSlim /app/
18 | ENTRYPOINT ["/app/NpgCliSlim"]
19 |
--------------------------------------------------------------------------------
/OpenSslEmbedding/OpenSslEmbedding.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | true
8 | true
9 | false
10 | true
11 | true
12 | true
13 | true
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/GrpcApiClient/GrpcApiClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net7.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 | runtime; build; native; contentfiles; analyzers; buildtransitive
15 | all
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/EmbeddedICU/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
2 | WORKDIR /app
3 | # these RUN lines below is optimization for current experiment to account for the fact that I have multiple similar configuration
4 | # best practices of Docker building imply that I put all dependencies in single line
5 | RUN apk add clang binutils musl-dev build-base zlib-static
6 | RUN apk add cmake
7 | RUN apk add icu-static icu-dev
8 | COPY nuget.config .
9 | COPY EmbeddedICU.csproj .
10 | RUN dotnet restore --runtime linux-musl-x64 EmbeddedICU.csproj
11 |
12 | COPY . .
13 | RUN dotnet publish -c Release -r linux-musl-x64 -o out EmbeddedICU.csproj
14 |
15 | FROM scratch AS runtime
16 | WORKDIR /app
17 | COPY --from=build /app/out/EmbeddedICU /app/
18 | COPY --from=build /usr/share/icu/74.2/icudt74l.dat /usr/share/icu/74.2/
19 | ENTRYPOINT ["/app/EmbeddedICU"]
20 |
--------------------------------------------------------------------------------
/NpgCli/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
2 | WORKDIR /app
3 | # these RUN lines below is optimization for current experiment to account for the fact that I have multiple similar configuration
4 | # best practices of Docker building imply that I put all dependencies in single line
5 | RUN apk add clang binutils musl-dev build-base zlib-static
6 | RUN apk add cmake
7 | RUN apk add icu-static icu-dev
8 | RUN apk add openssl-dev openssl-libs-static
9 | COPY nuget.config .
10 | COPY NpgCli.csproj .
11 | RUN dotnet restore --runtime linux-musl-x64 NpgCli.csproj
12 |
13 | COPY . .
14 | RUN dotnet publish -c Release -r linux-musl-x64 -o out NpgCli.csproj
15 |
16 | FROM scratch AS runtime
17 | WORKDIR /app
18 | COPY --from=build /app/out/NpgCli /app/
19 | COPY --from=build /usr/share/icu/74.2/icudt74l.dat /usr/share/icu/74.2/
20 | ENTRYPOINT ["/app/NpgCli"]
21 |
--------------------------------------------------------------------------------
/WebApi/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
2 | WORKDIR /app
3 | # these RUN lines below is optimization for current experiment to account for the fact that I have multiple similar configuration
4 | # best practices of Docker building imply that I put all dependencies in single line
5 | RUN apk add clang binutils musl-dev build-base zlib-static
6 | RUN apk add cmake
7 | RUN apk add openssl-dev openssl-libs-static openssl
8 | COPY nuget.config .
9 | COPY WebApi.csproj .
10 | RUN dotnet restore --runtime linux-musl-x64 WebApi.csproj
11 |
12 | COPY . .
13 | RUN dotnet publish -c Release -r linux-musl-x64 -o out WebApi.csproj
14 |
15 | FROM scratch AS runtime
16 | WORKDIR /app
17 | COPY --from=build /app/out/WebApi /app/
18 | COPY --from=build /etc/ssl/certs/* /etc/ssl/certs/
19 | ENV ASPNETCORE_URLS="http://+"
20 | EXPOSE 443
21 | EXPOSE 80
22 | ENTRYPOINT ["/app/WebApi"]
23 |
--------------------------------------------------------------------------------
/NpgCliSlim/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
2 | WORKDIR /app
3 | # these RUN lines below is optimization for current experiment to account for the fact that I have multiple similar configuration
4 | # best practices of Docker building imply that I put all dependencies in single line
5 | RUN apk add clang binutils musl-dev build-base zlib-static
6 | RUN apk add cmake
7 | RUN apk add icu-static icu-dev
8 | RUN apk add openssl-dev openssl-libs-static
9 | COPY nuget.config .
10 | COPY NpgCliSlim.csproj .
11 | RUN dotnet restore --runtime linux-musl-x64 NpgCliSlim.csproj
12 |
13 | COPY . .
14 | RUN dotnet publish -c Release -r linux-musl-x64 -o out NpgCliSlim.csproj
15 |
16 | FROM scratch AS runtime
17 | WORKDIR /app
18 | COPY --from=build /app/out/NpgCliSlim /app/
19 | COPY --from=build /usr/share/icu/74.2/icudt74l.dat /usr/share/icu/74.2/
20 | ENTRYPOINT ["/app/NpgCliSlim"]
21 |
--------------------------------------------------------------------------------
/OpenSslEmbedding/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
2 | WORKDIR /app
3 | # these RUN lines below is optimization for current experiment to account for the fact that I have multiple similar configuration
4 | # best practices of Docker building imply that I put all dependencies in single line
5 | RUN apk add clang binutils musl-dev build-base zlib-static
6 | RUN apk add cmake
7 | RUN apk add openssl-dev openssl-libs-static
8 | COPY nuget.config .
9 | COPY OpenSslEmbedding.csproj .
10 | RUN dotnet restore --runtime linux-musl-x64 OpenSslEmbedding.csproj
11 |
12 | COPY . .
13 | RUN dotnet publish -c Release -r linux-musl-x64 -o out OpenSslEmbedding.csproj
14 | RUN strip /app/out/OpenSslEmbedding
15 |
16 | FROM scratch AS runtime
17 | WORKDIR /app
18 | COPY --from=build /app/out/OpenSslEmbedding /app/
19 | COPY --from=build /etc/ssl/certs/* /etc/ssl/certs/
20 | ENTRYPOINT ["/app/OpenSslEmbedding"]
21 |
--------------------------------------------------------------------------------
/OpenSslEmbedding/Dockerfile.nossl:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
2 | WORKDIR /app
3 | # these RUN lines below is optimization for current experiment to account for the fact that I have multiple similar configuration
4 | # best practices of Docker building imply that I put all dependencies in single line
5 | RUN apk add clang binutils musl-dev build-base zlib-static
6 | RUN apk add cmake
7 | RUN apk add openssl-dev openssl-libs-static
8 | COPY nuget.config .
9 | COPY OpenSslEmbedding.csproj .
10 | RUN dotnet restore --runtime linux-musl-x64 OpenSslEmbedding.csproj
11 |
12 | COPY . .
13 | RUN dotnet publish -c Release -r linux-musl-x64 -o out OpenSslEmbedding.csproj /p:StaticOpenSslLinking=false
14 | RUN strip /app/out/OpenSslEmbedding
15 |
16 | FROM scratch AS runtime
17 | WORKDIR /app
18 | COPY --from=build /app/out/OpenSslEmbedding /app/
19 | COPY --from=build /etc/ssl/certs/* /etc/ssl/certs/
20 | ENTRYPOINT ["/app/OpenSslEmbedding"]
21 |
--------------------------------------------------------------------------------
/GrpcApi/GrpcApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | true
8 | true
9 | false
10 | true
11 | true
12 | true
13 | true
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/GrpcApiClient/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 | using System.Threading.Tasks;
3 | using Grpc.Net.Client;
4 | using GrpcApiClient;
5 |
6 | ServicePointManager.ServerCertificateValidationCallback += (o, c, ch, er) => true;
7 |
8 | // The port number must match the port of the gRPC server.
9 | var options = new GrpcChannelOptions(){ UnsafeUseInsecureChannelCallCredentials = true };
10 | var httpClientHandler = new HttpClientHandler();
11 |
12 | // That's only to simplify showing that GRPC channel woks
13 | // Remove from production code.
14 | httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, _) => {
15 | return true;
16 | };
17 | options.HttpHandler = httpClientHandler;
18 |
19 | using var channel = GrpcChannel.ForAddress("https://localhost:8011", options);
20 | var client = new Greeter.GreeterClient(channel);
21 | var reply = await client.SayHelloAsync(
22 | new HelloRequest { Name = "GreeterClient" });
23 | Console.WriteLine("Greeting: " + reply.Message);
24 | Console.WriteLine("Press any key to exit...");
25 | Console.ReadKey();
26 |
--------------------------------------------------------------------------------
/NpgCli/NpgCli.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 | true
9 | true
10 | false
11 |
12 | false
13 | true
14 | $(DefineConstants);NO_GLOBALIZATION
15 | true
16 | true
17 | true
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/NpgCliSlim/NpgCliSlim.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 | true
9 | true
10 | false
11 |
12 | false
13 | true
14 | $(DefineConstants);NO_GLOBALIZATION
15 | true
16 | true
17 | true
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/WebApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:59162",
7 | "sslPort": 44350
8 | }
9 | },
10 | "profiles": {
11 | "http": {
12 | "commandName": "Project",
13 | "dotnetRunMessages": true,
14 | "launchBrowser": true,
15 | "applicationUrl": "http://localhost:5243",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "https": {
21 | "commandName": "Project",
22 | "dotnetRunMessages": true,
23 | "launchBrowser": true,
24 | "applicationUrl": "https://localhost:7078;http://localhost:5243",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | },
29 | "IIS Express": {
30 | "commandName": "IISExpress",
31 | "launchBrowser": true,
32 | "environmentVariables": {
33 | "ASPNETCORE_ENVIRONMENT": "Development"
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/WebApiChiseled/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:59162",
7 | "sslPort": 44350
8 | }
9 | },
10 | "profiles": {
11 | "http": {
12 | "commandName": "Project",
13 | "dotnetRunMessages": true,
14 | "launchBrowser": true,
15 | "applicationUrl": "http://localhost:5243",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "https": {
21 | "commandName": "Project",
22 | "dotnetRunMessages": true,
23 | "launchBrowser": true,
24 | "applicationUrl": "https://localhost:7078;http://localhost:5243",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | },
29 | "IIS Express": {
30 | "commandName": "IISExpress",
31 | "launchBrowser": true,
32 | "environmentVariables": {
33 | "ASPNETCORE_ENVIRONMENT": "Development"
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/GrpcApi/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
2 | WORKDIR /app
3 | # these RUN lines below is optimization for current experiment to account for the fact that I have multiple similar configuration
4 | # best practices of Docker building imply that I put all dependencies in single line
5 | RUN apk add clang binutils musl-dev build-base zlib-static
6 | RUN apk add cmake
7 | RUN apk add openssl-dev openssl-libs-static openssl
8 | #RUN apk add protoc
9 | RUN wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub
10 | RUN wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.34-r0/glibc-2.34-r0.apk
11 | RUN apk add --force-overwrite glibc-2.34-r0.apk
12 |
13 | COPY nuget.config .
14 | COPY GrpcApi.csproj .
15 | RUN dotnet restore --runtime linux-musl-x64 GrpcApi.csproj
16 |
17 | COPY . .
18 | RUN dotnet publish -c Release -r linux-musl-x64 -o out GrpcApi.csproj
19 |
20 | FROM scratch AS runtime
21 | WORKDIR /app
22 | COPY --from=build /app/out/GrpcApi /app/
23 | COPY --from=build /etc/ssl/certs/* /etc/ssl/certs/
24 | ENV ASPNETCORE_URLS="https://+;http://+"
25 | EXPOSE 443
26 | EXPOSE 80
27 | ENTRYPOINT ["/app/GrpcApi"]
28 |
--------------------------------------------------------------------------------
/CompressionEmbedding/Program.cs:
--------------------------------------------------------------------------------
1 | using System.IO.Compression;
2 |
3 | // Testing System.IO.Compression native libraries.
4 | TestGzip();
5 | TestBrotli();
6 | TestDeflate();
7 |
8 | static void TestGzip()
9 | {
10 | var sourceStream = new MemoryStream();
11 | using (var stringWriter = new StreamWriter(sourceStream, leaveOpen: true))
12 | {
13 | stringWriter.WriteLine("This is text");
14 | }
15 |
16 | sourceStream.Position = 0;
17 |
18 | var destinationStream = new MemoryStream();
19 | using var compressor = new GZipStream(destinationStream, CompressionMode.Compress);
20 | sourceStream.CopyTo(compressor);
21 | destinationStream.Position = 0;
22 |
23 | Console.WriteLine($"Length of gzip archive is {destinationStream.Length}");
24 | }
25 |
26 | static void TestBrotli()
27 | {
28 | var sourceStream = new MemoryStream();
29 | using (var stringWriter = new StreamWriter(sourceStream, leaveOpen: true))
30 | {
31 | stringWriter.WriteLine("This is text");
32 | }
33 |
34 | sourceStream.Position = 0;
35 |
36 | var destinationStream = new MemoryStream();
37 | using (var compressor = new BrotliStream(destinationStream, CompressionMode.Compress, leaveOpen: true))
38 | {
39 | sourceStream.CopyTo(compressor);
40 | }
41 |
42 | destinationStream.Position = 0;
43 |
44 | Console.WriteLine($"Length of brotli archive is {destinationStream.Length}");
45 | }
46 |
47 | static void TestDeflate()
48 | {
49 | var sourceStream = new MemoryStream();
50 | using (var stringWriter = new StreamWriter(sourceStream, leaveOpen: true))
51 | {
52 | stringWriter.WriteLine("This is text");
53 | }
54 |
55 | sourceStream.Position = 0;
56 |
57 | var destinationStream = new MemoryStream();
58 | using (var compressor = new DeflateStream(destinationStream, CompressionMode.Compress, leaveOpen: true))
59 | {
60 | sourceStream.CopyTo(compressor);
61 | }
62 |
63 | destinationStream.Position = 0;
64 |
65 | Console.WriteLine($"Length of deflate archive is {destinationStream.Length}");
66 | }
67 |
--------------------------------------------------------------------------------
/NativeAOTDocker.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.5.002.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CompressionEmbedding", "CompressionEmbedding\CompressionEmbedding.csproj", "{B7F28D17-41CD-4A1A-95DF-9EDC29EF75BD}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EmbeddedICU", "EmbeddedICU\EmbeddedICU.csproj", "{9609965F-ED5C-4555-B3FB-1AF1321FA688}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GrpcApi", "GrpcApi\GrpcApi.csproj", "{1BCB2BAA-32A3-4F5F-AB97-6C280BA16739}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GrpcApiClient", "GrpcApiClient\GrpcApiClient.csproj", "{F38CEA85-91A7-4793-894E-12F906EF9088}"
13 | EndProject
14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InvariantGlobalization", "InvariantGlobalization\InvariantGlobalization.csproj", "{3D17D717-0CEC-4575-92C3-CF6AED45D939}"
15 | EndProject
16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NpgCli", "NpgCli\NpgCli.csproj", "{4CF174F3-AE9D-428A-91CF-9709CA057D4D}"
17 | EndProject
18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NpgCliSlim", "NpgCliSlim\NpgCliSlim.csproj", "{25960806-4B63-440C-8F0E-5CD4132880C6}"
19 | EndProject
20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenSslEmbedding", "OpenSslEmbedding\OpenSslEmbedding.csproj", "{A2CE7504-FB26-4BD9-BBC9-6B45F63498BF}"
21 | EndProject
22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApi", "WebApi\WebApi.csproj", "{D01B5453-645C-480D-8886-7FBD260D7E42}"
23 | EndProject
24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApiChiseled", "WebApiChiseled\WebApi.csproj", "{F19ED7B2-8F75-4DA9-A79A-C3DCAB27985D}"
25 | EndProject
26 | Global
27 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
28 | Debug|Any CPU = Debug|Any CPU
29 | Release|Any CPU = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
32 | {B7F28D17-41CD-4A1A-95DF-9EDC29EF75BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {B7F28D17-41CD-4A1A-95DF-9EDC29EF75BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {B7F28D17-41CD-4A1A-95DF-9EDC29EF75BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {B7F28D17-41CD-4A1A-95DF-9EDC29EF75BD}.Release|Any CPU.Build.0 = Release|Any CPU
36 | {9609965F-ED5C-4555-B3FB-1AF1321FA688}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {9609965F-ED5C-4555-B3FB-1AF1321FA688}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {9609965F-ED5C-4555-B3FB-1AF1321FA688}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {9609965F-ED5C-4555-B3FB-1AF1321FA688}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {1BCB2BAA-32A3-4F5F-AB97-6C280BA16739}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41 | {1BCB2BAA-32A3-4F5F-AB97-6C280BA16739}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 | {1BCB2BAA-32A3-4F5F-AB97-6C280BA16739}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {1BCB2BAA-32A3-4F5F-AB97-6C280BA16739}.Release|Any CPU.Build.0 = Release|Any CPU
44 | {F38CEA85-91A7-4793-894E-12F906EF9088}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45 | {F38CEA85-91A7-4793-894E-12F906EF9088}.Debug|Any CPU.Build.0 = Debug|Any CPU
46 | {F38CEA85-91A7-4793-894E-12F906EF9088}.Release|Any CPU.ActiveCfg = Release|Any CPU
47 | {F38CEA85-91A7-4793-894E-12F906EF9088}.Release|Any CPU.Build.0 = Release|Any CPU
48 | {3D17D717-0CEC-4575-92C3-CF6AED45D939}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
49 | {3D17D717-0CEC-4575-92C3-CF6AED45D939}.Debug|Any CPU.Build.0 = Debug|Any CPU
50 | {3D17D717-0CEC-4575-92C3-CF6AED45D939}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 | {3D17D717-0CEC-4575-92C3-CF6AED45D939}.Release|Any CPU.Build.0 = Release|Any CPU
52 | {4CF174F3-AE9D-428A-91CF-9709CA057D4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
53 | {4CF174F3-AE9D-428A-91CF-9709CA057D4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
54 | {4CF174F3-AE9D-428A-91CF-9709CA057D4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
55 | {4CF174F3-AE9D-428A-91CF-9709CA057D4D}.Release|Any CPU.Build.0 = Release|Any CPU
56 | {25960806-4B63-440C-8F0E-5CD4132880C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
57 | {25960806-4B63-440C-8F0E-5CD4132880C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
58 | {25960806-4B63-440C-8F0E-5CD4132880C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
59 | {25960806-4B63-440C-8F0E-5CD4132880C6}.Release|Any CPU.Build.0 = Release|Any CPU
60 | {A2CE7504-FB26-4BD9-BBC9-6B45F63498BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
61 | {A2CE7504-FB26-4BD9-BBC9-6B45F63498BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
62 | {A2CE7504-FB26-4BD9-BBC9-6B45F63498BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
63 | {A2CE7504-FB26-4BD9-BBC9-6B45F63498BF}.Release|Any CPU.Build.0 = Release|Any CPU
64 | {D01B5453-645C-480D-8886-7FBD260D7E42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
65 | {D01B5453-645C-480D-8886-7FBD260D7E42}.Debug|Any CPU.Build.0 = Debug|Any CPU
66 | {D01B5453-645C-480D-8886-7FBD260D7E42}.Release|Any CPU.ActiveCfg = Release|Any CPU
67 | {D01B5453-645C-480D-8886-7FBD260D7E42}.Release|Any CPU.Build.0 = Release|Any CPU
68 | {F19ED7B2-8F75-4DA9-A79A-C3DCAB27985D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
69 | {F19ED7B2-8F75-4DA9-A79A-C3DCAB27985D}.Debug|Any CPU.Build.0 = Debug|Any CPU
70 | {F19ED7B2-8F75-4DA9-A79A-C3DCAB27985D}.Release|Any CPU.ActiveCfg = Release|Any CPU
71 | {F19ED7B2-8F75-4DA9-A79A-C3DCAB27985D}.Release|Any CPU.Build.0 = Release|Any CPU
72 | EndGlobalSection
73 | GlobalSection(SolutionProperties) = preSolution
74 | HideSolutionNode = FALSE
75 | EndGlobalSection
76 | GlobalSection(ExtensibilityGlobals) = postSolution
77 | SolutionGuid = {8218E612-1951-481A-8E86-004F87000A74}
78 | EndGlobalSection
79 | EndGlobal
80 |
--------------------------------------------------------------------------------
/calc.fsx:
--------------------------------------------------------------------------------
1 | #r "nuget: MathNet.Numerics, 5.0.0"
2 | #r "nuget: MathNet.Numerics.FSharp, 5.0.0"
3 |
4 | // Illustrates solving systems of simultaneous linear
5 | // equations using the DenseMatrix and LUDecomposition classes
6 | // in the Numerics.NET.LinearAlgebra namespace of Numerics.NET.
7 |
8 | #light
9 |
10 | open System
11 |
12 | open MathNet.Numerics
13 | // The DenseMatrix and LUDecomposition classes reside in the
14 | // Numerics.NET.LinearAlgebra namespace.
15 | open MathNet.Numerics.LinearAlgebra
16 |
17 | // The license is verified at runtime. We're using a 30 day trial key here.
18 | // For more information, see:
19 | // https://numerics.net/trial-key
20 | //let licensed = Numerics.NET.License.Verify("64542-18980-57619-62268")
21 |
22 | // A system of simultaneous linear equations is
23 | // defined by a square matrix A and a right-hand
24 | // side B, which can be a vector or a matrix.
25 | //
26 | // You can use any matrix type for the matrix A.
27 | // The optimal algorithm is automatically selected.
28 |
29 | []
30 | let ConsoleInvariantGlobalization = 0
31 | []
32 | let ConsoleWithICU = 1
33 | []
34 | let ConsoleWithCompression = 2
35 | []
36 | let AppHttpClient = 3
37 | []
38 | let AppHttpClientWithSSL = 4
39 | []
40 | let AppWebApi = 5
41 | []
42 | let AppGrpcApi = 6
43 | []
44 | let AppNpgSqlAdoIcu = 7
45 | []
46 | let AppNpgSqlAdo = 8
47 | []
48 | let AppOpenSSLFiles = 9
49 | []
50 | let AppICU = 10
51 | []
52 | let AppNpgSqlSlimBuilderIcu = 11
53 | []
54 | let AppNpgSqlSlimBuilder = 12
55 |
56 | []
57 | let ComponentRuntime = 0
58 | []
59 | let ComponentGlobalizationSupport = 1
60 | []
61 | let ComponentCompressionSupport = 2
62 | []
63 | let ComponentHttpClient = 3
64 | []
65 | let ComponentOpenSSLSupport = 4
66 | []
67 | let ComponentWebApi = 5
68 | []
69 | let ComponentGrpc = 6
70 | []
71 | let ComponentNpgsqlAdoNet = 7
72 | []
73 | let ComponentOpenSSLCertificates = 8
74 | []
75 | let ComponentICUDatafiles = 9
76 | []
77 | let ComponentNpgsqlBuilderSlim = 10
78 |
79 | let m = Matrix.Build.Dense(13, 11)
80 | // Console + Invariant globalization
81 | m[ConsoleInvariantGlobalization, ComponentRuntime] <- 1.0
82 | // Console + ICU
83 | m[ConsoleWithICU,ComponentRuntime] <- 1.0
84 | m[ConsoleWithICU,ComponentGlobalizationSupport] <- 1.0
85 | m[ConsoleWithICU,ComponentICUDatafiles] <- 1.0
86 | // Console + Brotli + Deflate + Gzip
87 | m[ConsoleWithCompression,ComponentRuntime] <- 1.0
88 | m[ConsoleWithCompression,ComponentCompressionSupport] <- 1.0
89 | // HttpClient
90 | m[AppHttpClient,ComponentRuntime] <- 1.0
91 | m[AppHttpClient,ComponentHttpClient] <- 1.0
92 | // HttpClient + OpenSSL
93 | m[AppHttpClientWithSSL,ComponentRuntime] <- 1.0
94 | m[AppHttpClientWithSSL,ComponentHttpClient] <- 1.0
95 | m[AppHttpClientWithSSL,ComponentOpenSSLSupport] <- 1.0
96 | m[AppHttpClientWithSSL,ComponentOpenSSLCertificates] <- 1.0
97 | // Web API
98 | m[AppWebApi,ComponentRuntime] <- 1.0
99 | m[AppWebApi,ComponentWebApi] <- 1.0
100 | // Grpc API
101 | m[AppGrpcApi,ComponentRuntime] <- 1.0
102 | m[AppGrpcApi,ComponentGrpc] <- 1.0
103 | // Npgsql ADO.NET + ICU
104 | m[AppNpgSqlAdoIcu,ComponentRuntime] <- 1.0
105 | m[AppNpgSqlAdoIcu,ComponentNpgsqlAdoNet] <- 1.0
106 | m[AppNpgSqlAdoIcu,ComponentGlobalizationSupport] <- 1.0
107 | m[AppNpgSqlAdoIcu,ComponentICUDatafiles] <- 1.0
108 | // Npgsql ADO.NET + Invariant globalization
109 | m[AppNpgSqlAdo,ComponentRuntime] <- 1.0
110 | m[AppNpgSqlAdo,ComponentNpgsqlAdoNet] <- 1.0
111 | // OpenSSL certificates
112 | m[AppOpenSSLFiles,ComponentOpenSSLCertificates] <- 1.0
113 | // Npgsql ADO.NET + Invariant globalization
114 | m[AppICU,ComponentICUDatafiles] <- 1.0
115 | // Npgsql ADO.NET + ICU
116 | m[AppNpgSqlSlimBuilderIcu,ComponentRuntime] <- 1.0
117 | m[AppNpgSqlSlimBuilderIcu,ComponentNpgsqlBuilderSlim] <- 1.0
118 | m[AppNpgSqlSlimBuilderIcu,ComponentGlobalizationSupport] <- 1.0
119 | m[AppNpgSqlSlimBuilderIcu,ComponentICUDatafiles] <- 1.0
120 | // Npgsql ADO.NET + Invariant globalization
121 | m[AppNpgSqlSlimBuilder,ComponentRuntime] <- 1.0
122 | m[AppNpgSqlSlimBuilder,ComponentNpgsqlBuilderSlim] <- 1.0
123 |
124 | // Console + ICU
125 | let b1 = vector[
126 | 1.29; // Console + Invariant globalization (nativeaot-scratch-invariant)
127 | 35.14; // Console + ICU
128 | 2.22; // Console + Brotli + Deflate + Gzip (nativeaot-scratch-compression)
129 | 7.26; // HttpClient (nativeaot-scratch-http-client)
130 | 12.16; // HttpClient + OpenSSL (nativeaot-scratch-openssl)
131 | 21.94; // Web API (nativeaot-scratch-webapi)
132 | 23.46; // Grpc API (nativeaot-scratch-grpcapi)
133 | 50.98; // Npgsql ADO.NET + ICU (nativeaot-scratch-npgsql)
134 | 17.08; // Npgsql ADO.NET + Invariant globalization (nativeaot-scratch-npgsql-noicu)
135 | 0.; // OpenSSL certificates
136 | 0.; // ICU data
137 | 44.1; // NpgsqlSlimDataSourceBuilder + ICU (nativeaot-scratch-npgsql)
138 | 10.2; // NpgsqlSlimDataSourceBuilder + Invariant globalization (nativeaot-scratch-npgsql-noicu)
139 | ]
140 |
141 | Vector.Build.Dense(11)
142 | // Static immutable data
143 | b1[AppOpenSSLFiles] <- 0.64
144 | b1[AppICU] <- 29.4
145 |
146 | //
147 | // The Solve method
148 | //
149 |
150 | // The following solves m x = b1. The second
151 | // parameter specifies whether to overwrite the
152 | // right-hand side with the result.
153 | let x1 = m.Solve(b1)
154 | printfn "| Component | Size |"
155 | printfn "| ------------ | ----- |"
156 | printfn "| Barebone runtime + console | %.2fMB |" x1[ComponentRuntime]
157 | printfn "| ICU data | %.2fMB | " x1[ComponentICUDatafiles]
158 | printfn "| Globalization support | %.2fMB |" x1[ComponentGlobalizationSupport]
159 | printfn "| Brotli + Deflate + Gzip | %.2fMB |" x1[ComponentCompressionSupport]
160 | printfn "| HttpClient | %.2fMB |" x1[ComponentHttpClient]
161 | printfn "| OpenSSL | %.2fMB |" x1[ComponentOpenSSLSupport]
162 | printfn "| OpenSSL certificates | %.2fMB |" x1[ComponentOpenSSLCertificates]
163 | printfn "| Web API | %.2fMB |" x1[ComponentWebApi]
164 | printfn "| Grpc API | %.2fMB |" x1[ComponentGrpc]
165 | printfn "| Npgsql ADO.NET | %.2fMB |" x1[ComponentNpgsqlAdoNet]
166 | printfn "| Npgsql Builder Slim | %.2fMB |" x1[ComponentNpgsqlBuilderSlim]
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Scratch docker image using C#
2 | =============================
3 |
4 | This repository is sample how to statically link console application into single executable and run on Docker.
5 |
6 | # Results
7 |
8 | This is sizes for experiment
9 |
10 | | Experiment | Size | Embed ICU | Embed OpenSSL |
11 | | ------------ | ----- | --- | ---------- |
12 | | Console + Invariant globalization | 1.29 MB | No | No |
13 | | Console + ICU | 35.14 MB | Yes | No |
14 | | Console + Brotli + Deflate + Gzip | 2.22 MB | No | No |
15 | | HttpClient | 7.26 MB | No | No |
16 | | HttpClient + OpenSSL | 12.16 MB | No | Yes |
17 | | Web API | 21.94 MB | No | Yes |
18 | | Grpc API | 23.46 MB | No | Yes |
19 | | Npgsql ADO.NET + ICU | 50.98 MB | Yes | Yes |
20 | | Npgsql ADO.NET + Invariant globalization | 17.08 MB | No | Yes |
21 | | Npgsql Builder Slim + ICU | 44.1 MB | Yes | Yes |
22 | | Npgsql Builder Slim + Invariant globalization | 10.2 MB | No | Yes |
23 |
24 | Chilsed for comparison
25 |
26 | | Experiment | Size | Embed ICU | Embed OpenSSL |
27 | | ------------ | ----- | --- | ---------- |
28 | | Web API | 30.46 MB | No | No |
29 |
30 | Resulting docker image have size of 1.56 MB. Thats after disabling reflection. That's the minimum which I can get without integrating with Docker tightly. Or is it kernel integration I'm dreaming about? Unikernels, I see unikernels around me
31 |
32 | # Sizes of the components
33 |
34 | Based on results I get approximate minimum size of code which added to your application if you using these libraries.
35 |
36 | | Component | Size |
37 | | ------------ | ----- |
38 | | Barebone runtime + console | 1.28MB |
39 | | ICU data | 29.40MB |
40 | | Globalization support | 4.47MB |
41 | | Brotli + Deflate + Gzip | 0.94MB |
42 | | HttpClient | 5.98MB |
43 | | OpenSSL | 4.26MB |
44 | | OpenSSL certificates | 0.64MB |
45 | | Web API | 20.66MB |
46 | | Grpc API | 22.18MB |
47 | | Npgsql ADO.NET | 15.82MB |
48 | | Npgsql Builder Slim | 8.93MB |
49 |
50 | # Build and Run
51 |
52 | ## Embedded ICU - 35.14 MB
53 | ```shell
54 | docker build -t nativeaot-scratch EmbeddedICU
55 | docker run -i nativeaot-scratch
56 | ```
57 |
58 | 30 MB is ICU data.
59 |
60 | ## Invariant globalization - 1.29 MB
61 | ```shell
62 | docker build -t nativeaot-scratch-invariant InvariantGlobalization
63 | docker run -i nativeaot-scratch-invariant
64 | ```
65 |
66 | ## Brotli + Deflate + Gzip - 2.22 MB
67 | ```shell
68 | docker build -t nativeaot-scratch-compression CompressionEmbedding
69 | docker run -i nativeaot-scratch-compression
70 | ```
71 |
72 | ## HttpClient - 7.26 MB
73 | with reflection unfortunately
74 | ```shell
75 | docker build -t nativeaot-scratch-http-client -f OpenSslEmbedding/Dockerfile.nossl OpenSslEmbedding
76 | docker run -i nativeaot-scratch-http-client
77 | ```
78 |
79 | ## HttpClient + OpenSSL - 12.16 MB
80 | with reflection unfortunately
81 | ```shell
82 | docker build -t nativeaot-scratch-openssl OpenSslEmbedding
83 | docker run -i nativeaot-scratch-openssl
84 | ```
85 |
86 | ## Web API - 21.94 MB
87 | with reflection unfortunately
88 | ```shell
89 | docker build -t nativeaot-scratch-webapi WebApi
90 | docker run -p 5022:80 -i nativeaot-scratch-webapi
91 | ```
92 |
93 | Web API accessible on http://localhost:5022.
94 |
95 | For SSL configuration take a look at https://learn.microsoft.com/en-us/dotnet/core/additional-tools/self-signed-certificates-guide#with-openssl nd create `certs` folder with certificates. Then you can run following command.
96 |
97 | ```
98 | docker run --rm -it -p 8000:80 -p 8001:443 -e ASPNETCORE_URLS="https://+;http://+" -e ASPNETCORE_HTTPS_PORT=8001 -e ASPNETCORE_ENVIRONMENT=Development -e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/contoso.com.crt -e ASPNETCORE_Kestrel__Certificates__Default__KeyPath=/https/contoso.com.key -v $PWD\certs/:/https/ nativeaot-scratch-webapi
99 | ```
100 |
101 | Web API accessible on http://localhost:8000 and https://localhost:8001.
102 |
103 | ## GrpcApi - 23.46 MB
104 | with reflection unfortunately
105 | ```shell
106 | docker build -t nativeaot-scratch-grpcapi GrpcApi
107 | docker run --rm -it -p 8010:80 -p 8011:443 -e ASPNETCORE_URLS="https://+;http://+" -e ASPNETCORE_HTTPS_PORT=8001 -e ASPNETCORE_ENVIRONMENT=Development -e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/contoso.com.crt -e ASPNETCORE_Kestrel__Certificates__Default__KeyPath=/https/contoso.com.key -v $PWD\certs/:/https/ nativeaot-scratch-grpcapi
108 | ```
109 |
110 | ## NpgCli + Globalization - 50.98 MB
111 | with reflection unfortunately
112 | ```shell
113 | docker build -t nativeaot-scratch-npgsql NpgCli
114 | docker run -i -e ConnectionString='Host=172.17.0.2;Username=postgres;Password=postgrespw' nativeaot-scratch-npgsql
115 | ```
116 |
117 | ## NpgCli - 17.08 MB
118 | with reflection unfortunately
119 | ```shell
120 | docker build -t nativeaot-scratch-npgsql-noicu NpgCli -f NpgCli/Dockerfile.noicu
121 | docker run -i -e ConnectionString='Host=172.17.0.2;Username=postgres;Password=postgrespw' nativeaot-scratch-npgsql-noicu
122 | ```
123 |
124 | ## Web API on Chiseled - 30.46 MB
125 | with reflection unfortunately
126 | ```shell
127 | docker build -t nativeaot-scratch-webapi-chiseled WebApiChiseled
128 | docker run -p 5122:80 -i nativeaot-scratch-webapi-chiseled
129 | ```
130 |
131 | Web API accessible on http://localhost:5122.
132 |
133 | docker run --rm -it -p 8000:80 -p 8001:443 -e ASPNETCORE_URLS="https://+;http://+" -e ASPNETCORE_HTTPS_PORT=8001 -e ASPNETCORE_ENVIRONMENT=Development -e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/contoso.com.crt -e ASPNETCORE_Kestrel__Certificates__Default__KeyPath=/https/contoso.com.key -v $PWD\certs/:/https/ nativeaot-scratch-webapi
134 |
135 |
136 | # Inspeciting scratch container
137 |
138 | You can use dive
139 | ```shell
140 | docker run --rm -it `
141 | -v /var/run/docker.sock:/var/run/docker.sock `
142 | wagoodman/dive:latest nativeaot-scratch
143 | ```
144 |
145 | or export tar with container
146 |
147 | ```
148 | docker save nativeaot-scratch -o nativeaot-scratch.tar
149 | ```
150 |
151 | # Testing that building inside Alpine works.
152 |
153 | That's was needed when NativeAOT does not have objwriter for musl. Still interesting if you need to build augment ObjWriter.
154 | ```
155 | docker build -t test-build -f Dockerfile.objwriter .
156 | ```
157 |
158 | # Smoke test for ObjWriter build
159 |
160 | ```
161 | docker build -t nativeaot-scratch-build -f Dockerfile.objwriter .
162 | docker run -i nativeaot-scratch-build
163 | ```
164 |
165 | Compiled `libobjwriter.so` is located at `artifacts/obj/InstallRoot-/lib` inside docker.
166 |
167 |
168 | ```
169 | docker run --name postgres-aot -e "POSTGRES_USER=postgres" -e "POSTGRES_PASSWORD=postgrespw" -p 5432:32768 -d postgres
170 | ```
--------------------------------------------------------------------------------