0Pricing
Docker & Kubernetes for Developers · Lesson

Containerizing a Web Application

Walk through the process of Dockerizing a typical web application, including its frontend, backend, and database components.

Containerizing a Web Application is a free Docker & Kubernetes for Developers lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Docker & Kubernetes for Developers learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Containerizing Web Apps

Welcome to containerizing a web application! In this lesson, we'll walk through how to package a complete web application, including its frontend, backend, and database, into Docker containers.

This is a crucial step for modern development, enabling consistency across environments and simplifying deployment.

Web App Architecture

A typical web application usually consists of several components working together. For our example, we'll focus on a common three-tier architecture:

  • Frontend: The user interface (e.g., React, Vue, Angular) that runs in the browser.
  • Backend: The server-side logic (e.g., Node.js, Python Flask, Java Spring) that handles business logic and API requests.
  • Database: Stores and manages application data (e.g., PostgreSQL, MySQL, MongoDB).

Backend: Node.js API

First, let's create a Dockerfile for a simple Node.js backend API. This file tells Docker how to build an image for our backend service.

We'll start with a base Node.js image, copy our application code, install dependencies, and define the command to run the server.

FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

Frontend: React & Nginx

For our frontend, we'll use a multi-stage Dockerfile. This is a best practice for frontend applications, allowing us to build the app in one stage and then serve the static assets using a lightweight web server like Nginx in a separate, smaller stage.

This results in a much smaller final image.

FROM node:18-alpine as builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:stable-alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Database: PostgreSQL Service

For the database, we don't need to write a Dockerfile. Instead, we can use an official image from Docker Hub, like PostgreSQL.

It's crucial to use a Docker volume to ensure our database data persists even if the container is removed or recreated. We'll define this when we use Docker Compose.

Orchestration with Compose

Now that we have Dockerfiles for our frontend and backend, and know we'll use an official image for our database, we need a way to define and run all these services together.

This is where Docker Compose comes in. It uses a YAML file (docker-compose.yml) to configure all our services, networks, and volumes.

version: '3.8'
services:
  # Define your application services here

volumes:
  # Define named volumes for data persistence

networks:
  # Define custom networks for inter-service communication

Compose: Backend Service

Let's add our backend service to the docker-compose.yml file. We'll specify its build context (where its Dockerfile is), map ports, define environment variables for database connection, and set up a dependency on the database.

version: '3.8'
services:
  backend:
    build: ./backend # Path to backend Dockerfile
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgres://user:password@db:5432/mydb
    depends_on:
      - db # Ensure db starts before backend
    networks:
      - app-network

networks:
  app-network:
    driver: bridge # Custom network for app services

Compose: Frontend Service

Next, we add the frontend service definition. This service will also be built from its Dockerfile, expose port 80, and depend on the backend service to ensure it's available for API calls.

version: '3.8'
services:
  # ... backend service definition ...
  frontend:
    build: ./frontend # Path to frontend Dockerfile
    ports:
      - "80:80"
    depends_on:
      - backend # Frontend needs backend to be ready
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

Compose: Database Service

Finally, we define the database service. We'll use the official postgres image, set crucial environment variables for database setup, and most importantly, attach a named volume for data persistence.

version: '3.8'
services:
  # ... backend and frontend definitions ...
  db:
    image: postgres:13-alpine # Use an official PostgreSQL image
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - db_data:/var/lib/postgresql/data # Mount named volume
    networks:
      - app-network

volumes:
  db_data: # Define the named volume
networks:
  app-network:
    driver: bridge

Launching the App Stack

With our docker-compose.yml file complete, launching the entire application stack is incredibly simple. Navigate to the directory containing your docker-compose.yml file and run a single command:

  • docker compose up -d: Builds images (if needed), creates containers, networks, and volumes, and starts all services in detached mode (-d).
  • docker compose down: Stops and removes all services, networks, and volumes defined in the file.
docker compose up -d

Compose Configuration Check

Consider the following docker-compose.yml snippet for a simple web application:

version: '3.8'
services:
  web:
    build: .
    ports:
      - "8000:8000"
    depends_on:
      - db
  db:
    image: postgres:latest
    environment:
      POSTGRES_DB: appdb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    volumes:
      - db_data:/var/lib/postgresql/data
volumes:
  db_data:

Which of the following statements about this configuration are TRUE?

Lesson Summary

In this lesson, we learned how to containerize a full web application stack using Docker. We covered creating Dockerfiles for frontend and backend services, using official images for databases, and orchestrating everything with Docker Compose. This approach simplifies development, deployment, and scaling of complex applications.

  • Defined Dockerfiles for a multi-stage frontend and a backend service.
  • Integrated a database using an official Docker image and a named volume.
  • Orchestrated all services using a docker-compose.yml file.
  • Learned to launch the entire application stack with a single command.

Frequently asked questions

Is the “Containerizing a Web Application” lesson free?

Yes — the full text of “Containerizing a Web Application” is free to read here on the web, and the Docker & Kubernetes for Developers course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Docker & Kubernetes for Developers course, upgrade to CoddyKit PRO.

What will I learn in “Containerizing a Web Application”?

Walk through the process of Dockerizing a typical web application, including its frontend, backend, and database components. You practise Docker & Kubernetes for Developers with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Docker & Kubernetes for Developers?

No prior experience is required. Docker & Kubernetes for Developers on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Containerizing a Web Application” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Docker & Kubernetes for Developers lesson?

Yes. Every Docker & Kubernetes for Developers lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Containerizing a Web Application
  2. Optimizing Docker Images
  3. Security & Production Best Practices
  4. Multi-Stage Builds for Lean Production Images
← Back to Docker & Kubernetes for Developers