Computers & Electronics
153,933 views
25 min · 3 min read
7 steps
Advanced

How to set up and run Docker containers for local web development

Docker makes it fast to create reproducible local web development environments that match production. This guide walks you through installing Docker, creating a simple project, and running containers for a web app and a database. Follow the steps to get a reliable local stack you can iterate on in 15–60 minutes.

Verified by pleasexplain editors
  1. Step 1: Install Docker Desktop or Engine

    Download Docker Desktop for macOS or Windows, or install Docker Engine on Linux following your distro's package manager instructions. Expect a 200–500 MB download and 5–15 minutes to install; confirm with docker --version and docker compose version to ensure both CLI and Compose are available.

    [Illustration: computer screen showing Docker Desktop install progress and terminal confirming docker --version]

  2. Step 2: Create project directory

    Make a new project folder (for example ~/projects/myapp) and create subfolders www and db-data to separate code from persistent storage. This keeps files organized and ensures container volumes won’t overwrite your source; run mkdir -p ~/projects/myapp/{www,db-data} to create them in one command.

    [Illustration: file explorer showing project folder with www and db-data subfolders and terminal running mkdir command]

  3. Step 3: Add app and Dockerfile

    Place a simple web app in www (for example a Node.js index.js and package.json or a static index.html). Add a Dockerfile that installs dependencies and exposes the app port (for Node: FROM node:18, WORKDIR /app, COPY ., RUN npm install, EXPOSE 3000, CMD ["node","index.js"]). A clear Dockerfile produces consistent builds across machines.

    [Illustration: text editor open with Dockerfile and a simple Node.js index.js file on screen]

  4. Step 4: Define services with docker-compose

    Create a docker-compose.yml in the project root defining at least a web service and optionally a database service. Map ports like 3000:3000, mount ./www:/app:cached for fast code sync, and configure volumes for db-data. Using Compose simplifies starting multiple containers with docker compose up -d.

    [Illustration: yaml file shown in editor with docker-compose services web and db and port mappings highlighted]

  5. Step 5: Build and run containers

    From the project root run docker compose build to build images, then docker compose up -d to start services in detached mode. Expect initial build to take 30–120 seconds; subsequent docker compose up uses cached layers and is much faster. Verify with docker compose ps and docker logs <service> if needed.

    [Illustration: terminal showing docker compose build and docker compose up -d output and docker compose ps list]

  6. Step 6: Connect and test locally

    Open your browser at http://localhost:3000 (or the mapped port) to confirm the app responds. For databases, connect with localhost and the mapped port (e.g., 5432) or use docker exec -it <db-container> psql to inspect data. Quick iterative testing lets you change code in ./www and see updates immediately if volumes are configured.

    [Illustration: browser window displaying local web app at localhost:3000 with developer tools open and terminal showing database connection test]

  7. Step 7: Clean up and iterate safely

    When you finish a session, stop containers with docker compose down which removes networks and default-created containers; add --volumes if you want to remove named volumes. Use docker system prune --volumes periodically (cautiously) to free up disk space; expect to reclaim hundreds of MBs or more depending on images.

    [Illustration: terminal running docker compose down and docker system prune with confirmation prompts]


  • Pin image versions (e.g., node:18.20) to avoid unexpected changes when rebuilding.
  • Use .dockerignore to exclude node_modules, logs, and large files to speed builds; example: node_modules, .git, *.log.
  • Map only required ports and use different host ports (e.g., 3001 vs 3000) if running multiple projects concurrently.
  • Add healthcheck entries in docker-compose.yml to let Compose know when a service is ready for dependent services.
  • Use bind mounts for rapid code editing during development and copy files into images for production builds to improve stability.
  • Commit your docker-compose.yml and Dockerfile to source control so teammates can reproduce the environment exactly.

  • Do not run containers as root user unless necessary; set a nonroot USER in your Dockerfile to avoid permission and security issues.
  • Avoid binding production credentials directly into docker-compose.yml; use environment files or secrets management and never commit sensitive files to version control.
  • Be cautious with docker system prune --volumes; it permanently deletes images, containers, and volumes and can cause data loss if run unintentionally.
  • Windows file sharing and antivirus can slow bind-mounted volumes; test and adjust performance settings if file operations seem slow.

Was this guide helpful?