🐳 Docker In-Depth: A Developer’s Guide for Local Development

Kean SernaKean Serna
4 min read

If you're a developer looking to streamline your environment, ensure consistency across teams, or just want to run your app in isolated containers Docker is your best friend. This post dives into Docker fundamentals, real-world usage, and practical commands with examples tailored for local development.

šŸš€ Getting Started with Docker

Before diving in, install Docker from the official docs:
šŸ‘‰ Install Docker Engine

After installing, run this command to check if Docker is working:

docker

āš™ļø How Docker Works (Inside Docker)

Under the hood, Docker uses several core Linux features like namespaces, cgroups, and union file systems.

  • Namespaces: These provide isolation between containers. Each container gets its own network, file system, and process space.

  • Control Groups (cgroups): These limit the resources (CPU, memory, etc.) that a container can use.

  • Union File Systems: Docker images are made up of multiple layers. Each instruction in a Dockerfile (like RUN, COPY) creates a new layer, which helps with caching and efficiency.

When you run a Docker container, Docker combines the image layers, mounts a new read-write layer on top, and then launches the process inside an isolated environment.

🧰 Essential Docker Commands

Here are some go-to commands every developer should know:

CommandDescription
docker imagesList available Docker images
docker psList running containers
docker ps -aList all containers
docker runRun a new container
docker start <id>Start a stopped container
docker kill <id>Stop a running container

šŸ” Access a Running Container

docker exec -it <container_id> /bin/sh   # For Alpine-based or minimal images  
docker exec -it <container_id> /bin/bash # For Ubuntu/Debian images  
docker exec <container_id> ls /path/to/folder  # List contents inside container

šŸ“¦ Dockerfile Basics

Here’s a sample Dockerfile for a Node.js app using Prisma:

image.png

Breakdown:

  • WORKDIR: Set working directory inside container

  • RUN: Execute shell commands

  • CMD: Command to run when container starts

  • EXPOSE: Expose ports

  • COPY: Copy files from host to image

Logs:

image.png

🧱 Images vs Containers

Understanding the difference between Docker images and containers is key.

  • A Docker image is a blueprint. It’s a read-only template with instructions for creating a container, like a snapshot of your application’s code, dependencies, and environment.

  • A container is a running instance of an image. It’s the real process isolated from your system, created from an image.

ā˜ļø Pushing Docker Images to DockerHub

  1. Create a DockerHub account

  2. Create a new repository

  3. Login:

     docker login
    
  4. Tag your image:

     docker tag <image_id> dockerhub_username/repo_name:tag
    
  5. Push it:

     docker push dockerhub_username/repo_name:tag
    

šŸ”Œ Docker Networks & Volumes

Volumes: Persisting Data

docker volume create volume_database
docker run -v volume_database:/data/db -p 27017:27017 mongo

Networks: Connecting Services

docker network create my_custom_network

# Backend with custom network
docker run -d -p 3000:3000 --name backend --network my_custom_network image_tag

# MongoDB on same network
docker run -d -v volume_database:/data/db --name mongo --network my_custom_network -p 27017:27017 mongo

# Check logs
docker logs <container_id>

Network Types:

  • Bridge (default): For isolated communication between containers

  • Host: Shares host network directly (use with caution)

Without volume:

With volume:

🧩 Docker Compose

For multi-container setups, use docker-compose.yml:

version: '3.8'
services:
  mongodb:
    image: mongo
    container_name: mongo-database
    ports:
      - '27017:27017'
    volumes:
      - mongodb_data:/data/db

  app:
    build:
      context: .
      dockerfile: Dockerfile
    image: testingimage2
    container_name: backend-mongo
    environment:
      - DATABASE_URL=mongodb://mongo-database:27017/course
    ports:
      - '3000:3000'
    depends_on:
      - mongodb

volumes:
  mongodb_data:

Common Commands:

docker compose up       # Start containers
docker compose down     # Stop and remove containers
docker compose logs     # View container logs
docker compose down --volumes  # Remove all volumes as well

šŸ”„ Bind Mounts (Hot Reloading)

Useful for development, especially with frameworks like Next.js.

Sample Dockerfile:

FROM node:20-alpine

WORKDIR /nextapp

COPY package* .

RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "run", "dev"]

docker-compose.yml:

version: '3'
services:
  nextapp:
    build: .
    container_name: nextapp-docker
    ports:
      - 3000:3000
    volumes:
      - .:/nextapp
      - /nextapp/node_modules

Without Compose:

docker run --name next-dev \
  -v .:/nextapp \
  -v /nextapp/node_modules \
  -p 3000:3000 \
  -d nextjs-image

🧠 Final Thoughts

Docker simplifies app development and deployment with containers that are fast, lightweight, and consistent across machines. Whether you're building APIs, full-stack apps, or databases, Docker should be part of your toolkit.

Happy Docking! 🐳

Follow me on Hashnode: https://hashnode.com/Kean De La Serna

0
Subscribe to my newsletter

Read articles from Kean Serna directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Kean Serna
Kean Serna