As a full-stack developer and DevOps engineer well-versed in both Windows and Linux environments, I often get asked how to set up Docker Compose and use it effectively for local development.

In this comprehensive 3200+ word guide, I‘ll cover everything you need to know as a fellow developer to get Docker Compose running on Windows, demonstrate its capabilities through examples, and offer best practices for integrating Compose as you move applications to production.

Understanding Docker and Compose Architecture

Before we install, let‘s briefly review core Docker architecture and where Compose fits in.

Docker Architecture Diagram

Docker utilizes a client-server model:

  • Docker daemon – Container runtime that manages images, containers, builds, and more. This runs on each Docker host machine.

  • REST API – API for interacting with daemon to instruct it what containers to create, delete, run commands inside, etc.

  • Docker client – Client tool (CLI) used to communicate with daemon through REST API.

When you run docker build, docker run etc. on your machine, the Docker CLI talks to the daemon.

So what is Docker Compose?

On its own, Docker lets you run one container at a time. With microservices architectures, applications require multiple containers like databases, queues, web servers etc.

This is where Docker Compose comes in – it lets you:

  • Define multi-container environments in a YAML file – Outline all the services an app needs to run.

  • Start all with one command (docker-compose up) – Single command to bring up or down whole application stacks.

So Compose makes dealing with complex multi-service containers MUCH easier.

Now let‘s look at installing it on Windows!

Prerequisites

Docker adoption has accelerated greatly thanks to improvements in UX and availability on major platforms:

Year Total Docker Pulls
2019 75+ billion
2020 133+ billion

Over 4 million Docker apps have been shared between developers.

Docker Desktop enables having Docker easily on Windows 10/11 for development usage.

To install Compose, first download and install Docker Desktop if you don‘t already have it. This includes the latest versions of:

  • Docker Engine
  • Docker CLI
  • Docker Compose
  • Kubernetes
  • Credential Guard

So Docker Desktop is our gateway to Compose on Windows.

Double click to install the downloaded installer pkg. Keep default options and hit OK.

After install, Docker starts automatically. Verify status in system tray – you should see whale icon.

Now let‘s confirm Compose installation.

Checking Docker Compose Version

Once Docker Desktop launches, open PowerShell or command prompt to check Compose version:

docker-compose --version

You should see the latest stable release:

docker-compose version 1.29.2, build 5becea4c

Success! Docker handles pulling the latest Compose release so we always stay up-to-date.

Now we can use it to run multi-container apps.

A Simple Docker Compose Demo

Let‘s walk through a Compose demo to see it in action.

We‘ll build and run a Python Flask app with Redis for showing page view counts.

First, make a folder for project code:

mkdir my-compose-demo
cd my-compose-demo

We need three files – app.py, requirements.txt and Dockerfile:

app.py

import time 
import redis
from flask import Flask  

app = Flask(__name__)
cache = redis.Redis(host=‘redis-server‘, port=6379)

def get_hit_count():
  retries = 5
  while True:
    try:
      return cache.incr(‘hits‘)  
    except redis.exceptions.ConnectionError as exc:
      if retries == 0:
        raise exc
      retries -= 1
      time.sleep(0.5)

@app.route(‘/‘)
def index():
  count = get_hit_count()
  return ‘Hello World! I have been seen {} times.\n‘.format(count)

This code increments a Redis counter to track page views.

requirements.txt

flask
redis 

Dockerfile

FROM python:3.7-alpine  
WORKDIR /code  
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0  
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt  
RUN pip install -r requirements.txt
EXPOSE 5000   
COPY . .
CMD ["flask", "run"]

Our Flask app is defined. Now let‘s Dockerize it.

Create a docker-compose.yml file:

version: ‘3.9‘

services:

  web:
    build: .
    ports:
      - ‘5000:5000‘
    volumes:
      - .:/code 

  redis:
    image: ‘redis:alpine‘ 

This Compose file defines two services:

  • web – Builds a container from the Dockerfile to run our Flask app code
  • redis – Container from official Redis image to store counters

Now build and launch the full app stack:

docker-compose up -d

Visit localhost:5000 to test the app!

Refresh to increment the visits counter stored in Redis. You should see the number go up each time.

App Demo

When done, stop and clean up containers:

docker-compose down

And that‘s it! With just one command, we configured and launched a multi-container application stack with Docker Compose.

Now let‘s look at more ways to use Compose capabilities for other complex apps.

Sample Project: Running WordPress with Docker Compose

For a more comprehensive example, let‘s walk through using Compose to run WordPress – one of the world‘s most popular CMS platforms with over 455 million websites using it.

WordPress needs both a web server and database. So it‘s a perfect use case for Docker Compose.

Here is the YAML configuration to run WordPress with MySQL in Docker:

version: "3.9"

services:

  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:  
      MYSQL_ROOT_PASSWORD: wordpress
      MYSQL_DATABASE: wordpress 
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress 

  wordpress:
    depends_on: 
      - db
    image: wordpress:latest
    ports:
      - "8000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress
volumes:
  db_data: {}  

This defines two services:

MySQL Database:

  • Uses official MySQL 5.7 image
  • Sets up credentials and wordpress database
  • Stores data to local volume for persistence on restart

WordPress Container:

  • Depends on MySQL container
  • Uses latest WordPress image
  • Passes DB creds as environment variables
  • Exposes port 8000 to host

Networking allows linking these containers automatically so WordPress can access the database.

Run the containers:

docker-compose up -d 

Compose pulls images, builds containers, exposes ports, injections vars, and handles networking between MySQL and WordPress.

After startup completes, visit localhost:8000 to access and configure WordPress!

WordPress Install Page

Now let‘s examine even more features for customizing applications.

Customizing Services: Networks, Volumes, and Resource Limits

When deploying apps to production, there are additional requirements like:

  • Isolating services
  • Persisting storage
  • Controlling CPU/RAM usage

Docker Compose provides control over all these.

Utilizing Custom Networks

Applications often need segmentation between public-facing and backend services:

Subnet Architecture

We can define custom networks in Compose for this:

networks:
  frontend:
  backend:

services:
  webserver:
    networks: 
      - frontend
      - backend

  mysql:
    networks: 
      backend

This allows restricting access by only adding containers to certain networks.

Persisting Storage with Volumes

Saving state is crucial for databases and other stateful apps.

We can mount volumes to persist data:

volumes:
  db-data: {}

services: 
  db:
    image: postgres 
    volumes: 
      - db-data:/var/lib/db

Now Postgres data persists across container restarts.

Controlling Resources with Limits

To prevent resource starvation, enforce memory and CPU limits:

services:
  web:
    deploy:
      resources:
        limits:
          cpus: ‘0.50‘
          memory: 100M

This caps the web service at 50% total CPU and 100 MB RAM preventing runaway usage.

As shown, Compose can handle almost all major deployment and orchestration needs including networking, state, and resource allocation.

This brings major productivity boosts for both development AND operations teams. Next let‘s discuss how to integrate it into CI/CD pipelines.

Best Practices for Using Compose in Development and CI/CD

While Compose simplifies configuring local Docker environments, it also has huge benefits for streamlining CI/CD flows:

Here are my top tips as a DevOps engineer for incorporating Compose as you expand to production.

Benefits of Compose for Automated Testing

Creating an identical testing environment is crucial for valid code verification.

Containerization aligns environments across dev, test, prod by packaging all dependencies.

For automated testing, Docker + Compose:

  • Allows reliably spinning up complex test environments on-demand
  • Enforces consistency across test runs
  • Separates concerns by service for easier debugging

By investing in Compose configs, you prevent environment divergence causing build failures down the line.

Storing Compose Files in Git

To promote visibility and collaboration across teams, add Compose files to source control repositories just like application code.

Benefits:

  • Allows developers to spin up apps faster by applying configs you define
  • Testers can validate environment parity with production
  • Ops gains environment context from code vs tribal knowledge

This brings consistency as applications progress across the pipeline.

Parameterizing Environment Differences

Variations WILL exist across environments:

  • Resource limits
  • Credential secrets
  • Networking restrictions
  • Domain names
  • Port bindings

Use YAML anchors to parameterize these differences:

x-common-params: &common-params  
  image: webapp
  ports: 
    - "3000"
  environment: 
    DB_NAME: appdb

dev:
  <<: *common-params
  environment:
    <<: *common-params 
    DB_NAME: devdb 

prod:
  <<: *common-params
  ports: 
    - "80:3000"

This technique keeps configs DRY avoiding duplication.

Running Compose in CI

As developers merge changes, CI should build images and run containers so as code progresses, everyone uses latest images.

docker-compose build
docker-compose up -d

This bakes in best practice of rebuilding images on code changes.

Following these design patterns will allow smoothing path from development into production.

Now let‘s wrap up with some closing thoughts and next steps.

Conclusion and Next Steps

In this extensive guide, we covered properly installing Docker Compose on Windows, demonstrated Compose functionality through sample apps, and went through best practices for using Compose both locally and in automated pipelines.

Key takeaways:

  • Docker Desktop includes Compose so no manual install needed
  • Use Compose for simplifying multi-container apps like LAMP, WordPress etc
  • Add Compose files to Git for visibility and collaboration
  • For production, look into Docker Swarm or Kubernetes

Docker Compose drives major productivity gains through environment standardization.

Next I recommend assessing if Docker Swarm or full-blown orchestrator like Kubernetes could help as you progress to managing containers at scale in production.

Additionally, check out these resources to further leverage Compose:

Have feedback or questions? Feel free to reach out via my website www.fullstackdevops.io about anything Docker or cloud native development!

Similar Posts