Deploying Web Applications in Azure with Docker

Learn how to containerize your application using Docker and deploy it seamlessly to Azure App Services.

Building and Deploying Services Using Docker

Note: This plan was generated by GitHub Copilot Workspaces.

Introduction

In this blog post, we will explore how to use Docker to containerize a web application and deploy it to Azure App Services. This approach ensures that your application runs consistently across different environments without dependency issues.

Prerequisites

Basic understanding of Docker An Azure account Docker installed on your local machine Azure CLI installed

Step 1: Understanding Docker and Containers

Docker is a platform that enables developers to create, deploy, and run applications in containers. Containers are lightweight, portable, and self-sufficient units that include everything needed to run an application, such as code, runtime, libraries, and system tools.

Key Concepts

Step 2: Containerizing Your Application

1. Create a Dockerfile in your project directory. 2. Define the base image and dependencies. 3. Copy your application code into the container. 4. Expose the necessary ports. 5. Build the Docker image.

Example Dockerfile

# Use an official Python runtime as a parent image
FROM python:3.8-slim

# Set the working directory in the container
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . /app

# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

Step 3: Testing Locally

1. Run the Docker container locally. 2. Test the application to ensure it works as expected.

Running the Container

docker build -t myapp .
docker run -p 4000:80 myapp

Step 4: Pushing to Docker Hub

1. Tag your Docker image. 2. Push the image to Docker Hub.

Pushing the Image

docker tag myapp mydockerhubusername/myapp
docker push mydockerhubusername/myapp

Step 5: Running Docker on Mac

Docker Desktop for Mac is the easiest way to get started with Docker on macOS. It includes Docker Engine, Docker CLI client, Docker Compose, Docker Content Trust, Kubernetes, and Credential Helper.

Installation Steps

1. Download Docker Desktop for Mac from the Docker website. 2. Open the downloaded file and drag the Docker icon to the Applications folder. 3. Launch Docker from the Applications folder. 4. Follow the on-screen instructions to complete the installation.

Running Docker Commands

Once Docker Desktop is installed, you can run Docker commands from the terminal. For example:

docker --version
docker run hello-world

Step 6: Deploying Docker Containers in the Cloud

Azure App Services provides a fully managed platform for building, deploying, and scaling web apps. You can deploy Docker containers to Azure App Services using the Azure CLI.

Deployment Steps

1. Create an Azure App Service. 2. Configure the App Service to use your Docker image. 3. Deploy the Docker container to Azure.

Example Deployment

# Log in to Azure
az login

# Create a resource group
az group create --name myResourceGroup --location eastus

# Create an App Service plan
az appservice plan create --name myAppServicePlan --resource-group myResourceGroup --sku B1 --is-linux

# Create a web app
az webapp create --resource-group myResourceGroup --plan myAppServicePlan --name myUniqueAppName --deployment-container-image-name mydockerhubusername/myapp

# Configure the web app to use the Docker image
az webapp config container set --name myUniqueAppName --resource-group myResourceGroup --docker-custom-image-name mydockerhubusername/myapp

# Browse to the web app
az webapp browse --name myUniqueAppName --resource-group myResourceGroup

Step 7: Timeline and Daily Plan

To get a good understanding of Docker and containers, follow this daily plan:

Day 1: Introduction to Docker

Day 2: Understanding Docker Images and Containers

Day 3: Docker Networking and Volumes

Day 4: Docker Compose

Day 5: Deploying Docker Containers to the Cloud

Conclusion

By following these steps, you can easily containerize your web application using Docker and deploy it to Azure App Services, ensuring a smooth and consistent deployment process.

Additional Resources


Background & Prerequisites — What You Need to Cover Beyond the Existing Content

The current content covers Docker basics well. Below are the deeper topics needed to make this blog production-grade and differentiated.


1. Docker Internals — How Containers Actually Work

Why: Understanding internals helps debug issues and make better architectural decisions. - Linux namespaces — Containers use kernel namespaces to isolate: PID (process IDs), NET (network stack), MNT (filesystem mounts), UTS (hostname), IPC (inter-process communication), USER (user/group IDs). Each container gets its own isolated view of these resources. - cgroups (Control Groups) — Limit and account for resource usage: CPU, memory, disk I/O, network. When you set --memory=512m in Docker, it's a cgroup limit. - Union filesystem (OverlayFS) — Images are layered. Each Dockerfile instruction creates a layer. Layers are read-only; the container gets a thin read-write layer on top. This enables image sharing and efficient storage. - Container runtime — Docker daemon → containerd → runc. runc is the OCI (Open Container Initiative) reference implementation that actually creates the container using namespaces and cgroups.

2. Multi-Stage Builds

Why: Critical for production — reduces image size by 50-90%. - Problem — Build tools (compilers, dev dependencies) bloat the final image. A Python image with build tools can be 1GB+. - Solution — Stage 1: install dependencies, compile code. Stage 2: copy only the built artifacts and runtime dependencies into a slim base image. - Example pattern — Build stage uses python:3.12 (full, ~900MB), runtime stage uses python:3.12-slim (~150MB) or python:3.12-alpine (~50MB but compatibility issues).

3. Docker Compose for Multi-Container Apps

Why: Real applications have multiple services (web app + database + cache + worker). - docker-compose.yml — Declarative definition of services, networks, volumes. Version 3.x syntax. - Service dependenciesdepends_on, health checks, restart policies. - Networking — Services on the same network can reach each other by service name (DNS resolution). Custom networks for isolation. - Volumes — Named volumes for persistent data (databases). Bind mounts for development (live code reload). - Environment variables.env file, environment section, secrets management.

4. Container Security Best Practices

Why: Production containers need hardening. - Run as non-root — Add USER appuser in Dockerfile. Never run as root in production. - Minimal base images — Use slim or distroless images. Fewer packages = smaller attack surface. - Image scanning — Use docker scout, Trivy, or Snyk to scan for CVEs in your image layers. - Secrets management — Never put secrets in Dockerfile or image layers. Use environment variables, Docker secrets, or Azure Key Vault. - Read-only filesystem — Run containers with --read-only flag. Write only to specific tmpfs mounts.

5. Azure Container Apps vs App Service (Deeper Comparison)

Why: The blog covers App Service. Container Apps is the newer alternative. - Container Apps — Serverless, scale to zero, built-in Dapr support, KEDA-based autoscaling, ingress management. Better for microservices. - App Service — PaaS, always running (minimum 1 instance), integrated CI/CD, custom domains, SSL, deployment slots. Better for traditional web apps. - AKS — Full Kubernetes control. For complex multi-service architectures with specific orchestration needs.


TODO / Remaining Work

Back to Blog About the Author