Skip to content

Docker Exercise 5

Docker Exercise 5

Create a new C# Minimal API project (use at least dotnet 8) and use this Program.cs file:

using Microsoft.AspNetCore.Mvc;
// Setup
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
// Endpoint mapping
app.MapPost("/add", SaveFile);
app.MapGet("get/{name}", GetFileContent);
// Endpoint implementation
async Task<IResult> GetFileContent([FromRoute] string name)
{
var fileNames = FileNames.FromInput(name);
if (!File.Exists(fileNames.PersistentFilePath))
{
return Results.NotFound();
}
var content = await File.ReadAllTextAsync(fileNames.PersistentFilePath);
return Results.Ok(content);
}
async Task SaveFile([FromBody] AddRequest addRequest)
{
var fileNames = FileNames.FromInput(addRequest.Name);
await using (var sw = File.CreateText(fileNames.TempFilePath))
{
await sw.WriteAsync(addRequest.Content);
}
if (File.Exists(fileNames.TempFilePath))
{
File.Move(
fileNames.TempFilePath,
fileNames.PersistentFilePath,
overwrite: true);
}
}
if (!Directory.Exists("./temp"))
{
Directory.CreateDirectory("./temp");
}
if (!Directory.Exists("./persistent"))
{
Directory.CreateDirectory("./persistent");
}
app.Run();
public class FileNames
{
public string FileName { get; set; }
public string TempFilePath
{
get => "./temp/" + FileName;
}
public string PersistentFilePath
{
get => "./persistent/" + FileName;
}
public static FileNames FromInput(string name) =>
new()
{
FileName = SanitizeFileName(name) + ".txt"
};
private static string SanitizeFileName(string name)
{
string invalidChars = System.Text.RegularExpressions.Regex.Escape( new string( Path.GetInvalidFileNameChars() ) );
string invalidRegStr = string.Format( @"([{0}]*\.+$)|([{0}]+)", invalidChars );
return System.Text.RegularExpressions.Regex.Replace( name, invalidRegStr, "_" );
}
}
public class AddRequest
{
public string Name { get; set; }
public string Content { get; set; }
}

In this exercise you will have to perform a lot of steps without any explanation. Your goal is to find your own conclusions on how data is stored inside and outside containers and how volumes work. It is highly recommended that you document your findings after each step.

Instructions

  • Dockerize this application using a Dockerfile. You will need these commands:
    • dotnet restore <path to .csproj file>
    • dotnet build <path to .csproj file> -c Release -o <output path>
    • dotnet publish <path to .csproj file> -c Release -o <output path> /p:UseAppHost=false
  • Create an image using the tag volumes-exercise
  • Start a container using this image using docker run -d -p 8080:8080 --name volumescontainer volumes-exercise
  • Try using the provided API to generate and access files within the container
  • Use docker exec -it volumescontainer bash to connect to a bash shell inside the container. Analyse which files are generated.
  • Stop and restart the container using docker stop volumescontainer and docker start volumescontainer
  • Analyse if the files are still there.
  • Stop and remove the container.
  • Start a new container from the image using docker run -d -p 8080:8080 --rm --name volumescontainer volumes-exercise
  • Analyse if the files are still there.
  • Stop the container (this should also remove the container since you used the --rm flag)
  • Define a volume inside the container, adding this line to the Dockerfile: VOLUME ["/app/persistent"]
  • Rebuild the image
  • Inspect the image and check if the volume is defined
  • Start a new container from the image using docker run -d -p 8080:8080 --rm --name volumescontainer volumes-exercise
    • Note: In recent Images provided by Microsoft, the App runs under the user app, yet if you create a volume as described above, the created folder will be owned by the root user. Therefore the application won’t have write access to this folder. To change the ownership of that folder add these lines to the Dockerfile:
      VOLUME ["/app/persistent"]
      RUN mkdir /app/persistent
      RUN chown app /app/persistent
  • Again use the API and check if the files are created accordingly.
  • Use Docker desktop to analyse if a volume has been created.
  • Stop the container (thus removing it).
  • Check if the volume is still there
  • Start a new container and analyse if the files are still there.
  • Stop the container (thus removing it).
  • Start a new container from the image using docker run -d -p 8081:8080 -v myvolume:/app/persistent --rm --name volumescontainer volumes-exercise
  • Generate data
  • Stop and remove the container
  • Check if the volume is still there
  • Start a new container from the image using docker run -d -p 8081:8080 -v myvolume:/app/persistent --rm --name volumescontainer volumes-exercise
  • Check if the files are still there.