Docker for Web Applications

#Docker

Docker for Web Applications

This guide explains how to dockerize a full‑stack web application with separate backend and frontend containers, plus PostgreSQL and Redis for data persistence.

Project Structure

my-app/
├── backend/
│   ├── src/
│   │   └── index.ts
│   ├── Dockerfile
│   ├── package.json
│   ├── tsconfig.json
│   └── .dockerignore
├── frontend/
│   ├── src/
│   │   └── App.tsx
│   ├── Dockerfile
│   ├── package.json
│   └── .dockerignore
├── docker-compose.yml
├── .env
└── .gitignore

backend/Dockerfile

Purpose: Describes the build process for the Node.js backend with TypeScript.

FROM node:18-alpine
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
COPY . .
RUN yarn build
CMD ["node", "dist/index.js"]

frontend/Dockerfile

Purpose: Describes the build process for the React frontend.

FROM node:18-alpine
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
COPY . .
RUN yarn build
CMD ["yarn", "start"]

docker-compose.yml

Purpose: Defines services (backend, frontend, PostgreSQL, Redis), ports, environment, and volumes.

version: '3.8'

services:
  backend:
    build: ./backend
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgres://user:password@db:5432/myapp
      - REDIS_HOST=redis
      - NODE_ENV=production
    depends_on:
      - db
      - redis
    volumes:
      - ./backend:/app

  frontend:
    build: ./frontend
    ports:
      - "80:3000"
    environment:
      - REACT_APP_API_URL=http://backend:3000
    depends_on:
      - backend

  db:
    image: postgres:13
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=myapp
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data

  redis:
    image: redis:6
    ports:
      - "6379:6379"
    volumes:
      - redisdata:/data

volumes:
  pgdata:
  redisdata:

.env

Purpose: Stores environment variables (do not commit to Git).

DATABASE_URL=postgres://user:password@db:5432/myapp
REDIS_HOST=redis
API_KEY=your-secret-key

.dockerignore

Purpose: Excludes unnecessary files from being copied.

node_modules
dist
.git
.env
Dockerfile

Installation

  • Docker: Install from the official website.
  • Docker Compose: Comes with Docker Desktop or install on Linux (sudo apt install docker-compose).

Verify:

docker --version
docker-compose --version

Container Interactions

All services share a network and access each other by service name.

Example (backend/src/index.ts):

import express from 'express';
import { Pool } from 'pg';
import { createClient } from 'redis';

const app = express();
const port = 3000;

const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const redisClient = createClient({ url: `redis://${process.env.REDIS_HOST}:6379` });
redisClient.connect().catch(console.error);

app.get('/data', async (req, res) => {
  const cached = await redisClient.get('data');
  if (cached) return res.json({ source: 'redis', data: JSON.parse(cached) });

  const { rows } = await pool.query('SELECT NOW()');
  await redisClient.setEx('data', 3600, JSON.stringify(rows));
  res.json({ source: 'db', data: rows });
});

app.listen(port, () => console.log(`Backend on port ${port}`));

Port Mapping & Env Variables

Ports map host:container (e.g., 3000:3000). Environment variables are set in docker-compose or pulled from .env.

Working Commands

  • docker-compose up --build: build & start all services
  • docker-compose up -d: start in background
  • docker-compose down: stop all (add --volumes to remove data)
  • docker-compose logs backend: view backend logs
  • docker-compose restart backend: restart backend

Backend Version Updates

Local Development

Modify code and run docker-compose up --build backend.

Production (Tagged Images)

  1. Build: docker build -t myapp-backend:1.0.0 ./backend
  2. Push to registry:
    docker login
    docker tag myapp-backend:1.0.0 yourusername/myapp-backend:1.0.0
    docker push yourusername/myapp-backend:1.0.0
    
  3. Update docker-compose.yml to use image: yourusername/myapp-backend:1.0.0, then docker-compose pull backend && docker-compose up -d backend.

Automation with CI/CD

Use GitHub Actions to build & push images on push to main:

name: Build and Push Docker Image
on:
  push:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Build & push Docker image
        run: |
          docker build -t yourusername/myapp-backend:${{ github.sha }} ./backend
          docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
          docker push yourusername/myapp-backend:${{ github.sha }}
Planet Green Devinity LLCPlanet Green Devinity LLCPlanet Green Devinity LLCPlanet Green Devinity LLC

More Blogs

DeepSeek Integration with Node.js
#DeepSeek #OpenAI #AWS #Node.js #AI Integration

DeepSeek Integration with Node.js

Learn how to integrate DeepSeek AI with Node.js and deploy scalable solutions using AWS.

/blog/8
Machine Learning Basics
#Python practices

Machine Learning Basics

Key concepts of machine learning and popular libraries like scikit-learn and TensorFlow.

/blog/1