DEV Community

Cover image for 🧱 Lecture 10 : Dockerizing the Full Stack Application
Farrukh Rehman
Farrukh Rehman

Posted on

🧱 Lecture 10 : Dockerizing the Full Stack Application

Series: From Code to Cloud: Building a Production-Ready .NET Application
By: Farrukh Rehman - Senior .NET Full Stack Developer / Team Lead
LinkedIn: https://linkedin.com/in/farrukh-rehman
GitHub: https://github.com/farrukh1212cs

Source Code Backend : https://github.com/farrukh1212cs/ECommerce-Backend.git

Source Code Frontend : https://github.com/farrukh1212cs/ECommerce-Frontend.git

🎯 Introduction
In modern software engineering, containerization is a fundamental skill for building portable, scalable, and DevOps-friendly applications. By packaging both the .NET 8 backend API and the Angular Admin Panel inside Docker containers, we ensure that the entire application stack can run consistently across any environment—local, QA, staging, or production—without dependency conflicts or manual setup.

This lesson focuses exclusively on:

  • Creating a Dockerfile for the .NET 8 E-Commerce API
  • Creating a Dockerfile for the Angular Admin App (using the Mantis free template)
  • Running both applications in isolated Docker containers
  • Configuring docker-compose to orchestrate both services together

After completing this lesson, you will be able to launch the entire backend + admin panel with one command:

docker-compose up --build -d

This is an essential step toward production readiness and CI/CD automation in future lessons.

Section 1 — Dockerizing the .NET 8 Backend API

FIRST OF ALL WE NEED TO UPDATE PROGRAM FILE FOR AUTO RUN MIGRATIONS

We will create a multi-stage Dockerfile that:

  1. Restores dependencies
  2. Publishes the project
  3. Runs the optimized build inside ASP.NET Core runtime

Step 1.1 — Create Dockerfile in your API project root

Location:
Path : "/ECommerce.API/Dockerfile"
Right-click the API project, select Add, and then choose Container Support to enable containerization for the service.

Lets Configure Docker Containers to connect each other.

First Create Docker Network
docker network create ecommerce-net

Lets Connect Postgres to this Network (ecommerce-net)
docker network connect ecommerce-net postgres

Now time to connect RabbitMQ to network (ecommerce-net)
docker network connect ecommerce-net rabbitmq

Its time to connect Redis with the network (ecommerce-net)

docker network connect ecommerce-net ecommerce-redis

Last setp lets verify Network

docker inspect ecommerce-net

All Containers are Connected with our network.now its time to work on api side.

  1. Copy all configuration values from appsettings.json into appsettings.Development.json

  2. Update appsettings.Development.json Replace localhost from ConnectionStrings:PostgreSQL to ContainerName (postgres)

  3. Update Redis localhost to ContainerName (ecommerce-redis)

  4. Update RabbitMQ localhost to ContainerName (rabbitmq)

Lets try to Build Image (make sure docker is running)

docker build -t ecommerce-api -f ECommerce.API/Dockerfile .

docker images

Run the API Container

docker run -p 5000:8080 --name ecommerce-api-container --network ecommerce-net -e ASPNETCORE_ENVIRONMENT=Development ecommerce-api

Its time to Test Swagger our container is accessable on port 5000

Lets start working on angular containerization
we need to create four files
Dockerfile,.dockerignore,nginx.conf,environment.prod.ts
Path: "ecommerce-backoffice\Dockerfile"

FROM node:20.19-alpine AS build

WORKDIR /app

# Install dependencies (use npm ci for reproducible installs)
COPY package.json package-lock.json* ./
RUN npm ci --silent || npm install --silent

# Copy source and build the Angular app
COPY . .
RUN npm run build -- --configuration=production

FROM nginx:stable-alpine

# Remove default nginx static assets
RUN rm -rf /usr/share/nginx/html/*

# Copy built Angular app from the builder stage
COPY --from=build /app/dist/sakai-ng/browser  /usr/share/nginx/html

# Expose port 80
EXPOSE 80

# Start nginx in the foreground
CMD ["nginx", "-g", "daemon off;"]
Enter fullscreen mode Exit fullscreen mode

Path: "ecommerce-backoffice.dockerignore"
.dockerignore

node_modules
dist
.git
.gitignore
Dockerfile
docker-compose*.yml
docker-compose*.yaml
README.md
*.log
.vscode
.idea
coverage
tmp
out-tsc
# keep source files included so the build can run
Enter fullscreen mode Exit fullscreen mode

Path: "ecommerce-backoffice\nginx.conf"
nginx.conf

server {
    listen 80;
    server_name localhost;

    # Serve the Angular app
    location / {
        root /usr/share/nginx/html;
        try_files $uri $uri/ /index.html;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }

    # Proxy API requests to your backend
    location /api/ {
        proxy_pass https://host.docker.internal:7104;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;

        # Disable SSL verification (for self-signed certs in local dev)
        proxy_ssl_verify off;
        proxy_ssl_session_reuse on;
    }
}
Enter fullscreen mode Exit fullscreen mode

Path: "ecommerce-backoffice\src\environments\environment.prod.ts"
environment.prod.ts

export const environment = {
  production: true,
  // API requests are proxied through nginx to the backend
    baseUrl: 'http://localhost:7104/api'
};
Enter fullscreen mode Exit fullscreen mode

Its time to build Angular Image

docker build -t sakai-ng:latest .

docker images
docker run --rm -p 80:80 sakai-ng:latest
Enter fullscreen mode Exit fullscreen mode

Final Step Lets Write docker-compose.yml

networks:
  ecommerce-net:
    external: true

services:
  postgres:
    image: postgres:15
    container_name: postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: ECommerceDb
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: Admin123!
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - ecommerce-net

  rabbitmq:
    image: rabbitmq:3-management
    container_name: rabbitmq
    restart: unless-stopped
    ports:
      - "5672:5672"
      - "15672:15672"
    networks:
      - ecommerce-net

  redis:
    image: redis:7
    container_name: ecommerce-redis
    restart: unless-stopped
    ports:
      - "6379:6379"
    networks:
      - ecommerce-net

  ecommerce-api:
    image: ecommerce-api
    container_name: ecommerce-api-container
    restart: unless-stopped
    ports:
      - "7104:8080"
    environment:
      ASPNETCORE_ENVIRONMENT: Development
      ConnectionStrings__PostgreSQL: Host=postgres;Port=5432;Database=ECommerceDb;Username=postgres;Password=Admin123!
      Redis__Host: redis
      RabbitMQ__Host: rabbitmq
    depends_on:
      - postgres
      - rabbitmq
      - redis
    networks:
      - ecommerce-net

  sakai-ng:
    image: sakai-ng:latest
    container_name: sakai-ng
    restart: unless-stopped
    ports:
      - "80:80"
    depends_on:
      - ecommerce-api
    networks:
      - ecommerce-net

volumes:
  postgres_data:
Enter fullscreen mode Exit fullscreen mode

Lets Test from UI

Next Lecture Preview
Lecture 11 : Continuous Integration with Jenkins

Creating CI/CD pipelines in Jenkins for automated build, test, and deployment workflows.

Top comments (0)