Containerize a Python Microservice

Build a Flask + Redis hit counter app using Docker and Docker Compose.

Introduction

30 Second Summary

When you deploy software at work, you need every developer's machine to run the app the same way. Containers solve this by packaging your code with everything it needs into a single portable unit.

In this project, you will containerize a Python microservice using Docker and Docker Compose. You'll build a hit counter API backed by a Redis database, with both services running in separate containers that talk to each other over a Docker network.

What You'll Build

A hit counter microservice: a Python Flask API connected to Redis that tracks and displays how many times the endpoint has been visited.

By the end of this project, you'll have:

  • A custom Docker image built from a Dockerfile you wrote from scratch.
  • A multi-container application running with Docker Compose, connecting a Flask API to a Redis database.
  • A working understanding of how container networking lets services discover and communicate with each other.
  • Secret Mission: Add health checks and startup dependency ordering so your web service only starts after Redis is confirmed healthy.

Are there any prerequisites?

You should have basic Python knowledge and familiarity with the Linux command line. No Python installation is needed on your machine because everything runs inside containers.

Verify Your Docker Setup

Before writing any code, you need to confirm that your tools are ready to go. Docker Desktop bundles the Docker CLI and Docker Compose into a single install.

In this step, you will verify that Docker is running, create your project folder, and pull your first container image to prove everything works end to end.

In this step, get ready to:
  • Confirm Docker Desktop is running and check your Docker and Compose versions.
  • Create the project directory for the hit counter app.
  • Verify Docker can pull images by running a hello-world container.
Confirm Docker Desktop is running

Docker Desktop must be running before you can use the docker command in your terminal. The Docker daemon (the background process that manages containers) starts automatically when Docker Desktop launches.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Docker Desktop and press Enter to open it.
  • Wait until you see a green icon or the status Engine running in the bottom-left corner of the Docker Desktop window.

What is Docker Desktop?

Docker Desktop is a GUI application that installs and manages the Docker daemon, the Docker CLI, and Docker Compose on your machine.

You interact with Docker through terminal commands, but Docker Desktop handles starting the background engine for you.

  • Open your terminal by pressing Cmd+Space (macOS) or the Windows key (Windows), typing Terminal, and pressing Enter.
  • Check your Docker CLI version by running this command:
docker --version
  • Check your Docker Compose version by running this command:
docker compose version

You should see version numbers printed for both commands.

✔️ I see version numbers for both

Docker and Docker Compose are both ready to go.

ⓧ I see 'command not found' or an error

This means Docker Desktop is not running or not installed correctly.

  • Make sure Docker Desktop is fully open and shows a green "running" status.
  • Close and reopen your terminal after starting Docker Desktop.
  • If Docker Desktop is not installed, download it from docker.com/products/docker-desktop.

Why docker compose instead of docker-compose?

Docker Compose v1 used a separate binary called docker-compose (with a hyphen). Compose v2 is built into the Docker CLI as a subcommand: docker compose (with a space).

Docker Compose v1 is deprecated. Docker Desktop includes Compose v2 as part of the Docker CLI, so you already have it.

Create the project directory

You need a dedicated folder for your hit counter project files.

  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create your project folder and move into it by running these commands:
mkdir hit-counter
cd hit-counter
  • Confirm the folder was created by running:
pwd

You should see a path ending in hit-counter (for example, /Users/yourname/Desktop/hit-counter).

Not seeing hit-counter in the path?

  • Make sure you ran both the mkdir and cd commands.
  • If the folder already exists, just run cd hit-counter to move into it.

help me create my project directory

Verify Docker can pull and run images

The real test is whether Docker can download a container image from the internet and run it. The hello-world image is a tiny test image published by Docker for exactly this purpose.

  • Run the Docker hello-world container by running this command:
docker run hello-world

What does this command do?

  • docker run tells Docker to create and start a new container.
  • hello-world is the name of the image to use. Docker pulls this image from Docker Hub (Docker's public image registry) if it is not already cached locally.
  • The container runs, prints a confirmation message, and then exits.

You should see output that includes the line Hello from Docker! followed by an explanation of what just happened.

✔️ I see 'Hello from Docker!'

Docker is fully working. It pulled the image, created a container, ran the program inside it, and printed the message. You are ready to build your own images.

ⓧ I see a permission denied or connection error

This usually means the Docker daemon is not running or your user does not have permission to access it.

  • Check that Docker Desktop is open and shows the engine as running.
  • Try closing and reopening your terminal.
  • If you are on macOS, Docker Desktop handles permissions for you. Make sure it finished starting up before retrying.

help me fix Docker permission errors

  • Open VS Code by pressing Cmd+Space (macOS) or the Windows key (Windows), typing VS Code, and pressing Enter.
  • In VS Code, click File in the top menu bar.
  • Click Open Folder.
  • Navigate to Desktop, select the hit-counter folder, and click Open.

You should see the empty hit-counter folder open in the VS Code Explorer sidebar.

Your environment is ready. Next up, you will write the Flask application that Docker will package into a container.

Build the Flask Application

Your Docker environment is confirmed working and your project directory is ready. Now it's time to write the application that will run inside your container.

You'll build a hit counter microservice using Flask (a lightweight Python web framework) and Redis (an in-memory data store that keeps track of visit counts). The app itself is simple, but it demonstrates the core pattern of two services talking to each other across containers.

In this step, get ready to:
  • Create a requirements.txt file listing the Python dependencies.
  • Write the app.py hit counter application.
  • Create a .env file with environment configuration.
Create the requirements file

Python projects use a requirements.txt file to list their dependencies and version numbers. Docker will read this file later to install the exact packages your app needs inside the container.

  • In VS Code, hover over the Explorer sidebar and click the New File icon (the page icon with a +).
  • Name the file requirements.txt and press Enter.
  • Paste the following code into the file:
flask==3.1.3
redis==6.4.0

What does this file do?

Each line pins a specific package version. flask==3.1.3 is the web framework that handles HTTP requests. redis==6.4.0 is the Python client library for talking to a Redis server.

Pinning versions ensures your container builds the same way every time, regardless of when you build it.

  • Save requirements.txt by pressing Cmd+S (macOS) or Ctrl+S (Windows).
  • Confirm the file exists by running this command in your terminal:
ls

You should see requirements.txt listed in the output.

Don't see the file?

Make sure your terminal is in the hit-counter directory. Run pwd to check your current location.

Also confirm you saved the file inside the hit-counter folder in VS Code, not a parent directory. help me find where my file was saved

Write the hit counter application

The app.py file is the actual Python application that runs inside your container. It connects to Redis, increments a counter on every visit, and returns the count as JSON.

  • Create a new file in VS Code named app.py using the same New File icon in the Explorer sidebar.
  • Add the imports and Redis connection setup by pasting this code:
import os
from flask import Flask, jsonify
import redis

app = Flask(__name__)

redis_host = os.environ.get("REDIS_HOST", "redis")
redis_port = int(os.environ.get("REDIS_PORT", 6379))

cache = redis.Redis(host=redis_host, port=redis_port, decode_responses=True)

What does this code do?

app = Flask(__name__) creates the Flask web application.

os.environ.get("REDIS_HOST", "redis") reads the Redis hostname from an environment variable, falling back to redis if the variable isn't set. This is how containers find each other on a Docker network.

decode_responses=True tells the Redis client to return strings instead of raw bytes, which makes the data easier to work with.

  • Save app.py.

You won't see a visible change yet. The next section adds the route that handles incoming requests.

  • Below the cache = redis.Redis(...) line, add the home route by pasting this code:

@app.route("/")
def home():
    count = cache.incr("hits")
    return jsonify(
        message="Hello from Docker!",
        visits=count
    )

What does this route do?

cache.incr("hits") increments a key called hits in Redis every time someone visits the / endpoint. If the key doesn't exist yet, Redis creates it starting at 1.

jsonify() converts the response into JSON format, which is the standard for APIs to communicate data.

  • Save app.py.

You won't see a change yet. The final section adds a health check and makes the file runnable.

  • Below the home() function, add the health check route and the startup block by pasting this code:

@app.route("/health")
def health():
    try:
        cache.ping()
        return jsonify(status="healthy"), 200
    except redis.ConnectionError:
        return jsonify(status="unhealthy"), 503


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

What does this code do?

The /health route pings Redis and returns a status code. If Redis responds, the endpoint returns 200 (healthy). If Redis is unreachable, it returns 503 (unhealthy). You'll use this in the Secret Mission to add startup dependency ordering.

The if __name__ == "__main__": block starts the Flask server on port 5000, listening on all network interfaces (0.0.0.0). This is required for traffic from outside the container to reach the app.

  • Save app.py.
  • Confirm your files exist by running:
ls

You should see both app.py and requirements.txt in the output.

Seeing a missing file?

Check that you created both files inside the hit-counter folder, not in a subfolder or parent directory. In VS Code, the Explorer sidebar should show app.py and requirements.txt at the same level.

If you see extra nesting, drag the file up to the root of the hit-counter folder in the sidebar. help me fix my file structure

✔️ Awesome, I've got everything!

Great. Double check you've saved app.py and move on to the next substep.

ⓧ I'd like to double check the full code

Here's the complete app.py file. Compare yours against it line by line:

import os
from flask import Flask, jsonify
import redis

app = Flask(__name__)

redis_host = os.environ.get("REDIS_HOST", "redis")
redis_port = int(os.environ.get("REDIS_PORT", 6379))

cache = redis.Redis(host=redis_host, port=redis_port, decode_responses=True)


@app.route("/")
def home():
    count = cache.incr("hits")
    return jsonify(
        message="Hello from Docker!",
        visits=count
    )


@app.route("/health")
def health():
    try:
        cache.ping()
        return jsonify(status="healthy"), 200
    except redis.ConnectionError:
        return jsonify(status="unhealthy"), 503


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)
Create the environment configuration

A .env file stores configuration values that Docker Compose reads automatically. This keeps settings like port numbers and hostnames out of your code, making the app easier to reconfigure without editing source files.

  • Create a new file in VS Code named .env (note the dot at the start of the filename).
  • Paste the following configuration into the file:
APP_PORT=8000
REDIS_HOST=redis
REDIS_PORT=6379

What do these values mean?

APP_PORT=8000 sets which port on your local machine maps to the container. You'll visit localhost:8000 in your browser to reach the app.

REDIS_HOST=redis tells the Flask app the hostname of the Redis service. Docker Compose creates a network where each service is reachable by its name. Since you'll name the Redis service redis in your Compose file, this value matches.

REDIS_PORT=6379 is the default port Redis listens on.

  • Save .env.
  • Run ls -a in your terminal to confirm all three files exist (the -a flag shows hidden files like .env):
ls -a

You should see app.py, requirements.txt, and .env in the output.

Don't see .env in the list?

Files starting with a dot are hidden by default. Make sure you ran ls -a (with the -a flag), not just ls.

If the file still doesn't appear, check that you named it .env exactly (no extra extension like .env.txt). VS Code sometimes adds extensions automatically. help me find my .env file

Hidden files in VS Code

If .env doesn't appear in the VS Code Explorer sidebar, it may be excluded by default. Open Settings with Cmd+, (macOS) or Ctrl+, (Windows), search for files.exclude, and remove any pattern hiding dotfiles.

Your application code is ready. Next up, you'll write a Dockerfile that packages this app into a container image Docker can run anywhere.

Write the Dockerfile

You have a working Flask app and its dependencies listed. The next challenge is packaging everything into a portable container that runs identically on any machine.

A Dockerfile is your recipe for building a container image. It tells Docker which base environment to start from, what files to include, and how to launch your app.

In this step, get ready to:
  • Create a Dockerfile for the Flask application.
  • Build the Docker image and verify it exists locally.
Create the Dockerfile

A container image is a snapshot of everything your app needs to run: the operating system, language runtime, installed packages, and your code. The Dockerfile describes how to assemble that snapshot layer by layer.

  • In VS Code, create a new file called Dockerfile (no file extension) inside your hit-counter folder.
  • Paste the following code into the file:
# Use a lightweight Python image as the base
FROM python:3.12-slim

# Set the working directory inside the container
WORKDIR /app

# Copy dependency list and install packages
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy the application code into the container
COPY app.py .

# Document which port the app listens on
EXPOSE 5000

# Run the Flask app when the container starts
CMD ["python", "app.py"]

What does each instruction do?

  • FROM python:3.12-slim picks the starting point for your image. This is a minimal Python 3.12 environment built on Debian Linux.
  • WORKDIR /app creates and switches into a /app directory inside the container. All following commands run from here.
  • COPY requirements.txt . copies the dependency file from your machine into the container's working directory.
  • RUN pip install --no-cache-dir -r requirements.txt installs Flask and redis inside the container. The --no-cache-dir flag keeps the image size small by skipping pip's download cache.
  • COPY app.py . adds your application code to the image.
  • EXPOSE 5000 documents that the container listens on port 5000. It does not publish the port to the host by itself.
  • CMD ["python", "app.py"] is the default command that runs when a container starts from this image.

Why copy requirements.txt before app.py?

Docker caches each layer. By copying and installing dependencies first, Docker can reuse that cached layer whenever you change app.py but leave requirements.txt unchanged. This makes rebuilds much faster during development.

  • Save Dockerfile.

✔️ Awesome, I've got everything!

Great. Double check you've saved the file with no extension (not Dockerfile.txt).

ⓧ I'd like to double check the full code

FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY app.py .

EXPOSE 5000

CMD ["python", "app.py"]

VS Code added a .txt extension?

Some editors add a default extension when you create a new file. Make sure the file is named exactly Dockerfile with a capital D and no extension.

In the VS Code Explorer sidebar, right-click the file and select Rename to fix the name if needed.

help me rename my Dockerfile in VS Code

Build the Docker image

With the Dockerfile written, you can now ask Docker to execute each instruction and produce a final image. The docker build command reads your Dockerfile and creates a reusable image from it.

  • Build your Docker image by running this command in your terminal:
docker build -t hit-counter .

What does this command do?

  • docker build tells Docker to read the Dockerfile in the current directory and execute each instruction.
  • -t hit-counter tags the resulting image with the name hit-counter so you can reference it by name later.
  • . (the dot) sets the build context to the current directory. Docker sends all files here into the build process.

The build takes a minute or two the first time because Docker downloads the python:3.12-slim base image and installs your Python packages.

  • Verify your image was built successfully by running:
docker images

You should see hit-counter listed under the REPOSITORY column, with a TAG of latest and a SIZE around 150-200 MB.

Build failed with an error?

Make sure Docker Desktop is running. The Docker daemon must be active for build commands to work.

Check that your terminal is inside the hit-counter folder where the Dockerfile lives. The . in the command points to the current directory.

If you see a pip install error, open requirements.txt and confirm it lists flask==3.1.3 and redis==6.4.0 on separate lines with no typos.

help me fix my Docker build error

Your Flask app is now packaged inside a Docker image that can run anywhere Docker is installed. Next up, you will use Docker Compose to launch this image alongside a Redis container so they can communicate.

Define Services with Docker Compose

You have a working Docker image for your Flask app. The next piece of the puzzle is connecting it to Redis so the hit counter has a database to store visit counts.

Docker Compose lets you define multiple services in a single file and start them together with one command. It also handles the networking between containers automatically, so your Flask app can talk to Redis without any manual configuration.

In this step, get ready to:
  • Create a compose.yaml file that defines your web and Redis services.
  • Start both containers and verify the app is accessible at http://localhost:8000.
Create the compose.yaml file

A Compose file declares all of your services, their configuration, and how they connect to each other. Docker Compose reads this file and creates the full environment for you.

  • In VS Code, create a new file called compose.yaml in your hit-counter folder (the same level as your Dockerfile).
  • Paste the following into compose.yaml:
services:
  web:
    build: .
    ports:
      - "${APP_PORT}:5000"
    environment:
      - REDIS_HOST=${REDIS_HOST}
      - REDIS_PORT=${REDIS_PORT}
    depends_on:
      - redis

  redis:
    image: redis:alpine

What does this file do?

This file defines two services that Docker Compose will run as separate containers on the same network:

  • web builds an image from your local Dockerfile (build: .).
  • ports maps your host machine's port (from APP_PORT in .env) to the container's port 5000, where Flask listens.
  • environment injects REDIS_HOST and REDIS_PORT into the container so your app.py can find Redis.
  • depends_on tells Docker Compose to start the redis container before web.
  • redis uses the official redis:alpine image from Docker Hub. No build step needed.

How does Docker Compose read the .env file?

Docker Compose automatically reads a .env file in the same directory and makes its values available for variable interpolation inside compose.yaml. That is why ${APP_PORT} resolves to 8000 without any extra configuration.

  • Save compose.yaml.
  • Confirm the file exists by running:
ls

You should see compose.yaml listed alongside app.py, Dockerfile, requirements.txt, and .env.

Don't see compose.yaml in the output?

  • Make sure you created the file in the hit-counter folder, not inside a subfolder.
  • Check the filename is exactly compose.yaml with no extra extensions like .txt.

Why isn't my compose.yaml showing up?

✔️ Awesome, I've got everything!

Great. Double check you have saved compose.yaml before moving on.

ⓧ I'd like to double check the full code

Here is the full compose.yaml for comparison:

services:
  web:
    build: .
    ports:
      - "${APP_PORT}:5000"
    environment:
      - REDIS_HOST=${REDIS_HOST}
      - REDIS_PORT=${REDIS_PORT}
    depends_on:
      - redis

  redis:
    image: redis:alpine
Start the full stack with Docker Compose

Your Compose file is ready. One command will build your image, create both containers, wire up their network, and start everything.

  • Start both services by running:
docker compose up

You will see logs streaming from both the web and redis containers. Look for a line from the web service that says Running on http://0.0.0.0:5000. This confirms Flask is up and listening inside the container.

  • Open your browser and go to http://localhost:8000.

You should see a JSON response with a message and a visits count of 1.

Why port 8000 and not 5000?

Flask listens on port 5000 inside the container. The ports mapping in compose.yaml forwards your host's port 8000 (from APP_PORT in .env) to the container's port 5000. So you access the app on localhost:8000 from your machine.

Seeing an error or can't reach localhost:8000?

  • Make sure Docker Desktop is running. Docker Compose requires the Docker daemon to be active.
  • Check that no other app is already using port 8000 on your machine. If something is, change APP_PORT in your .env to another value like 8080, then re-run docker compose up.
  • If you see a Redis connection error in the logs, give it a few seconds. Redis may still be starting up.

My Docker Compose stack won't start or I can't reach my app in the browser.

Your multi-container app is live. Both services are running, connected, and talking to each other over a Docker network you never had to configure manually. Next up, you will explore the running stack and test the hit counter in action.

Test and Explore Your Running Services

Your multi-container stack is alive. Flask and Redis are communicating across a Docker network that Compose created automatically.

Now it's time to prove it works. You'll hit the API endpoint, watch the counter climb, and learn the essential Docker Compose commands for inspecting and managing running containers.

In this step, get ready to:
  • Hit the API endpoint and watch the visits counter increment.
  • Inspect running containers with Docker Compose commands.
  • Stop and remove the full stack cleanly.
Hit the API endpoint multiple times

Your docker compose up command from the last step is still running in your terminal, streaming logs. You need a second terminal to send requests.

  • Open a new terminal tab by pressing Cmd+T (macOS) or Ctrl+Shift+T (Windows).
  • Navigate to your project folder by running this command:
cd ~/Desktop/hit-counter
  • Hit your API endpoint by running this command:
curl http://localhost:8000

You should see a JSON response with a visits count of 1.

What does this response mean?

Your Flask app received the request, told Redis to increment the hits key, and returned the new count. Every piece of this happened inside Docker containers talking to each other over the Compose network.

  • Run the same command a few more times:
curl http://localhost:8000
curl http://localhost:8000
curl http://localhost:8000

Each response shows the visits value climbing: 2, 3, 4. Redis is persisting the count across requests, even though each request is a completely independent HTTP call.

Seeing "Connection refused"?

Make sure docker compose up is still running in your other terminal tab. If you accidentally closed it, switch back and run docker compose up again.

Also confirm the URL uses port 8000 (not 5000). Your .env maps host port 8000 to the container's internal port 5000.

help me debug why curl can't connect to my Docker Compose Flask app

Inspect your running containers

Docker Compose gives you commands to peek inside your running stack without interrupting it. These are the commands you'll use daily when debugging containerized apps.

  • List all running containers in this project by running:
docker compose ps

You should see a table listing both the web and redis services, their status, and port mappings.

What does docker compose ps show?

This command lists every container managed by your compose.yaml. It shows container names, current state (Running/Exited), and which ports are exposed to your host machine.

  • View the logs from both services by running:
docker compose logs

You should see log output from both services, prefixed with the service name. Look for Flask's startup message and Redis's ready message.

What does docker compose logs show?

This displays the combined stdout and stderr output from all containers in your stack. Each line is prefixed with the service name so you can tell which container produced it.

In production, you would use docker compose logs -f to follow logs in real time. For now, the static dump is enough to confirm everything started correctly.

  • Run a command inside the running Redis container by running:
docker compose exec redis redis-cli ping

You should see PONG printed in your terminal. This confirms Redis is alive and responding inside its container.

What does docker compose exec do?

The docker compose exec command runs a one-off command inside a running container. Here you ran redis-cli ping inside the redis service container.

This is useful for debugging. You can exec into any service to check file contents, test connectivity, or run diagnostic tools without rebuilding anything.

Seeing "no container found"?

Make sure you're in the hit-counter directory. Docker Compose uses the directory name to identify which project's containers to target.

Also confirm docker compose up is still running in your other terminal tab.

help me troubleshoot docker compose exec not finding my container

Stop and clean up the stack

When you're done working with your containers, Docker Compose can tear everything down in one command. This stops the containers and removes the network that connected them.

  • Switch to the terminal tab where docker compose up is running.
  • Press Ctrl+C to stop the running containers.
  • Remove the stopped containers and their network by running:
docker compose down

You should see Docker removing both containers and the default network.

What does docker compose down do?

This command stops containers and removes the network. Your source files and Docker image remain intact. You can bring everything back up with docker compose up any time.

  • Confirm nothing is running by checking:
docker compose ps

You should see an empty table with no containers listed. Your stack is fully shut down.

Still seeing containers listed?

Run docker compose down again. If containers persist, try docker compose down --remove-orphans to catch any leftover containers from previous runs.

help me fully stop and remove my Docker Compose containers

You've just completed the full container lifecycle: build, run, test, inspect, and tear down. Next up is an optional challenge that adds production-grade reliability to your stack.

Secret mission

Add Health Checks and Startup Dependencies

Your containers start and stop, but what happens when Redis crashes while Flask is running? Add production-ready health monitoring so Docker can detect failures and manage startup order automatically.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely locally using Docker containers, so there are no ongoing cloud costs. Decide whether to keep your resources running, pause them to come back later, or delete them entirely.

Resources you used:

  • Docker containers (web and redis services).
  • Docker images (custom web image and redis:alpine).
  • Project files (app.py, Dockerfile, compose.yaml, requirements.txt, .env).
  • Docker network created by Compose.

Keep everything running

No action needed. Choose this if you're still actively building or experimenting with your hit counter app.

  • Your containers continue running in the background.
  • Docker Desktop uses some memory while containers are active.
  • You can stop Docker Desktop from the system tray if you want to free up memory without deleting anything.

Pause - I'll come back to this later

Shut down running containers to free up memory, but keep your files and images for next time.

  • Stop the running containers by running this command from your project folder:
  • Your project files remain on your Desktop.
  • Your Docker image stays cached locally, so next time you run docker compose up it starts instantly.
docker compose stop

When you want to resume, navigate to your project folder and run docker compose up again.

Delete - I don't want to use this again

Remove all project resources and start fresh. This removes containers, networks, images, and volumes created by the project.

  • Navigate to your project folder and stop all containers, remove images, and clean up volumes by running:
docker compose down --rmi all -v
  • Delete the project folder from your Desktop by running:

macOS

rm -rf ~/Desktop/hit-counter

Windows

rmdir /s /q %USERPROFILE%\Desktop\hit-counter
  • Confirm the project folder is gone by checking your Desktop.

What about Docker Desktop?

Docker Desktop itself stays installed on your machine. It is useful for future container projects, so there is no reason to uninstall it unless you need the disk space.

That's a Wrap!

That's a Wrap!

Nice work! You just containerized your first microservice architecture with Docker Compose.

Here's what you learned:

  • Built a custom Docker image from a Dockerfile you wrote from scratch.
  • Created a multi-container application with Docker Compose, connecting a Flask API and Redis database over a shared network.
  • Managed the full container lifecycle from build to run, inspect, and tear down using docker compose commands.
  • Added health checks and startup dependency ordering so your web service only starts after Redis is confirmed healthy.

Ready to quiz yourself?