Docker Images and Containers Simplified

Images & Containers

Images

Images are one of the two core building blocks Docker is all about (the other one is Containers).

  • Images are blueprints / templates for containers.
  • They are read-only and contain:
    • The application
    • Operating system
    • Runtimes
    • Tools and dependencies
  • Images do not run themselves; they are executed as containers.
  • Images can be:
    • Pre-built (e.g. official images from DockerHub)
    • Custom-built using a Dockerfile
  • Dockerfiles contain instructions executed when an image is built using: docker build .
  • Each instruction in a Dockerfile creates a layer. Layers help in efficient rebuilding and sharing of images.
  • The CMD instruction is special:
    • Not executed when the image is built
    • Executed when a container is created and started

Containers

  • Containers are the other key building block Docker is all about.
  • Containers are running instances of images.
  • When a container is created using docker run, a thin read-write layer is added on top of the image.
  • Multiple containers can be created from the same image.
  • All containers run in isolation:
    • No shared application state
    • No shared written data
  • To start an application, you must:
    • Create a container
    • Start the container
  • Containers are what actually run in both development and production.

Key Docker Commands

For a full list of commands, use --help: docker --help, docker run --help

Official documentation: Docker Run Reference

Note: You only need a small subset of commands in real-world usage.

  • docker build . – Build a Dockerfile and create an image
  • -t NAME:TAG – Assign a name and tag to an image
  • docker run IMAGE_NAME – Create and start a container
  • --name NAME – Assign a name to a container
  • -d – Run container in detached mode
  • -it – Run container in interactive mode (stop with CTRL + C)
  • --rm – Automatically remove the container after stopping
  • docker ps – List running containers
  • docker ps -a – List all containers (including stopped)
  • docker images – List all local images
  • docker rm CONTAINER – Remove a container
  • docker rmi IMAGE – Remove an image
  • docker container prune – Remove all stopped containers
  • docker image prune – Remove dangling images
  • docker image prune -a – Remove all local images
  • docker push IMAGE – Push image to DockerHub or registry
  • docker pull IMAGE – Pull image from DockerHub

.NET 8 Web API – Multi-Stage Docker Build

# Build stage
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src

COPY InternifyWebAPI.csproj ./
RUN dotnet restore

COPY . .
RUN dotnet publish -c Release -o /app/publish /p:UseAppHost=false

# Runtime stage
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app

ENV ASPNETCORE_URLS=http://+:8085
ENV ASPNETCORE_ENVIRONMENT=Production

COPY --from=build /app/publish .
EXPOSE 8085

ENTRYPOINT ["dotnet", "InternifyWebAPI.dll"]
  

What This Dockerfile Does

  • Builds the .NET 8 Web API in a separate build stage
  • Publishes optimized release output
  • Runs the app in a lightweight runtime image
  • Keeps final image small and production-ready

Build Stage (SDK Image)

dotnet restore

Restores NuGet dependencies using the project file. This step is cached to speed up future builds.

dotnet publish

Creates a production-ready build in the /app/publish folder. The Release configuration ensures better performance.

Runtime Stage (ASP.NET Image)

ASPNETCORE_URLS

Configures the application to listen on port 8085 inside the container.

ASPNETCORE_ENVIRONMENT

Sets the environment to Production for optimized runtime behavior.

Port Exposure

Exposes port 8085 so the API can be accessed externally.

Application Startup

Starts the Web API using dotnet InternifyWebAPI.dll.

Key Benefits

  • Smaller Docker image
  • Faster startup time
  • Clean separation of build and runtime
  • Ideal for Docker, Render, and cloud deployment

Ignored Files & Folders

These entries are excluded to keep the project clean, secure, and lightweight during builds and version control.

Development Tools

  • .vs/ – Visual Studio local settings
  • .vscode/ – VS Code editor configuration

Build Output

  • bin/ – Compiled binaries
  • obj/ – Temporary build files

User-Specific Files

  • *.user – User-specific IDE settings
  • *.suo – Visual Studio solution options

Logs

  • *.log – Application and build logs

Environment & Secrets

  • *.env – Environment variables and secrets

OS-Specific Files

  • Thumbs.db – Windows system file
  • .DS_Store – macOS system file

Docker Files

  • docker-compose* – Local orchestration files
  • Dockerfile* – Build instructions (not needed inside image)

Result

Ignoring these files reduces clutter, improves security, and speeds up Docker builds and repository management.


Angular Docker Multi-Stage Build with Nginx

Build Stage (Angular App)

  • Node Image: Uses node:20-alpine to build Angular app
  • Working Directory: /app
  • Dependencies: Installs using npm install
  • Build: Runs production build
  • Output: Generates optimized files in dist/
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build -- --configuration production

Serve Stage (Nginx)

  • Nginx Image: Lightweight nginx:alpine
  • Cleanup: Removes default Nginx page
  • Routing: Custom Nginx config for Angular routing
  • Deploy: Copies Angular build to Nginx web folder
FROM nginx:alpine
RUN rm -rf /usr/share/nginx/html/*
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist/InternifyUI/browser/ /usr/share/nginx/html/

Container Runtime

  • Port: Exposes port 80
  • Start: Runs Nginx in foreground
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
  

Key Notes

  • InternifyUI = Angular project name
  • browser folder is used in Angular’s new build structure
  • Multi-stage build keeps image small and secure

What is .dockerignore?

.dockerignore tells Docker which files and folders should NOT be copied into the Docker image during build.

Benefits

  • Faster Docker builds
  • Smaller image size
  • More secure containers

Important .dockerignore Entries

node_modules

Prevents copying local Node.js dependencies. Docker installs fresh dependencies inside the container, avoiding OS compatibility issues and reducing image size.

dist

Excludes Angular build output. The app is built inside Docker to ensure clean and reproducible builds.

.git

Removes Git history from the image. This reduces size and improves security.

.angular

Excludes Angular cache and local build files to avoid unexpected behavior during Docker builds.

.env

Prevents sensitive environment variables from being included in the image. Environment values should be provided at runtime.

Commonly Ignored (Optional but Recommended)

  • .vscode – editor-specific settings
  • README.md – documentation only
  • npm-debug.log – local error logs
  • docker-compose.yml – used only for local setup
  • Dockerfile – already used by Docker during build
  • .gitignore – relevant only for Git

Nginx Configuration for Angular SPA

 
  server {
  listen 80;
  server_name localhost;

  root /usr/share/nginx/html;
  index index.html;

  location / {
    try_files $uri $uri/ /index.html;
  }
}
  

What This Configuration Does

  • Listens on port 80
  • Serves Angular static files
  • Supports Angular client-side routing
  • Prevents 404 errors on page refresh

Key Configuration Explained

listen 80;

Tells Nginx to accept HTTP requests on port 80, the standard port for web applications.

server_name localhost;

Defines the hostname this server responds to. Works for Docker containers, Render, and local testing.

root /usr/share/nginx/html;

Specifies the directory where Angular build files are stored (index.html, JavaScript, assets).

index index.html;

Sets index.html as the default file served at /.

Angular Routing Support (Most Important)

location /

Handles all incoming routes such as /, /home, /about, /login.

try_files $uri $uri/ /index.html;

Ensures Angular SPA routing works correctly:

  • Serves static files if they exist
  • Falls back to index.html for client-side routes
  • Lets Angular Router handle navigation

Result

  • No 404 error on page refresh
  • Direct URL access works (/home, /about)
  • Angular app loads correctly every time

Create and Run a Container

    docker run -d --name mycontainer -p 8080:80 myimage:latest
  
  • docker run – Create and start a container
  • -d – Run in background (detached mode)
  • --name – Assign container name
  • -p 8080:80 – Map host port to container port
  • myimage:latest – Image name and tag

Create Container Only

   docker create --name mycontainer -p 8080:80 myimage:latest
  

Start Created Container

   docker start mycontainer
  

Build a Docker Image

  docker build -t myimagename:latest .
  
  • docker build – Build image from Dockerfile
  • -t – Tag image (name:version)
  • . – Current directory (Dockerfile location)

Example

    docker build -t shadabalamcse0/myappui:latest .
  

Build with Version

   docker build -t shadabalamcse0/myappui:v1 .
  

Verify Images

  docker images
  

Run Container with Interactive Terminal

   docker run -it --name mycontainer ubuntu
  
  • -it – Interactive terminal mode
  • ubuntu – Base image

Example: Angular Nginx Container

   docker run -d --name angular-app -p 8080:80 shadabalamcse0/myappui:latest
  

Result

These commands allow you to build images, create containers, run applications, and manage Docker deployments efficiently.


Tagging and Pushing a Docker Image to Docker Hub

After building a Docker image locally, you must tag it and push it to Docker Hub so it can be deployed or shared.

Step 1: Tag the Docker Image

docker tag myapp:latest shadabalamcse0/myappui:latest
  

Explanation:

  • myapp:latest – Local Docker image
  • shadabalamcse0 – Docker Hub username
  • myappui – Repository name
  • latest – Image tag (version)

Docker Hub image naming format:

username/repository:tag
  

Tagging does not create a new image; it only creates a new reference.

Step 2: Push the Image to Docker Hub

docker push shadabalamcse0/myappui:latest
  

What happens during push:

  • Docker verifies login credentials
  • Image layers are uploaded to Docker Hub
  • Image becomes available on Docker Hub

No comments:

Post a Comment