Docker Compose with .NET 8, PostgreSQL, and Redis (step by step)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
I'm going to show you how to set up Docker compos for your API completely from scratch we're going to configure a database and a redis cache as external services and connect everything together so you can build your API so here's what we're going to do I already have a products API in place which is an asp.net core web API inside of the product endpoints class I Define a few minimal API endpoints they're using EF core to connect to the database and Implement some basic crowd logic with have a post 10o to get 10 points and a put and delete 10o unfortunately our API will not work because we are still not connected to any database and this is where I'm going to use Docker to introduce a database Docker compos is a container orchestration tool and it's easy to set up from visual studio all you have to do is right click on your project click add and then look for container orchestrator support I'm going to pick Docker compose then I'm going to choose Linux for my target operating system this determines which operating system your containers are going to run and when I click okay it's going to scaffold a darker compos project for me now I can close this down because we're not interested in that but let's take a look at the other things that are important let's take a look at the docker file inside of the products API project this Docker file describes how to take the products API application and create a Docker image a Docker image is like a template that you can use to spin up a container in and if you can spin up one container instance you can spin up multiple container instances which gives your way to horizontally scale the application and let's just do a brief overview of what's Happening inside of the docker file so first of all we're taking an existing image which is the as.net core 8 image and is going to be used at the end to run our application once we build it for the build part we're going to need the net 8 SDK and basically this part here is building and Publishing the project and then in the end we're going going to start the project by calling net run you can also configure which ports you want to expose here so this is the HTTP port and then the https port and I'm going to update them to be 5,000 and 5000 And1 if I head over to the docker compost project which is now also the startup project there is one file inside that's going to determine which Services you're going to run when you start your Docker compose project and this lives inside of the docker compose yaml file there's already one service scaffold and inside which is our products API and you can see it's targeting the docker file inside of the products API project what you can do here is expose external ports so I'm going to map the ports 5,000 and 50001 inside of the docker container to the same port in our local system this is also configurable from the docker compose override file where you can see some environment variables are being set so I'm going to update the ports here as well and also the environment variables for the HTTP and https ports so now I've made sure that my application is running on these specific ports and using Docker compost it's really simple to introduce additional services to your system so let's go ahead and add a database first of all I need to give my new service a name so I'm going to call it products database then I need to Define which image I want to use to spin up my database and I'm going to look for poql now the name for this image is is postgress latest but if you're wondering which image you should use you can head over to hub. do.com and for example here is the page for our postgress image which is going to help us run the postgressql database and you can see a lot of useful information here mainly how to configure your Docker container I won't go over everything that's in here but it's definitely worth reading when you are first starting out I already know what to do so I'm going to continue with my setup if you want to you can also configure a custom container name for your database container and let's give it the name the same as the service so products database if I want to I can do the same in my products API so this will be the products API and the next thing I want to do is to set up some environment variables for my postgress database I'm going to set up the default database and give it the name of products I also want to configure the postgress user and password and I'm just going to give them the default values which are postgress to make it easier for me to connect to the database obviously in production you're going to set up a proper username and password the next thing I want to add is a volume and this is a way for you to connect the file systems inside of your container which is this file path here to the file system on your local machine and why are volumes important well if you don't have one and shut down your Docker container you're going to lose all of the data that's inside so we connect the database files for the poql database to our local file system to have it persisted between multiple runs of the docker container I also want to map the port for my postgress database so I'm going to look for the ports setting and I'm going to map the port 5432 which is the default port for postgress to the same port internally in the container so with our two Docker containers set up we also need to make sure that we connect our web API to the database running inside of a Docker container so if I head over to program CS I already have the EF course setup in place I'm just calling add database context and specifying the database context class and I'm connecting to post SQL by specifying a connection string with the name of database now this is going to live inside of my application settings and right now I don't have a connection string in place so I'm going to add it I have to specify the same name that I'm referencing inside of my code and what is interesting is the value of this connection string so let me explain why we use the specific values the host value in the connection string should point to the psql instance now because our database is running inside of a Docker container we have to use the internal service host which is products database and this will match the name of the service inside of the darker compos yaml file also notice that I specified the default database to be products which is why I'm using that value for the database key we made sure to map the default port for postgress and I'm also specifying the username and password to the ones that we Define in the environment variables so everything I configured inside of the docker compos yaml file is also here in the connection string so maybe you didn't notice up until this point but when we added the docker compose orchestration and scaffolded the docker compose project it was set up as the startup project for our solution this also changes the project that I'm using here and gives you a darker compose command to start debugging from visual studio if I go ahead and run this and open up my Docker desktop instance you're going to see our Docker compose starting up and you can see the two services our API and the database that we configured inside of the yaml file you can jump into any of the services and see the logs that are present inside so here are the logs for our API now take a look at this log here which is a SQL query to create a new database this is actually my EF core migrations running in the background and generating my database because it doesn't exist yet if you're wondering how I'm doing this well inside of my program CS if I'm running in a Dev development environment I'm calling the apply migrations method and this is a custom extension method that I created that is going to use the application Builder to create a service scope resolve the database context from this service scope because the database context is a scoped service and then it's just going to run any pending migrations on the database running inside of my Docker container so now that my database has the migrations applied I can show you that this API is working for example we can use the Swagger user interface to try to create a new product and if I send this request I'm going to get back a new product with the given identifier now I can go ahead and fetch all of the products and we're going to get back the single product that we have I can fetch the product by the ID and we're going to get back to product I can update the values of this product so for example I can set the price to something different and you can see that this completes and finally I can delete this product by calling the delete endpoint and if I try to fetch the product again we're going to get a 404 notfound response if all of this seems easy well that's because it is we really have amazing tooling for working with Docker inside of visual studio now what if I wanted to add a reddish cache to my system well I would head over to the docker compos yaml file and Define another service I'm going to add the configuration for my red cache I'm giving the service a name of products cache I'm using the latest reddis image you can also find information about this on on dockerhub and the default port for reddis is 6379 which we are going to use to connect to this redis instance so I'll need to do two things one is add the connection string for my Rus instance and I'm going to call it cache it's going to point to the name of my container when I run this using Docker compose which is going to be product cache and then it's using the default reddis Port I'm going to need a library to be able to connect to redis so let me open up the nouet browser and I'm going to look for for reddis and I want to install Microsoft extensions caching stack exchange reddis this is a library that has an implementation of the I distributed cache that can call redis so I'm going to install this and then I need to configure it with dependency injection so I'm going to add the code for that here we need to call add stack exchange redis cache and then we need to set the configuration value which is just the connection string to the reddis instance and we're going to grab this from our application settings using using the cache connection string so just to recap how easy this is we added redis in three simple steps we configured the redis image as a service inside of the docker compos yaml file we added the connection string to our redis cache instance and we configured the services with dependency injection and made sure to connect to the red instance running inside of a container so let's go ahead and actually use our cache I'm going to add caching in the endpoint where we fetch the product by the ID so let's say we get a product pack and we're we going to get it from our cache I'm going to inject a new service which will be the ID distributed cache and it's going to connect to our reddish instance at runtime and in my code I can say cach get async then I can specify my cach key which I'm going to generate using the product ID and I can also Define an asynchronous callback function to fetch my product from the database if it doesn't exist in the cache and I'm going to reuse the existing code for this I'll use the cancellation token that I get from the Callback and I can just return the product with ef core if we get a cache Miss otherwise it's going to be returned from the cache and I also need to pass in the cancellation token instance I definitely need to configure my expiration time so I already defined a default expiration time which is an instance of the distributed cache entry options and it sets the absolute expiration property to 20 seconds so I can use this value when I'm trying to get something from the cache and if it's not there it's going to be retrieved from the database and cash for 20 seconds so what you're seeing here is an implementation of the cach aside pattern where we are first trying to fetch the value from the cash and if it's not present we're only then going to talk to the database when we fetch the value from the database we're going to set it in the cache and then return the value that we just got on the next request is going to be retrieved directly from the cash one thing you have to think about whenever you're working with caching is ending up with stale cash values so we have to make sure to clear the cash value when we are running destructive operations and these are going going to be our updates so for example after I updated the product I can say cach remove key and I can specify my products key and then add the product ID to get the correct cach key value now I can do the same in my delete endpoint and remove the product from the cache when I've deleted it from the database and now I'm going to show you why clearing the cache is important by adding a breakpoint inside of the call back function and I'm going to spin up our services with Docker compose if I open up dock desktop you can see all of our services are running including the reddish cache and if I head over to my Swagger UI I'm going to start by creating a new product so let's give it a name of new so that we know that this is a new product and it has an ID of two now if I try to fetch this product on my get endpoint by specifying this ID we're going to hit the breakpoint in our callback function and fetch this value from the database so let's return it and you can see that we get the new product back as the response if I send this request again we won't hit the breakpoint because it's present in the cache however if I try to update this product and say for example that this is now a new updated product and execute this it's going to clear the cash value and now if I try to fetch this product again you can see that we land on our breakpoint because the cash value has been cleared and we're going to fetch the product from the database and get the most upto-date value if you don't want to set up doer compose an alternative is net Aspire which is a new techn technology stack for building Cloud native applications and you can learn how to use it by watching this video next make sure to smash the like And subscribe buttons and until next time stay awesome
Info
Channel: Milan Jovanović
Views: 37,818
Rating: undefined out of 5
Keywords: docker tutorial, docker compose tutorial, docker tutorial for beginners, docker compose, docker explained, docker .net, docker c# tutorial, docker c# application, c# docker project, c# docker microservices, rabbitmq c# docker, c# docker image, c# docker compose, docker asp.net core, docker asp.net core tutorial, docker asp.net core web api, docker asp.net core 7, docker compose asp.net core, docker for asp.net core developers, docker asp.net core 8, docker compose setup
Id: WQFx2m5Ub9M
Channel Id: undefined
Length: 13min 40sec (820 seconds)
Published: Tue Jan 23 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.