Cheat Sheet: A Full-Stack Project in Docker
By: Anna Melashkina
Tags: Postgresql, Angular, Containerization, Docker, Aspnet

Cheat Sheet: A Full-Stack Project in Docker

How to dockerize your PostgreSQL + ASP.Net server + Angular client

Introduction

Docker came to us from the Linux world, that’s why sometimes developers, that are used to work with Windows platforms (like me) have some difficulties configuring Docker with their code. I wish I had such a cheat sheet tutorial when I just started working with docker. That’s why I want to share a fast tutorial on how to configure ASP.NET as a server with a connection to the PostgreSQL database and Angular as a client today.

Pre-Requirements

You will need docker for windows, PostgreSQL 12, Angular CLI, Visual Studio 2019, and VS Code.

Step 1: Server

We are going to prepare some very basic server, that gets data from the database and saves it to the database.

1. Create a new ASP.NET Core Web Application, use the Empty template. Choose an appropriate name for your project, but keep in mind that you will need to reuse the exact name later on, I will leave the name “WebApplication1".

2. Create folder Models and add Model.cs file:

3. Create folder Database and add there 2 files: Database.cs and IDatabase.cs (you need to install next NuGet packages: Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.Tools, Npgsql.EntityFrameworkCore.PostgreSQL):

Now, as we created a model, we have to create a migration. For this run

Add-Migration InitialCreate

in Visual Studio console. This will create Migrations folder with one migration. You can read more about migration here.

4. Configure dependency injection. You’ll need to add IDatabase to Startup.cs. Also add CORS, that allow all origins at least for testing purposes. Your Startup.cs will look like this:

5. Create a controller. For this add folder Controllers and file ValuesController.cs:

6. Change appsettings.Development.json file, add next variables:

DB_USER — your postgres user;

DB_PASSWORD — password for your postgres user;

DB_PORT — postgres port, most likely 5432;

DB_HOST — set to localhost;

My appsettings.Development.json looks like this:

Step 1: Summary

In this step, we have set up a very basic server, that takes values from the database and saves them to the database. If you want to test your server, then run Visual Studio. It will open the server, navigate to /values URL and you will see the empty array. If you want to add some value to the database, you can use Postman to generate post requests.

Step 2: Client

As for now, we have a server, let’s create a client for it.

Run ng new angular-client next to WebApplication1 folder. This will generate an angular app. angular-client and WebApplication1 should be at the same folder level! Run npm install and ng s. Let’s get data from the server. Open environment.ts and add baseUri (url where your server is running), my looks like this:

We will return to evironment.prod.ts later in this tutorial.

3. Add service, that will get/send data from/to server. Add data-provider.service.ts and model.ts to app folder:

Don’t forget to add HttpClientModule in the imports section of app.module.ts.

4. Let’s use data service and show something to the user. For this change app.component.ts and app.component.html:

Now when the user clicks on the button “Get data!” request is done to the server and the result is shown on the page; the user can also click “Send data!” this will send new data to the server.

Step 2: Summary

In this step, we have created a very basic angular app, that makes a request to the server and receives some values and also sends post requests and creates new value.

Step 3: Put it all in docker!

The final step is to put all components in docker.

As we need angular running on some server, we will use Nginx for this. Create nginx.conf in angular-client folder:

Nginx will serve requests and redirect them to index.html, unless it’s a request to “my_server”. In this case, it will redirect it to http://my_server/. Do you remember enviroment.prod.ts that we left without changes? Now it’s time to add baseUri:

2. Next, we need to build our angular app. You can either automate it (check this great article on how to can automize angular build in docker) or do it by hands as I do. Run ng build — prod=true this will generate a dist folder with built application.

3. Add Dockerfile to the angular-client folder:

This docker file will create images based on nginx image + your built angular app. You can already build this image via

docker build .

but I would recommend continuing following this tutorial because in the end, we will build all images together. You can read more about building images here.

4. Add the Dockerfile and the .dockerignore file to your web project’s folder. Remember the name you chose for your web project when you created the solution? Make sure that the directory path correlates with your physical folder structure (my folder is WebApplication1):

Dockerfile in the server folder will create an image with asp.net server. You will need to ignore /bin and /obj folders, for this we added .dockerignore file.

5. The last and most important part is to compose docker images from previous steps. For this create docker-compose.yml file in the folder above angular-client and WebApplication1:

Let’s take a closer look at this file. It creates:

db container (postgres database), that is running on port 9091;

db_admin is a container for database debugging and uses pgAdmin 4, running on 9092 port;

my_server container, that is running asp.net server on port 9093. By the way, do you remember how we set up my_server in nginx configuration? A container can “see” each other if they are part of one docker-compose, that’s why when we make any request to the server, we redirect it to my_server container.

my_client container, that is running the angular client on port 9094.

In order to run it type docker-compose up in the console. You should see something like this in the end:

After docker-compose up

Navigate to http://localhost:9094, you should see your website is running there, try to get/create values from the server.

Bonus: You can try to log in to pg admin on http://localhost:9092/ using email “dev@medialesson.de” and password “postgres123” (check these values in docker-compose.yml). Try to check, that data, that you’ve created in the client side is saved to the database:

Values in the database-container

Summary:

In this article, I described how we can set up a full-stack project with the help of docker-compose. We are running 3 containers in the end: database, server, and client. Although docker is a very useful tool, sometimes it might be complicated to finish all steps, especially if you’re a developer from the Windows ecosystem and do not work much with docker. I hope, that this tutorial will help you to set up your environment much faster.

Full code of the example can be found here: https://github.com/aosyatnik/docker-fullstack-example