diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..cc3f8db195ef9dcc092cedc977a40419ff331adc
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,10 @@
+**/bin/
+**/obj/
+**/.vscode/
+*.vsix
+*.user
+*.userosscache
+*.dbmdl
+*.jfm
+node_modules/
+npm-debug.log
diff --git a/Orchestration/.env.example b/.env.example
similarity index 100%
rename from Orchestration/.env.example
rename to .env.example
diff --git a/.gitignore b/.gitignore
index a0ff5e6ea099445cbd7dae1c4b9262fec2c2d0e7..ef957f02d9deaaf0d0310da0b96fb3a293040443 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,7 +7,6 @@
 .env
 
 # appsettings
-appsettings.json
 appsettings.Development.json
 
 # User-specific files
diff --git a/Api/Program.cs b/Api/Program.cs
index a5757e372827a229dab88a48b4991bdfa9f7a39c..d1ad0d5c8deb1efd69931495bf0425ed35dc874a 100644
--- a/Api/Program.cs
+++ b/Api/Program.cs
@@ -27,10 +27,15 @@ builder.Logging.AddElasticsearch(options =>
     options.Index = new IndexNameOptions { Format = elasticConfig.GetValue<string>("Index")! };
 });
 
-// Add services to the container.
+bool inContainer = false;
+_ = bool.TryParse(builder.Configuration["DOTNET_RUNNING_IN_CONTAINER"], out inContainer);
+
+string? connString = inContainer 
+    ? builder.Configuration.GetConnectionString("MSSQL_DOCKER")
+    : builder.Configuration.GetConnectionString("MSSQL");
+
 builder.Services.AddDbContextFactory<RestaurantDBContext>(options =>
-    options.UseSqlServer(
-        builder.Configuration.GetConnectionString("MSSQL"))
+    options.UseSqlServer(connString)
 );
 
 builder.Services.AddScoped<IEventService, EventService>();
diff --git a/Api/appsettings-example.json b/Api/appsettings-example.json
index 7b70aa1e42e2b3ebbfb74d323b3400c627fd6be1..c77cff9246a4149d02d6b2f87ebd40b3d1fcc610 100644
--- a/Api/appsettings-example.json
+++ b/Api/appsettings-example.json
@@ -1,13 +1,18 @@
 {
     "ConnectionStrings": {
-      "MSSQL": "EXAMPLE_STRING"
+      "MSSQL": "EXAMPLE_STRING",
+      "MSSQL_DOCKER": "EXAMPLE_STRING"
     },
   "Logging": {
     "Elasticsearch": {
       "NodeUris": [ "http://localhost:9200" ],
       "Index": "biterate-logs-{0:yyyy.MM.dd}",
       "ApplicationName": "BiteRate",
-      "MinimumLogEventLevel": "Information"
+      "MinimumLogEventLevel": "Information",
+      "ShipTo": {
+        "NodePoolType": "SingleNode",
+        "NodeUris": [ "http://elastic-search:9200" ]
+      }
     },
     "LogLevel": {
       "Default": "Information",
diff --git a/Api/appsettings.json b/Api/appsettings.json
new file mode 100644
index 0000000000000000000000000000000000000000..0411870ff40d4f9a45be50db27ed26aa363b3bfe
--- /dev/null
+++ b/Api/appsettings.json
@@ -0,0 +1,23 @@
+{
+  "ConnectionStrings": {
+    "MSSQL": "Server=127.0.0.1,1433;Database=master;User Id=SA;Password=Example123;TrustServerCertificate=True;",
+    "MSSQL_DOCKER": "Server=db,1433;Database=master;User Id=SA;Password=Example123;TrustServerCertificate=True;"
+  },
+  "Logging": {
+    "Elasticsearch": {
+      "NodeUris": [ "http://localhost:9200" ],
+      "Index": "biterate-logs-{0:yyyy.MM.dd}",
+      "ApplicationName": "BiteRate",
+      "MinimumLogEventLevel": "Information",
+      "ShipTo": {
+        "NodePoolType": "SingleNode",
+        "NodeUris": [ "http://elastic-search:9200" ]
+      }
+    },
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft.AspNetCore": "Warning"
+    }
+  },
+  "AllowedHosts": "*"
+  }
\ No newline at end of file
diff --git a/DAL/Migrations/20241115150548_Init.Designer.cs b/DAL/Migrations/20241115150548_Init.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..cd36881b8016044918f9122d3604420a84805429
--- /dev/null
+++ b/DAL/Migrations/20241115150548_Init.Designer.cs
@@ -0,0 +1,814 @@
+// <auto-generated />
+using System;
+using DAL.Data;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace DAL.Migrations
+{
+    [DbContext(typeof(RestaurantDBContext))]
+    [Migration("20241115150548_Init")]
+    partial class Init
+    {
+        /// <inheritdoc />
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "8.0.8")
+                .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+            SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+            modelBuilder.Entity("DAL.Models.Event", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<string>("Content")
+                        .IsRequired()
+                        .HasMaxLength(3600)
+                        .HasColumnType("nvarchar(3600)");
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime>("Date")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime?>("DeletedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<Guid>("RestaurantId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<string>("Title")
+                        .IsRequired()
+                        .HasMaxLength(100)
+                        .HasColumnType("nvarchar(100)");
+
+                    b.Property<DateTime>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("RestaurantId");
+
+                    b.ToTable("Events");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = new Guid("10ba7f93-895f-4be5-987e-45e6d55bda3f"),
+                            Content = "Join us for an exclusive dinner with gourmet cuisine.",
+                            CreatedAt = new DateTime(2024, 10, 20, 12, 20, 23, 0, DateTimeKind.Unspecified),
+                            Date = new DateTime(2024, 10, 30, 12, 20, 23, 0, DateTimeKind.Unspecified),
+                            RestaurantId = new Guid("104fdc28-a328-4f7b-85fe-81550cf1e247"),
+                            Title = "Exclusive Dinner Event",
+                            UpdatedAt = new DateTime(2024, 10, 20, 12, 20, 23, 0, DateTimeKind.Unspecified)
+                        },
+                        new
+                        {
+                            Id = new Guid("c68be8ab-fc64-456a-a5fb-f97f2a96e2d1"),
+                            Content = "An evening of exquisite wine tasting with fine cheeses.",
+                            CreatedAt = new DateTime(2024, 10, 12, 10, 23, 23, 0, DateTimeKind.Unspecified),
+                            Date = new DateTime(2024, 10, 27, 10, 23, 23, 0, DateTimeKind.Unspecified),
+                            RestaurantId = new Guid("104fdc28-a328-4f7b-85fe-81550cf1e247"),
+                            Title = "Wine Tasting Evening",
+                            UpdatedAt = new DateTime(2024, 10, 12, 10, 23, 23, 0, DateTimeKind.Unspecified)
+                        });
+                });
+
+            modelBuilder.Entity("DAL.Models.EventComment", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<string>("Content")
+                        .IsRequired()
+                        .HasMaxLength(1800)
+                        .HasColumnType("nvarchar(1800)");
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime?>("DeletedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<Guid>("EventId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<Guid?>("ParentCommentId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<Guid>("PosterId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<DateTime>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("EventId");
+
+                    b.HasIndex("ParentCommentId");
+
+                    b.HasIndex("PosterId");
+
+                    b.ToTable("EventComments");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = new Guid("88a4b4d4-b74d-40c5-823e-e708f15664d3"),
+                            Content = "Looking forward to this event!",
+                            CreatedAt = new DateTime(2024, 10, 21, 18, 23, 23, 0, DateTimeKind.Unspecified),
+                            EventId = new Guid("10ba7f93-895f-4be5-987e-45e6d55bda3f"),
+                            PosterId = new Guid("32669bac-a1bd-4e9d-9580-ee4a7764cda3"),
+                            UpdatedAt = new DateTime(2024, 10, 21, 18, 23, 23, 0, DateTimeKind.Unspecified)
+                        },
+                        new
+                        {
+                            Id = new Guid("e0e27f5b-bd6f-47d9-b5fa-5b7e7e77d462"),
+                            Content = "Me too! It sounds like a great night.",
+                            CreatedAt = new DateTime(2024, 10, 21, 19, 26, 23, 0, DateTimeKind.Unspecified),
+                            EventId = new Guid("10ba7f93-895f-4be5-987e-45e6d55bda3f"),
+                            ParentCommentId = new Guid("88a4b4d4-b74d-40c5-823e-e708f15664d3"),
+                            PosterId = new Guid("afde48a8-99e3-423e-a48d-9e4e6a3d823a"),
+                            UpdatedAt = new DateTime(2024, 10, 21, 19, 26, 23, 0, DateTimeKind.Unspecified)
+                        });
+                });
+
+            modelBuilder.Entity("DAL.Models.EventParticipant", b =>
+                {
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<Guid>("EventId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<int>("Attendance")
+                        .HasColumnType("int");
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime?>("DeletedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.HasKey("UserId", "EventId");
+
+                    b.HasIndex("EventId");
+
+                    b.ToTable("EventParticipants");
+
+                    b.HasData(
+                        new
+                        {
+                            UserId = new Guid("99499984-8947-4b85-bea2-9cfd487c55d3"),
+                            EventId = new Guid("10ba7f93-895f-4be5-987e-45e6d55bda3f"),
+                            Attendance = 0,
+                            CreatedAt = new DateTime(2024, 10, 20, 12, 20, 23, 0, DateTimeKind.Unspecified),
+                            UpdatedAt = new DateTime(2024, 10, 20, 12, 20, 23, 0, DateTimeKind.Unspecified)
+                        },
+                        new
+                        {
+                            UserId = new Guid("afde48a8-99e3-423e-a48d-9e4e6a3d823a"),
+                            EventId = new Guid("10ba7f93-895f-4be5-987e-45e6d55bda3f"),
+                            Attendance = 1,
+                            CreatedAt = new DateTime(2024, 10, 21, 10, 23, 23, 0, DateTimeKind.Unspecified),
+                            UpdatedAt = new DateTime(2024, 10, 21, 10, 23, 23, 0, DateTimeKind.Unspecified)
+                        },
+                        new
+                        {
+                            UserId = new Guid("32669bac-a1bd-4e9d-9580-ee4a7764cda3"),
+                            EventId = new Guid("10ba7f93-895f-4be5-987e-45e6d55bda3f"),
+                            Attendance = 3,
+                            CreatedAt = new DateTime(2024, 10, 20, 15, 20, 23, 0, DateTimeKind.Unspecified),
+                            UpdatedAt = new DateTime(2024, 10, 20, 15, 20, 23, 0, DateTimeKind.Unspecified)
+                        },
+                        new
+                        {
+                            UserId = new Guid("afde48a8-99e3-423e-a48d-9e4e6a3d823a"),
+                            EventId = new Guid("c68be8ab-fc64-456a-a5fb-f97f2a96e2d1"),
+                            Attendance = 1,
+                            CreatedAt = new DateTime(2024, 10, 12, 10, 23, 23, 0, DateTimeKind.Unspecified),
+                            UpdatedAt = new DateTime(2024, 10, 12, 10, 23, 23, 0, DateTimeKind.Unspecified)
+                        });
+                });
+
+            modelBuilder.Entity("DAL.Models.Location", b =>
+                {
+                    b.Property<Guid>("RestaurantId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<string>("Address")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<string>("City")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<string>("Country")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime?>("DeletedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("Zipcode")
+                        .IsRequired()
+                        .HasMaxLength(5)
+                        .HasColumnType("nvarchar(5)");
+
+                    b.HasKey("RestaurantId");
+
+                    b.ToTable("Locations");
+
+                    b.HasData(
+                        new
+                        {
+                            RestaurantId = new Guid("104fdc28-a328-4f7b-85fe-81550cf1e247"),
+                            Address = "Dřevařská 806/22",
+                            City = "Brno",
+                            Country = "Czech Republic",
+                            CreatedAt = new DateTime(2024, 10, 1, 6, 7, 23, 0, DateTimeKind.Unspecified),
+                            UpdatedAt = new DateTime(2024, 10, 1, 6, 7, 23, 0, DateTimeKind.Unspecified),
+                            Zipcode = "60200"
+                        },
+                        new
+                        {
+                            RestaurantId = new Guid("e9921304-5657-40b2-9bb6-28ca03d3a45e"),
+                            Address = "Štefánikova 39",
+                            City = "Brno",
+                            Country = "Czech Republic",
+                            CreatedAt = new DateTime(2024, 10, 1, 12, 1, 0, 0, DateTimeKind.Unspecified),
+                            UpdatedAt = new DateTime(2024, 10, 1, 12, 1, 0, 0, DateTimeKind.Unspecified),
+                            Zipcode = "60200"
+                        });
+                });
+
+            modelBuilder.Entity("DAL.Models.Restaurant", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<string>("About")
+                        .HasMaxLength(3600)
+                        .HasColumnType("nvarchar(3600)");
+
+                    b.Property<string>("Category")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime?>("DeletedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("Email")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<string>("Phone")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<DateTime>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("Web")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Restaurants");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = new Guid("104fdc28-a328-4f7b-85fe-81550cf1e247"),
+                            About = "V tomhle jednoduchém, ale útulném podniku se zahrádkou je k dostání poctivé jídlo i pivo několika pivovarů.",
+                            Category = "pub",
+                            CreatedAt = new DateTime(2024, 10, 1, 6, 7, 23, 0, DateTimeKind.Unspecified),
+                            Email = "info@udrevaka.cz",
+                            Name = "U Dřeváka Beer&Grill",
+                            Phone = "724 000 723",
+                            UpdatedAt = new DateTime(2024, 10, 1, 6, 7, 23, 0, DateTimeKind.Unspecified),
+                            Web = "https://udrevaka.cz/"
+                        },
+                        new
+                        {
+                            Id = new Guid("e9921304-5657-40b2-9bb6-28ca03d3a45e"),
+                            About = "Authentic Neapolitan Pizza // The taste of Naples in Brno",
+                            Category = "pizza",
+                            CreatedAt = new DateTime(2024, 10, 1, 12, 1, 0, 0, DateTimeKind.Unspecified),
+                            Email = "",
+                            Name = "Doe Boy Brno",
+                            Phone = "773 993 222",
+                            UpdatedAt = new DateTime(2024, 10, 1, 12, 1, 0, 0, DateTimeKind.Unspecified),
+                            Web = "https://facebook.com/pages/category/Pizza-Place/Doe-Boy-Brno-101177877951369/"
+                        });
+                });
+
+            modelBuilder.Entity("DAL.Models.Review", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<string>("Content")
+                        .IsRequired()
+                        .HasMaxLength(3600)
+                        .HasColumnType("nvarchar(3600)");
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime?>("DeletedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<long>("EnvironmentRating")
+                        .HasColumnType("bigint");
+
+                    b.Property<long>("FoodRating")
+                        .HasColumnType("bigint");
+
+                    b.Property<bool?>("LeftTip")
+                        .HasColumnType("bit");
+
+                    b.Property<Guid>("PosterId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<Guid>("RestaurantId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<bool?>("ServesFreeWater")
+                        .HasColumnType("bit");
+
+                    b.Property<long>("ServiceRating")
+                        .HasColumnType("bigint");
+
+                    b.Property<float?>("TimeSpent")
+                        .HasColumnType("real");
+
+                    b.Property<DateTime>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("PosterId");
+
+                    b.HasIndex("RestaurantId");
+
+                    b.ToTable("Reviews");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = new Guid("32669bac-a1bd-4e9d-9580-ee4a7764cda3"),
+                            Content = "The food was pretty good, but there were a lot of people and I could barely hear my friend. Due to this, the service was quite busy and it took them a while to get me food.",
+                            CreatedAt = new DateTime(2024, 10, 4, 23, 39, 1, 0, DateTimeKind.Unspecified),
+                            EnvironmentRating = 3L,
+                            FoodRating = 8L,
+                            LeftTip = false,
+                            PosterId = new Guid("afde48a8-99e3-423e-a48d-9e4e6a3d823a"),
+                            RestaurantId = new Guid("104fdc28-a328-4f7b-85fe-81550cf1e247"),
+                            ServiceRating = 1L,
+                            TimeSpent = 65.07f,
+                            UpdatedAt = new DateTime(2024, 10, 4, 23, 39, 1, 0, DateTimeKind.Unspecified)
+                        },
+                        new
+                        {
+                            Id = new Guid("e8f210bd-5666-40c7-bc61-4d8ef17c5191"),
+                            Content = "Good restaurant, very enjoy. Environment not so good - toilet door stuck. Send help.",
+                            CreatedAt = new DateTime(2024, 10, 5, 20, 5, 16, 0, DateTimeKind.Unspecified),
+                            EnvironmentRating = 1L,
+                            FoodRating = 10L,
+                            LeftTip = false,
+                            PosterId = new Guid("99499984-8947-4b85-bea2-9cfd487c55d3"),
+                            RestaurantId = new Guid("104fdc28-a328-4f7b-85fe-81550cf1e247"),
+                            ServesFreeWater = true,
+                            ServiceRating = 9L,
+                            TimeSpent = 3f,
+                            UpdatedAt = new DateTime(2024, 10, 5, 20, 5, 16, 0, DateTimeKind.Unspecified)
+                        },
+                        new
+                        {
+                            Id = new Guid("d748b6c9-8d9b-4809-b425-766cfc705b01"),
+                            Content = "The pizza is great, burned my tongue with how excited I was to eat. Service was decent. The environment was amazing, too!",
+                            CreatedAt = new DateTime(2024, 10, 10, 16, 41, 2, 0, DateTimeKind.Unspecified),
+                            EnvironmentRating = 8L,
+                            FoodRating = 10L,
+                            LeftTip = true,
+                            PosterId = new Guid("99499984-8947-4b85-bea2-9cfd487c55d3"),
+                            RestaurantId = new Guid("e9921304-5657-40b2-9bb6-28ca03d3a45e"),
+                            ServiceRating = 8L,
+                            TimeSpent = 2.5f,
+                            UpdatedAt = new DateTime(2024, 10, 10, 16, 41, 2, 0, DateTimeKind.Unspecified)
+                        });
+                });
+
+            modelBuilder.Entity("DAL.Models.ReviewAggregateResult", b =>
+                {
+                    b.Property<Guid>("RestaurantId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<long>("EnvironmentRating")
+                        .HasColumnType("bigint");
+
+                    b.Property<long>("FoodRating")
+                        .HasColumnType("bigint");
+
+                    b.Property<long>("ServiceRating")
+                        .HasColumnType("bigint");
+
+                    b.HasKey("RestaurantId");
+
+                    b.ToTable("ReviewAggregateResults");
+
+                    b.HasData(
+                        new
+                        {
+                            RestaurantId = new Guid("104fdc28-a328-4f7b-85fe-81550cf1e247"),
+                            EnvironmentRating = 2L,
+                            FoodRating = 9L,
+                            ServiceRating = 5L
+                        },
+                        new
+                        {
+                            RestaurantId = new Guid("e9921304-5657-40b2-9bb6-28ca03d3a45e"),
+                            EnvironmentRating = 8L,
+                            FoodRating = 10L,
+                            ServiceRating = 8L
+                        });
+                });
+
+            modelBuilder.Entity("DAL.Models.ReviewComment", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<string>("Content")
+                        .IsRequired()
+                        .HasMaxLength(1800)
+                        .HasColumnType("nvarchar(1800)");
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime?>("DeletedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<Guid?>("ParentCommentId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<Guid>("PosterId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<Guid>("ReviewId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<DateTime>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("ParentCommentId");
+
+                    b.HasIndex("PosterId");
+
+                    b.HasIndex("ReviewId");
+
+                    b.ToTable("ReviewComments");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = new Guid("af16972e-d611-4c1c-8ce3-a93d667c1b9a"),
+                            Content = "Hello, I am the owner of this restaurant. I don't think it is right for you to rate us badly because we get a lot of customers.",
+                            CreatedAt = new DateTime(2024, 10, 5, 23, 14, 5, 0, DateTimeKind.Unspecified),
+                            PosterId = new Guid("32669bac-a1bd-4e9d-9580-ee4a7764cda3"),
+                            ReviewId = new Guid("32669bac-a1bd-4e9d-9580-ee4a7764cda3"),
+                            UpdatedAt = new DateTime(2024, 10, 5, 23, 14, 5, 0, DateTimeKind.Unspecified)
+                        },
+                        new
+                        {
+                            Id = new Guid("9ddbe84f-f2f4-4532-bca7-13152905c3b1"),
+                            Content = "OK.",
+                            CreatedAt = new DateTime(2024, 10, 6, 23, 18, 1, 0, DateTimeKind.Unspecified),
+                            ParentCommentId = new Guid("af16972e-d611-4c1c-8ce3-a93d667c1b9a"),
+                            PosterId = new Guid("afde48a8-99e3-423e-a48d-9e4e6a3d823a"),
+                            ReviewId = new Guid("32669bac-a1bd-4e9d-9580-ee4a7764cda3"),
+                            UpdatedAt = new DateTime(2024, 10, 6, 23, 18, 1, 0, DateTimeKind.Unspecified)
+                        },
+                        new
+                        {
+                            Id = new Guid("b8046e83-94c9-4b48-8035-28a5873e1526"),
+                            Content = "Oh my god! Are you still in there?!",
+                            CreatedAt = new DateTime(2024, 10, 6, 10, 5, 6, 0, DateTimeKind.Unspecified),
+                            PosterId = new Guid("32669bac-a1bd-4e9d-9580-ee4a7764cda3"),
+                            ReviewId = new Guid("e8f210bd-5666-40c7-bc61-4d8ef17c5191"),
+                            UpdatedAt = new DateTime(2024, 10, 6, 10, 5, 6, 0, DateTimeKind.Unspecified)
+                        },
+                        new
+                        {
+                            Id = new Guid("652ba3f0-ad48-4e71-a791-f16b5707003d"),
+                            Content = "No, no, it's all good now. Turns out I just locked it.",
+                            CreatedAt = new DateTime(2024, 10, 6, 11, 3, 0, 0, DateTimeKind.Unspecified),
+                            ParentCommentId = new Guid("b8046e83-94c9-4b48-8035-28a5873e1526"),
+                            PosterId = new Guid("99499984-8947-4b85-bea2-9cfd487c55d3"),
+                            ReviewId = new Guid("e8f210bd-5666-40c7-bc61-4d8ef17c5191"),
+                            UpdatedAt = new DateTime(2024, 10, 6, 11, 3, 0, 0, DateTimeKind.Unspecified)
+                        });
+                });
+
+            modelBuilder.Entity("DAL.Models.User", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<string>("AvatarUrl")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<DateTime>("CreatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime?>("DeletedAt")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("Email")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(450)");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("nvarchar(255)");
+
+                    b.Property<DateTime>("UpdatedAt")
+                        .HasColumnType("datetime2");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Email")
+                        .IsUnique();
+
+                    b.ToTable("Users");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = new Guid("afde48a8-99e3-423e-a48d-9e4e6a3d823a"),
+                            CreatedAt = new DateTime(2024, 10, 1, 8, 20, 5, 0, DateTimeKind.Unspecified),
+                            Email = "Vit23@gmail.com",
+                            Name = "Vit23",
+                            UpdatedAt = new DateTime(2024, 10, 1, 8, 20, 5, 0, DateTimeKind.Unspecified)
+                        },
+                        new
+                        {
+                            Id = new Guid("32669bac-a1bd-4e9d-9580-ee4a7764cda3"),
+                            CreatedAt = new DateTime(2024, 10, 1, 4, 20, 0, 0, DateTimeKind.Unspecified),
+                            Email = "Erikuss.Cool@gmail.com",
+                            Name = "Erik512",
+                            UpdatedAt = new DateTime(2024, 10, 1, 4, 20, 0, 0, DateTimeKind.Unspecified)
+                        },
+                        new
+                        {
+                            Id = new Guid("99499984-8947-4b85-bea2-9cfd487c55d3"),
+                            CreatedAt = new DateTime(2024, 10, 5, 14, 23, 21, 0, DateTimeKind.Unspecified),
+                            Email = "Jaqub@azet.sk",
+                            Name = "Jakub23423",
+                            UpdatedAt = new DateTime(2024, 10, 5, 14, 23, 21, 0, DateTimeKind.Unspecified)
+                        });
+                });
+
+            modelBuilder.Entity("RestaurantUser", b =>
+                {
+                    b.Property<Guid>("MaintainedRestaurantsId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<Guid>("RestaurantMaintainersId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.HasKey("MaintainedRestaurantsId", "RestaurantMaintainersId");
+
+                    b.HasIndex("RestaurantMaintainersId");
+
+                    b.ToTable("RestaurantUser");
+
+                    b.HasData(
+                        new
+                        {
+                            MaintainedRestaurantsId = new Guid("104fdc28-a328-4f7b-85fe-81550cf1e247"),
+                            RestaurantMaintainersId = new Guid("afde48a8-99e3-423e-a48d-9e4e6a3d823a")
+                        },
+                        new
+                        {
+                            MaintainedRestaurantsId = new Guid("e9921304-5657-40b2-9bb6-28ca03d3a45e"),
+                            RestaurantMaintainersId = new Guid("32669bac-a1bd-4e9d-9580-ee4a7764cda3")
+                        });
+                });
+
+            modelBuilder.Entity("DAL.Models.Event", b =>
+                {
+                    b.HasOne("DAL.Models.Restaurant", "Restaurant")
+                        .WithMany("Events")
+                        .HasForeignKey("RestaurantId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.Navigation("Restaurant");
+                });
+
+            modelBuilder.Entity("DAL.Models.EventComment", b =>
+                {
+                    b.HasOne("DAL.Models.Event", "Event")
+                        .WithMany("Comments")
+                        .HasForeignKey("EventId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.HasOne("DAL.Models.EventComment", "ParentComment")
+                        .WithMany("ChildComments")
+                        .HasForeignKey("ParentCommentId")
+                        .OnDelete(DeleteBehavior.Restrict);
+
+                    b.HasOne("DAL.Models.User", "Poster")
+                        .WithMany()
+                        .HasForeignKey("PosterId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.Navigation("Event");
+
+                    b.Navigation("ParentComment");
+
+                    b.Navigation("Poster");
+                });
+
+            modelBuilder.Entity("DAL.Models.EventParticipant", b =>
+                {
+                    b.HasOne("DAL.Models.Event", "Event")
+                        .WithMany("Participants")
+                        .HasForeignKey("EventId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.HasOne("DAL.Models.User", "User")
+                        .WithMany()
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.Navigation("Event");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("DAL.Models.Location", b =>
+                {
+                    b.HasOne("DAL.Models.Restaurant", "Restaurant")
+                        .WithOne("Location")
+                        .HasForeignKey("DAL.Models.Location", "RestaurantId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.Navigation("Restaurant");
+                });
+
+            modelBuilder.Entity("DAL.Models.Review", b =>
+                {
+                    b.HasOne("DAL.Models.User", "Poster")
+                        .WithMany()
+                        .HasForeignKey("PosterId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.HasOne("DAL.Models.Restaurant", "Restaurant")
+                        .WithMany("Reviews")
+                        .HasForeignKey("RestaurantId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.Navigation("Poster");
+
+                    b.Navigation("Restaurant");
+                });
+
+            modelBuilder.Entity("DAL.Models.ReviewAggregateResult", b =>
+                {
+                    b.HasOne("DAL.Models.Restaurant", "Restaurant")
+                        .WithOne("ReviewAggregate")
+                        .HasForeignKey("DAL.Models.ReviewAggregateResult", "RestaurantId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.Navigation("Restaurant");
+                });
+
+            modelBuilder.Entity("DAL.Models.ReviewComment", b =>
+                {
+                    b.HasOne("DAL.Models.ReviewComment", "ParentComment")
+                        .WithMany("ChildComments")
+                        .HasForeignKey("ParentCommentId")
+                        .OnDelete(DeleteBehavior.Restrict);
+
+                    b.HasOne("DAL.Models.User", "Poster")
+                        .WithMany()
+                        .HasForeignKey("PosterId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.HasOne("DAL.Models.Review", "Review")
+                        .WithMany("Comments")
+                        .HasForeignKey("ReviewId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.Navigation("ParentComment");
+
+                    b.Navigation("Poster");
+
+                    b.Navigation("Review");
+                });
+
+            modelBuilder.Entity("RestaurantUser", b =>
+                {
+                    b.HasOne("DAL.Models.Restaurant", null)
+                        .WithMany()
+                        .HasForeignKey("MaintainedRestaurantsId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.HasOne("DAL.Models.User", null)
+                        .WithMany()
+                        .HasForeignKey("RestaurantMaintainersId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("DAL.Models.Event", b =>
+                {
+                    b.Navigation("Comments");
+
+                    b.Navigation("Participants");
+                });
+
+            modelBuilder.Entity("DAL.Models.EventComment", b =>
+                {
+                    b.Navigation("ChildComments");
+                });
+
+            modelBuilder.Entity("DAL.Models.Restaurant", b =>
+                {
+                    b.Navigation("Events");
+
+                    b.Navigation("Location");
+
+                    b.Navigation("ReviewAggregate");
+
+                    b.Navigation("Reviews");
+                });
+
+            modelBuilder.Entity("DAL.Models.Review", b =>
+                {
+                    b.Navigation("Comments");
+                });
+
+            modelBuilder.Entity("DAL.Models.ReviewComment", b =>
+                {
+                    b.Navigation("ChildComments");
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/DAL/Migrations/20241115150548_Init.cs b/DAL/Migrations/20241115150548_Init.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d5039096ba46fa5e0b0056f637326430a999a929
--- /dev/null
+++ b/DAL/Migrations/20241115150548_Init.cs
@@ -0,0 +1,22 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace DAL.Migrations
+{
+    /// <inheritdoc />
+    public partial class Init : Migration
+    {
+        /// <inheritdoc />
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+
+        }
+
+        /// <inheritdoc />
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+
+        }
+    }
+}
diff --git a/DAL/Migrations/RestaurantDBContextModelSnapshot.cs b/DAL/Migrations/RestaurantDBContextModelSnapshot.cs
index fd7ff15aff56b9b086161e34a7ae85e4efb0a594..33ec8147391b8ecb620364cd7ace3112e66e3180 100644
--- a/DAL/Migrations/RestaurantDBContextModelSnapshot.cs
+++ b/DAL/Migrations/RestaurantDBContextModelSnapshot.cs
@@ -17,7 +17,7 @@ namespace DAL.Migrations
         {
 #pragma warning disable 612, 618
             modelBuilder
-                .HasAnnotation("ProductVersion", "8.0.10")
+                .HasAnnotation("ProductVersion", "8.0.8")
                 .HasAnnotation("Relational:MaxIdentifierLength", 128);
 
             SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
@@ -789,11 +789,9 @@ namespace DAL.Migrations
                 {
                     b.Navigation("Events");
 
-                    b.Navigation("Location")
-                        .IsRequired();
+                    b.Navigation("Location");
 
-                    b.Navigation("ReviewAggregate")
-                        .IsRequired();
+                    b.Navigation("ReviewAggregate");
 
                     b.Navigation("Reviews");
                 });
diff --git a/Dockerfile_API b/Dockerfile_API
new file mode 100644
index 0000000000000000000000000000000000000000..a1dc5928c83710b803b14b5f81e9a054145f0fa3
--- /dev/null
+++ b/Dockerfile_API
@@ -0,0 +1,23 @@
+# https://hub.docker.com/_/microsoft-dotnet
+FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
+WORKDIR /app
+EXPOSE 5171
+
+FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+WORKDIR /src
+COPY ["pv179-project.sln", "pv179-project.sln"]
+COPY ["DAL/DAL.csproj", "DAL/"]
+COPY ["BusinessLayer/BusinessLayer.csproj", "BusinessLayer/"]
+COPY ["TestUtilities/TestUtilities.csproj", "TestUtilities/"]
+COPY ["BusinessLayer.Tests/BusinessLayer.Tests.csproj", "BusinessLayer.Tests/"]
+COPY ["Api/Api.csproj", "Api/"]
+COPY ["MVC/MVC.csproj", "MVC/"]
+RUN dotnet restore "pv179-project.sln"
+
+COPY . .
+RUN dotnet publish "pv179-project.sln" -c Release -o /app/publish
+
+FROM base AS final
+WORKDIR /app
+COPY --from=build /app/publish .
+ENTRYPOINT ["dotnet", "Api.dll"]
\ No newline at end of file
diff --git a/Dockerfile_MVC b/Dockerfile_MVC
new file mode 100644
index 0000000000000000000000000000000000000000..91783b20c3adaf5c93485ae10743630e9612d577
--- /dev/null
+++ b/Dockerfile_MVC
@@ -0,0 +1,24 @@
+# https://hub.docker.com/_/microsoft-dotnet
+FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
+WORKDIR /app
+EXPOSE 5171
+
+FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+WORKDIR /src
+COPY ["pv179-project.sln", "pv179-project.sln"]
+COPY ["DAL/DAL.csproj", "DAL/"]
+COPY ["BusinessLayer/BusinessLayer.csproj", "BusinessLayer/"]
+COPY ["TestUtilities/TestUtilities.csproj", "TestUtilities/"]
+COPY ["BusinessLayer.Tests/BusinessLayer.Tests.csproj", "BusinessLayer.Tests/"]
+COPY ["Api/Api.csproj", "Api/"]
+COPY ["MVC/MVC.csproj", "MVC/"]
+RUN dotnet restore "pv179-project.sln"
+
+COPY . .
+WORKDIR "/src"
+RUN dotnet publish "pv179-project.sln" -c Release -o /app/publish
+
+FROM base AS final
+WORKDIR /app
+COPY --from=build /app/publish .
+ENTRYPOINT ["dotnet", "MVC.dll"]
\ No newline at end of file
diff --git a/MVC/MVC.csproj b/MVC/MVC.csproj
index 2eebefecf2b555249bc5be0d910baa5e79c96ad2..94482b42a6add2039f1d11ccf27605d89224d038 100644
--- a/MVC/MVC.csproj
+++ b/MVC/MVC.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
+<Project Sdk="Microsoft.NET.Sdk.Web">
 
   <PropertyGroup>
     <TargetFramework>net8.0</TargetFramework>
@@ -7,8 +7,17 @@
 	<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
 
+  <ItemGroup>
+	  <PackageReference Include="Elastic.Extensions.Logging" Version="8.12.2" />
+	  <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8">
+		  <PrivateAssets>all</PrivateAssets>
+		  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+	  </PackageReference>
+  </ItemGroup>
+
   <ItemGroup>
     <ProjectReference Include="..\BusinessLayer\BusinessLayer.csproj" />
+    <ProjectReference Include="..\DAL\DAL.csproj" />
   </ItemGroup>
 
 </Project>
diff --git a/MVC/Program.cs b/MVC/Program.cs
index 932610dc45040dfc9c9dc52760373873bd22e148..abb8b1b4f098c0d28bab8410c52dda687447898b 100644
--- a/MVC/Program.cs
+++ b/MVC/Program.cs
@@ -1,3 +1,8 @@
+using DAL.Data;
+using Elastic.Extensions.Logging;
+using Elastic.Extensions.Logging.Options;
+using Microsoft.EntityFrameworkCore;
+
 namespace MVC
 {
     public class Program
@@ -7,6 +12,24 @@ namespace MVC
             var builder = WebApplication.CreateBuilder(args);
 
             // Add services to the container.
+            // I've fought the appsettings.json and the appsettings.json won.
+            var elasticConfig = builder.Configuration.GetSection("Logging").GetSection("Elasticsearch");
+            builder.Logging.AddElasticsearch(options =>
+            {
+                options.Index = new IndexNameOptions { Format = elasticConfig.GetValue<string>("Index")! };
+            });
+
+            bool inContainer = false;
+            _ = bool.TryParse(builder.Configuration["DOTNET_RUNNING_IN_CONTAINER"], out inContainer);
+
+            string? connString = inContainer
+                ? builder.Configuration.GetConnectionString("MSSQL_DOCKER")
+                : builder.Configuration.GetConnectionString("MSSQL");
+
+            builder.Services.AddDbContextFactory<RestaurantDBContext>(options =>
+                options.UseSqlServer(connString)
+            );
+
             builder.Services.AddControllersWithViews();
 
             var app = builder.Build();
diff --git a/MVC/appsettings-example.json b/MVC/appsettings-example.json
new file mode 100644
index 0000000000000000000000000000000000000000..c77cff9246a4149d02d6b2f87ebd40b3d1fcc610
--- /dev/null
+++ b/MVC/appsettings-example.json
@@ -0,0 +1,23 @@
+{
+    "ConnectionStrings": {
+      "MSSQL": "EXAMPLE_STRING",
+      "MSSQL_DOCKER": "EXAMPLE_STRING"
+    },
+  "Logging": {
+    "Elasticsearch": {
+      "NodeUris": [ "http://localhost:9200" ],
+      "Index": "biterate-logs-{0:yyyy.MM.dd}",
+      "ApplicationName": "BiteRate",
+      "MinimumLogEventLevel": "Information",
+      "ShipTo": {
+        "NodePoolType": "SingleNode",
+        "NodeUris": [ "http://elastic-search:9200" ]
+      }
+    },
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft.AspNetCore": "Warning"
+    }
+  },
+    "AllowedHosts": "*"
+  }
\ No newline at end of file
diff --git a/MVC/appsettings.json b/MVC/appsettings.json
new file mode 100644
index 0000000000000000000000000000000000000000..0411870ff40d4f9a45be50db27ed26aa363b3bfe
--- /dev/null
+++ b/MVC/appsettings.json
@@ -0,0 +1,23 @@
+{
+  "ConnectionStrings": {
+    "MSSQL": "Server=127.0.0.1,1433;Database=master;User Id=SA;Password=Example123;TrustServerCertificate=True;",
+    "MSSQL_DOCKER": "Server=db,1433;Database=master;User Id=SA;Password=Example123;TrustServerCertificate=True;"
+  },
+  "Logging": {
+    "Elasticsearch": {
+      "NodeUris": [ "http://localhost:9200" ],
+      "Index": "biterate-logs-{0:yyyy.MM.dd}",
+      "ApplicationName": "BiteRate",
+      "MinimumLogEventLevel": "Information",
+      "ShipTo": {
+        "NodePoolType": "SingleNode",
+        "NodeUris": [ "http://elastic-search:9200" ]
+      }
+    },
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft.AspNetCore": "Warning"
+    }
+  },
+  "AllowedHosts": "*"
+  }
\ No newline at end of file
diff --git a/README.md b/README.md
index 09080dacad628e804e39b148e0d79de111cd5ef2..3282bddb2d6369ce76ae125e3950f21557e11120 100644
--- a/README.md
+++ b/README.md
@@ -41,43 +41,72 @@ Additionally, the system offers functionality to create and manage events for sp
 
 ### Steps to Run:
 
-1. **Clone the Repository**:
+#### Clone the Repository
     
     ```bash
     git clone <https://gitlab.fi.muni.cz/xvavrek/pv179-project.git>
     
     ```
 
-2. **Set Up the Database and other containers**:
-    Create new SQL database and update the connection string in <code>Api/appsetting.json</code> to point to your SQL Server instance.
+#### Full-Docker Run
+For your convenience, we have configured BiteRate to fully run in multiple docker containers, requiring only minimal work for the application to run.
 
-    For your convenience, you may use the docker compose file in the Orchestration directory. 
-    
+All you need to do is create a ``.env`` file in the same folder as ``.env.example`` (note: for simple testing, it is okay to copy the contents of ``.env.example`` into ``.env`` as is.).
+
+A functional ``appsettings.json`` is already in both runnable projects - API and MVC. This ``appsettings.json`` contains some default settings for relevant services and DEVELOPMENT-ONLY example connectionstrings that are preconfigured to work with the default configuration of our docker-compose. In a release mode, these settings should be changed, more secure passwords should be chosen, https and certificates should be used, and the ``appsettings.json`` file should not be posted publicly with real secret information in it.
+
+Once you have done so, you may use the ``docker compose --profile full up`` command in the same directory as the one that contains the ``compose.yml`` file (by default, this is the root of the project).
+
+Once the database container is up and running, in the Package Manager Console of Visual Studio, set the default project as DAL and run the ``Update-Database`` Command to update the database with seeded data.
+
+You should now be fully set! You can use your browser to see the application endpoints.
+
+Use <code>[http://localhost:5171/](http://localhost:5171/)</code> for the API project. Because of the authentication mechanism, though, it will be hard for you to access any of the API endpoints. Instead, we recommend using a tool such as [Insomnium](https://github.com/ArchGPT/insomnium), adding a header called Authorization with the value ``token`` and testing API calls that way.
+
+Use <code>[http://localhost:5173/](http://localhost:5173/)</code> for the MVC project.
+
+
+#### Partial Docker Run
+
+1. **Set Up the Database and other containers**: 
     First, you should copy the ``.env.example`` file and rename it to ``.env``. This will use example values to setup the environment used by docker compose, which affect the setup of the containers.
 
-    Once you have created a ``.env`` file, using the command `docker compose up` while in the directory, you will instantiate an MSSQL database container, Elasticsearch container and Kibana container. 
+    Once you have created a ``.env`` file, you may start the containers. Using the command `docker compose --profile db-log up` while in the directory, you will instantiate an MSSQL database container, Elasticsearch container and Kibana container.  
 
-    To connect to the database using our application, you must create a `appsettings.json` in the root of the `Api` project. You may use `appsettings-example.json` as a template. Within the `appsettings.json`, you must set the `MSSQL` field to a working connection string.
+    A functional ``appsettings.json`` is already in both runnable projects - API and MVC. This ``appsettings.json`` contains some default settings for relevant services and DEVELOPMENT-ONLY example connectionstrings that are preconfigured to work with the default configuration of our docker-compose. In a release mode, these settings should be changed, more secure passwords should be chosen, https and certificates should be used, and the ``appsettings.json`` file should not be posted publicly with real secret information in it.
 
-    An **example** of a **development-only** connection string can be this: ``"Server=127.0.0.1,1433;Database=master;User Id=SA;Password=Example123;TrustServerCertificate=True;"``. Please keep in mind that a connection string like this should never be used to access a production server - the password is weak (and publically posted in a README), and the TrustServerCertificate setting is not safe.
+    Once your database container is running, in the Package Manager Console of Visual Studio, set the default project as DAL and run the ``Update-Database`` Command to update the database.
 
-    Once your connection string is setup and your database container is running, in the Package Manager Console, set the default project as DAL and run the ``Update-Database`` Command to update the database.
+2. **Run the Application**:
+    **Api**
+    Run the <code>dotnet run --project Api</code> command from the project root directory or use the Visual Studio GUI to run the project with the startup project being API, configured to HTTP.
 
-3. **Run the Application**:
-    Run the <code>dotnet run --project Api</code> command from the project root directory or use the Visual Studio GUI to run the project with HTTP.
+    **MVC**
+    Run the <code>dotnet run --project MVC</code> command from the project root directory or use the Visual Studio GUI to run the project with the startup project being MVC configured to HTTP.
 
-4. **Access the Application**
+3. **Access the Application**
+    **API**
     Once the application is running, you can access it in your browser by navigating to <code>[http://localhost:5171/swagger](http://localhost:5171/swagger)</code>
 
+    **MVC**
+    Once the application is running, you can access it in your browser by navigating to <code>[http://localhost:5266](http://localhost:5266)</code>
+
 ### Logging
-Using the example appsettings.json, logging will be performed into an Elasticsearch container. If you have used the default settings, you may use this link <code>[http://localhost:9200/_cat/indices](http://localhost:9200/_cat/indices)</code> to find the index of the application logs, which should start with the name of application - **biterate**. Once you have found the name of the index (biterate-logs-{year}.{month}.{day}), you can use <code>htpp://localhost:9200/index_name/_search?pretty=true</code> to see the logs in your browser.
+Logging will be performed into an Elasticsearch container. If you have used the default settings, you may use <code>[http://localhost:9200/_cat/indices](http://localhost:9200/_cat/indices)</code> to find the index of the application logs, which should start with the name of application - **biterate**. Once you have found the name of the index (biterate-logs-{year}.{month}.{day}), you can use <code>htpp://localhost:9200/index_name/_search?pretty=true</code> where ``index_name`` is replaced with the name of the biterate-logs index, to see the logs in your browser.
 
-The composed containers for the application should also contain a kibana container. Kibana is a tool used for visualization of data from elasticsearch. To access kibana, you must go to localhost:5601.
+The composed containers for the application should also contain a kibana container. Kibana is a tool used for visualization of data from elasticsearch. To access kibana, you must go <code>[http://localhost:5601](http://localhost:5601)</code>.
 
 For convenience reasons, the current setup is not protected and should not ask for any passwords - this is not how it should be done in production, where proper security should be employed. To do so, you may try it at your own risk by modifying the .env file and setting ``ENABLE_SECURITY`` to ``true``.
 
 Once you are in Kibana, open the hamburger menu to the left, and select Analytics -> Discover. You will be prompted to create a data view and input an index pattern. To the left, you should already have recommendations for indices available, but you can input ``biterate-logs*`` to match the index. After that, you can save the data view, and the application should take you to a more structured view of the logs.
 
+### Image Management via Filesystem
+When setting up your first images, it is recommended to use the API project to do so with a tool such as the aforementioned Insomnium. Once the application has its first image uploaded, you will be able to access this image in by going to the root folder of the application on your disc and using this path: ``img/EntityName/EntityID/...``.
+
+EntityName refers to the type of the entity, such as Restaurant, User, Event and Review. (In reality, this is a redundant step when using GUID, but it helps human navigation a little!)
+EntityID refers to the GUID of a given entity, which uniquely identifies an entity and ensures that all images refer to the correct entity.
+Within the folder named after the EntityID, there are two types of images. The first is a single image known as the Avatar. The application considers there to be only one avatar. The second type is a Gallery image. There can be multiple gallery images.
+
 ## Application Structure
 
 ### The Api Project
@@ -85,7 +114,7 @@ This layer encompasses user interaction with the current iteration of the applic
 simple CRUD (Create, Retrieve, Update, Delete) operations and an example of simple authentication. 
 Much of the business logic, such as restaurant ranking, is left to the business logic layer which is not yet implemented in this iteration.
 - **Program.cs**: The entry point for the application, which sets up the ASP.NET Core environment.
-- **appsettings.json**: Configuration file used to set environment-specific settings, like connection strings and app configurations. The example of how this file should be set-up can be found in `appsettings-example.json`.
+- **appsettings.json**: Configuration file used to set environment-specific settings, like connection strings and app configurations.
 - **Controllers**: Contains the API controllers that handle HTTP requests. Controllers are named after the entity they represent.
 - **Middleware**: Contains custom middleware - Exception handling, request logging, authentication and others. The logging is currently setup to write to the console and to an elasticsearch database.
 - **Models**: Contains model classes used in the API layer of the application, each subfolder contains relevant entity models.
diff --git a/Orchestration/compose.yml b/compose.yml
similarity index 62%
rename from Orchestration/compose.yml
rename to compose.yml
index ba7fcc6ba54b277eb8db3ba63ee0ffb453ecfd0e..408de621cf368ecd08c9ef2a0ae972d779e28faa 100644
--- a/Orchestration/compose.yml
+++ b/compose.yml
@@ -8,6 +8,7 @@ services:
       MSSQL_SA_PASSWORD: "Example123" #This is just an example - CHANGE THIS!!!
     ports: 
     - "1433:1433"
+
   log-db:
     container_name: elastic-search
     image: docker.elastic.co/elasticsearch/elasticsearch:8.15.3
@@ -17,10 +18,8 @@ services:
       xpack.security.enabled: $ENABLE_SECURITY # To allow http connection during development - remove after!
       elastic_password: $ELASTIC_PASSWORD
     ports:
-    - "9200:9200"
-    - "9300:9300"
-    networks:
-    - elastic
+      - "9200:9200"
+      - "9300:9300"
 
   kibana:
     container_name: kibana
@@ -34,12 +33,35 @@ services:
       XPACK_SECURITY_ENABLED: $ENABLE_SECURITY
       ELASTICSEARCH_USER: $ELASTIC_USER
       ELASTICSEARCH_PASSWORD: $ELASTIC_PASSWORD
-    networks:
-      - elastic
-
-networks:
-  elastic:
-    driver: bridge
-    
-volumes:
-  elasticsearch-data:
\ No newline at end of file
+  
+  api:
+    container_name: biterate-api
+    environment:
+      - ASPNETCORE_URLS=http://+:5171
+    build: 
+      dockerfile: Dockerfile_API
+    ports:
+      - "5171:5171"
+    volumes:
+      - ./img:/img
+    depends_on: 
+      - db
+      - log-db
+    profiles:
+      - full
+  
+  mvc:
+    container_name: biterate-mvc
+    environment:
+      - ASPNETCORE_URLS=http://+:5173
+    build:
+      dockerfile: Dockerfile_MVC
+    ports:
+      - "5173:5173"
+    volumes:
+      - ./img:/img
+    depends_on: 
+      - db
+      - log-db
+    profiles:
+      - full
\ No newline at end of file
diff --git a/img/.gitkeep b/img/.gitkeep
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391