Table of Contents
Open Table of Contents
Docker Compose vs Docker Bake
Let’s clarify the difference:
Docker Compose is all about running services — managing containers, networks, volumes, and environment variables. It’s ideal for runtime orchestration.
version: '3.8'
services:
web:
image: node:18
container_name: web_app
working_dir: /app
volumes:
- ./app:/app
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:password@db:5432/mydatabase
depends_on:
- db
command: sh -c "npm install && npm start"
db:
image: postgres:15
container_name: postgres_db
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydatabase
volumes:
- db_data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
db_data:
Docker Bake, on the other hand, is focused on building container images — managing build arguments, tags, and build contexts. It’s optimized for creating standardized, efficient builds.
group:
default:
targets:
- app
- web
target:
app:
context: ./app
dockerfile: Dockerfile
tags:
- myorg/app:latest
platforms:
- linux/amd64
- linux/arm64
web:
context: ./web
dockerfile: Dockerfile
tags:
- myorg/web:latest
platforms:
- linux/amd64
In most real-world projects, you’ll end up using both tools together — Compose for local development, and Bake for standardized builds.
🧪 Basic Usage: A Simple Flask App
Let’s start with a simple Flask application:
- A
Dockerfile
using Python 3.9 - A
requirements.txt
with Flask - A basic Flask app exposing port 5000
1. Dockerfile
# Use the official Python 3.9 base image
FROM python:3.9-slim
# Set working directory
WORKDIR /app
# Copy requirements and install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application code
COPY app.py .
# Expose port Flask will run on
EXPOSE 5000
# Run the Flask app
CMD ["python", "app.py"]
2. requirements.txt
flask
3. app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return "Hello from Flask running in Docker!"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
Previously, we would run:
docker build -t myapp:latest .
But with Docker Bake, we define a docker-bake.yaml
like this:
services:
myapp:
build:
context: .
dockerfile: Dockerfile
image: myapp:latest
Then, we build it using:
docker buildx bake -f docker-bake.yaml
That’s it! The image is built with the tag myapp:latest
.
⚙️ Advanced Usage: Multi-Service Builds
Docker Bake really shines in complex scenarios.
Imagine a project with:
- A frontend (React)
- A backend (Flask)
- A database (Postgres)
Each component has its own Dockerfile in separate directories. Instead of three separate build commands, we define all three in a single docker-bake.yaml
file with different targets:
target:
frontend:
context: ./frontend
dockerfile: Dockerfile
tags: ["frontend:latest"]
backend:
context: ./backend
dockerfile: Dockerfile
tags: ["backend:latest"]
database:
context: ./database
dockerfile: Dockerfile
tags: ["database:latest"]
Then, with one command, we can build them all:
docker buildx bake -f docker-bake.yaml
This simplifies your workflow drastically and ensures consistency across all your services.
🌍 Environment-Specific Builds
You can even define multiple environments (like dev, QA, and production) using conditional logic within the bake file. For example:
target:
dev:
context: .
args:
ENV: development
tags: ["myapp:dev"]
prod:
context: .
args:
ENV: production
tags: ["myapp:prod"]
The same Dockerfile can behave differently based on the passed ENV
argument, making it easy to maintain multiple configurations in one place.
🔁 CI/CD Integration
Docker Bake works great in CI/CD pipelines. In fact, you can define matrix builds for multiple platforms and targets like this:
group:
default:
targets: ["api-dev", "api-prod", "web-dev", "web-prod"]
target:
base:
platforms: ["linux/amd64", "linux/arm64"]
api-dev:
inherits: ["base"]
context: ./api
args:
ENV: development
api-prod:
inherits: ["base"]
context: ./api
args:
ENV: production
web-dev:
inherits: ["base"]
context: ./web
args:
ENV: development
web-prod:
inherits: ["base"]
context: ./web
args:
ENV: production
Run it with:
docker buildx bake -f docker-bake.yaml
This structure makes it ideal for GitHub Actions, GitLab CI, or any other CI tool that benefits from standardized builds across different environments and platforms.
✅ Recap: Why Use Docker Bake?
Docker Bake | Docker Compose |
---|---|
Builds container images | Runs containerized services |
Handles arguments, tags, platforms | Manages volumes, networks, env vars |
Great for CI/CD | Ideal for local development |
Excels at matrix builds | Excels at service orchestration |
Use Docker Bake for building.
Use Docker Compose for running.
Together, they make a powerful DevOps duo.
🏁 Final Thoughts
Getting started is simple — just install Docker Desktop 4.38, create a docker-bake.yaml
, and start building smarter!
Until next time,
Happy baking with Docker!