If you’ve ever heard a developer say “just run it in Docker” and had no idea what that actually meant, you’re in exactly the right place. Docker for beginners doesn’t have to be intimidating — at its core, it solves one very relatable problem: getting an app to run the same way on your machine as it does on someone else’s.
Docker packages an application together with everything it needs to run — code, dependencies, system tools, even the exact software versions — into a lightweight, portable unit called a container. Instead of manually installing Python, MySQL, and a dozen other dependencies on your computer, you can describe them once and run them anywhere Docker is installed.
This guide covers the Docker basics every beginner should know: what containers actually are, the core Docker concepts and commands, and how Docker Compose lets you run a multi-part application — like a Flask app connected to a MySQL database — with a single command.
What Is Docker?
Docker is a platform for building, running, and sharing applications inside containers. A container bundles an application with its dependencies so it runs consistently, whether it’s on your laptop, a teammate’s machine, or a production server.
Containers vs. Virtual Machines
If you’ve read about virtual machines, containers might sound familiar — but they solve the same problem differently:
- A virtual machine includes an entire guest operating system, making it heavier and slower to start.
- A container shares the host machine’s operating system kernel and only packages the application and its dependencies, making it much lighter and faster to start — usually in seconds.
Containers trade some of a VM’s isolation for speed and efficiency, which is exactly why they’ve become the standard for running modern web applications.
Core Docker Concepts
A handful of terms show up constantly once you start using Docker:
- Image — a read-only template that defines what goes inside a container (code, dependencies, configuration).
- Container — a running instance of an image.
- Dockerfile — a text file with instructions for building an image.
- Docker Hub — a public registry of ready-made images (like
python,mysql, ornginx) you can build on top of. - Docker Compose — a tool for defining and running multi-container applications with one configuration file.
How to Install Docker
Docker Desktop provides everything you need on Windows and macOS, including Docker Engine, Docker Compose, and a graphical interface for managing containers. On Linux, you can install Docker Engine directly through your distribution’s package manager. Once installed, confirm it’s working:
docker --version
docker run hello-world
If you see a welcome message from the hello-world container, Docker is installed correctly.
Basic Docker Commands Cheat Sheet
| Command | Purpose |
|---|---|
docker run <image> | Run a container from an image |
docker ps | List running containers |
docker ps -a | List all containers, including stopped ones |
docker images | List downloaded images |
docker build -t <name> . | Build an image from a Dockerfile |
docker stop <container> | Stop a running container |
docker rm <container> | Remove a stopped container |
docker rmi <image> | Remove an image |
docker exec -it <container> bash | Open a shell inside a running container |
docker logs <container> | View a container’s output/logs |
What Is Docker Compose?
Most real applications aren’t just one piece — a typical web app needs a server and a database at minimum. Docker Compose lets you define every part of that application in a single docker-compose.yml file, then start the entire stack with one command instead of manually running and connecting each container yourself.
Example: Flask + MySQL with Docker Compose
Let’s put this into practice with a common beginner project: a Flask app that connects to a MySQL database, both running in their own containers.
Project Structure
flask-mysql-app/
├── app.py
├── requirements.txt
├── Dockerfile
└── docker-compose.yml
The Flask App
# app.py
import os
import mysql.connector
from flask import Flask
app = Flask(__name__)
def get_db_connection():
return mysql.connector.connect(
host=os.environ.get("MYSQL_HOST", "localhost"),
user=os.environ.get("MYSQL_USER", "root"),
password=os.environ.get("MYSQL_PASSWORD", ""),
database=os.environ.get("MYSQL_DB", "exampledb"),
)
@app.route("/")
def index():
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute("SELECT VERSION()")
db_version = cursor.fetchone()
cursor.close()
conn.close()
return f"Connected to MySQL version: {db_version[0]}"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
# requirements.txt
flask
mysql-connector-python
Notice that MYSQL_HOST defaults to localhost, but in Docker Compose it will actually be set to db — the name of the MySQL service, which Docker resolves automatically over its internal network.
The Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]
The docker-compose.yml File
services:
web:
build: .
ports:
- "5000:5000"
environment:
MYSQL_HOST: db
MYSQL_USER: root
MYSQL_PASSWORD: examplepass
MYSQL_DB: exampledb
depends_on:
db:
condition: service_healthy
db:
image: mysql:8.0
restart: always
environment:
MYSQL_ROOT_PASSWORD: examplepass
MYSQL_DATABASE: exampledb
ports:
- "3306:3306"
volumes:
- db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 5s
retries: 10
volumes:
db_data:
Why the healthcheck matters: MySQL can take a few seconds to fully start up inside its container. Without the healthcheck and condition: service_healthy, Flask’s container might start and try to connect before MySQL is actually ready — a classic beginner gotcha that looks like a random connection error on the first run.
Running the Project
Start everything with one command from the project folder:
docker compose up --build
Once both containers are running, visit http://localhost:5000 in your browser. You should see a message confirming the Flask app successfully connected to MySQL.
To stop everything:
docker compose down
Add the -v flag (docker compose down -v) if you also want to delete the stored database data.
Common Beginner Mistakes to Avoid
- Forgetting to rebuild after changing the Dockerfile. Use
docker compose up --buildto force a rebuild. - Connecting to
localhostinstead of the service name. Inside Docker Compose, containers reach each other by service name (likedb), notlocalhost. - Skipping the healthcheck on a database service, then wondering why the app fails to connect on the first startup.
- Hardcoding credentials directly in
docker-compose.ymlfor a real project — use an.envfile instead once you move past a learning example.
Conclusion
Docker for beginners boils down to one core idea: package an application and everything it needs into a portable container, so it runs the same way everywhere. From there, Docker Compose extends that idea to multi-part applications — like the Flask and MySQL example in this guide — letting you spin up an entire stack with a single command instead of configuring each piece by hand.
Start by getting comfortable with basic Docker commands and the image-versus-container distinction, then work through a small Compose project like the one here. Once you’ve connected a real app to a real database through Docker Compose, the rest of the Docker ecosystem — multi-service architectures, deployment pipelines, orchestration tools like Kubernetes — becomes a lot less intimidating and a lot more approachable.
