How to install, configure, and use Docker Compose for multi‑container local development
Docker Compose lets you define and run multi-container applications locally using a single YAML file. This guide walks you through installing Compose, creating a simple docker-compose.yml, configuring services and volumes, and running a reproducible development stack. Follow each step and you should have a working local environment in about 10–20 minutes.
Step 1: Install Docker Engine
Download and install Docker Desktop for macOS or Windows, or Docker Engine for Linux, following the official package for your OS. Verify the installation by running docker --version and docker run hello-world; both should complete in under a minute and confirm the daemon is working.
[Illustration: Laptop showing terminal with 'docker --version' and 'hello-world' output.]
Step 2: Install Docker Compose
If your Docker distribution does not include Compose v2, install the standalone Compose binary matching your OS and place it in a directory on PATH. Confirm with docker compose version or docker-compose --version — you should see a semantic version like 2.x in the output within a few seconds.
[Illustration: Terminal displaying 'docker compose version' output on a dark background.]
Step 3: Create project directory
Make a new directory for your app, for example mkdir myapp && cd myapp, and initialize any code (sample Node, Python, or static files). Keeping everything in one folder simplifies relative paths in docker-compose.yml and lets you rebuild containers quickly.
[Illustration: File explorer or terminal showing a new folder named 'myapp' with a simple app file.]
Step 4: Write docker-compose.yml
Create docker-compose.yml with at least two services (web and db), specifying images, ports, volumes, and depends_on. Use concrete settings like ports: "8080:80", volumes: ./code:/app, and environment variables for DB credentials so the stack is reproducible and easy to share.
[Illustration: Text editor open with a docker-compose.yml showing services web and db and port mappings.]
Step 5: Configure persistent volumes
Declare named volumes (e.g., db_data:) and bind mounts for code to preserve database state and enable live code editing. Using a named volume ensures data survives container recreation; bind mounts let you edit files locally and see changes within seconds in the container.
[Illustration: Diagram showing host folder mapped to container /app and a named volume attached to /var/lib/postgresql/data.]
Step 6: Bring the stack up
Run docker compose up --build in your project root to build images and start containers; add -d to run in the background. Expect first build to take several minutes; subsequent starts are faster. Verify with docker compose ps and test the app at http://localhost:8080.
[Illustration: Terminal running 'docker compose up --build' with logs streaming and a browser showing localhost:8080.]
Step 7: Iterate and debug containers
Use docker compose logs -f servicename to follow logs, docker compose exec servicename sh or bash to open a shell, and docker compose down to stop and remove containers. These commands let you inspect runtime state, run migrations, and quickly rebuild the environment when code or config changes.
[Illustration: Terminal split view: one pane with 'docker compose logs -f' and another with an interactive shell inside a container.]
- Pin image versions (for example node:18-alpine) to avoid unexpected changes when rebuilding.
- Use .env file to store non-secret configuration like ports and usernames; reference them in docker-compose.yml with ${VAR}.
- Use healthcheck entries to make depends_on more reliable; set interval: 10s, retries: 5 for service readiness.
- Mount only necessary directories as bind mounts to keep container performance good; avoid mounting your entire home directory.
- Run docker system prune --volumes monthly to reclaim disk space, but be cautious as it removes unused images and volumes.
- Add a Makefile with shortcuts (make up, make down, make logs) to speed common workflows and reduce typing.
- Never store production secrets in docker-compose.yml or .env; use a secrets manager or environment injection instead.
- docker compose down --volumes will delete named volumes and irreversibly remove data; back up databases first if you need the data.
- Be careful with published ports like 0.0.0.0:80:80 on shared networks; they expose services to other machines and can create security risks.
- Avoid running containers as root unless required; use user directives in Dockerfile or compose to limit privilege escalation.
Was this guide helpful?
More Computers & Electronics guides
How to set up Git, create a repository, and commit code locally
Setting up Git and committing code locally is a small, reliable skill that pays off immediately. In about 10–20 minutes you can install Git, create a repository, and make your first commits so your work is tracked and easy to manage. Follow these clear steps to get a solid local workflow going.
How to migrate email from one provider to another without losing folders or contacts
Migrating email between providers can feel risky, but with a plan you can preserve folders, labels, and contacts while minimizing downtime. This guide walks you through a careful, step-by-step transfer you can complete in a few hours to a couple days depending on mailbox size. Follow the checklist and you’ll keep structure and address data intact.
How to clean dust and replace a laptop fan to fix overheating and throttling
Overheating and CPU/GPU throttling are often caused by dust buildup or a failing fan. This guide walks you through safely cleaning dust and replacing a laptop fan to restore cooling performance and reduce temperature spikes. Read through all steps, gather basic tools, and work in a well-lit, static-safe area.