JustToThePoint English Website Version
JustToThePoint en español

Docker Compose: Simplifying Container Orchestration

You have enemies? Good. That means you’ve stood up for something, sometime in your life, Winston Churchill

image info

Docker is a powerful software platform designed to make it easier to create, deploy, and run applications by using containers. It offers OS-level virtualization to deliver software in packages called containers. Containers are lightweight, portable, and self-sufficient, which makes them an excellent choice for developing and deploying applications across various environments.

Docker compose

Docker compose is a tool for defining and running multi-container Docker applications. Using a declarative YAML configuration file (docker-compose.yml), you can manage interconnected services, networks, and volumes with a single command.

It offers several advantages:

  1. Your entire setup is documented in a single YAML file, making it easy to create, edit, maintain, and share.
  2. Easy Resource Management: Configure memory limits, GPU access, and networking settings all in one place, simplifying the management of resources.
  3. Service Orchestration: Run multiple interconnected containers (e.g., a web UI with a backend service) effortlessly, ensuring smooth communication between services.
  4. Simplified Commands: Use straightforward commands to start, stop, and rebuild your entire setup, streamlining your workflow and reducing unnecessarily complexity.

Installation

# Official installation method (no Python dependencies required)
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# Verify installation
docker-compose --version

Managing Containers

# List all running containers
docker ps

# List all containers, both running and stopped
docker ps -a

# Remove specific container
docker rm IdContainer # e.g., docker rm a3b0e1c2f2

# Remove all stopped containers
docker container prune

# Remove stopped containers + unused networks/images
docker system prune

Container Operations

# Start a stopped Docker container
docker start IdContainer

# Start a container in interactive mode
docker run -it --rm ubuntu /bin/bash

# Start all services. The -d flag runs the container in detached mode (background).
docker-compose up -d

# Stop services
docker-compose down

# View logs
docker-compose logs -f web

# Scale a service
docker-compose up -d --scale web=3

Set up an Nginx web server and a PostgreSQL database

Our docker-compose.yml sets up nginx to serve static files from ./html on our host, mapped to /usr/share/nginx/html in the container. However, Docker will not create an index.html for you —it only serves what exists in your mapped ./html directory,

# Create the directory and index file on your host
nmaximo7@ubuntupluckyvm:~/containers$ mkdir -p html
nmaximo7@ubuntupluckyvm:~/containers$ sudo chown nmaximo7:nmaximo7 html
nmaximo7@ubuntupluckyvm:~/containers$ sudo echo '<h1>Hello from Docker Nginx!</h1>' > html/index.html
version: '3.8'  # Specify the version of Docker Compose being used
# Always specify image versions (avoid latest)

services:  # Define the services that will be run
  web:  # Service for the web application
    image: nginx:alpine  # Use the lightweight Alpine version of Nginx
    ports:  # Map ports from the host to the container
      - "80:80"  # Expose port 80 on the host and map it to port 80 on the container
    volumes:  # Define volume mounts for the container
      - ./html:/usr/share/nginx/html  # Mount the local 'html' directory to the Nginx HTML directory

  db:  # Service for the database
    image: postgres:15  # Use PostgreSQL version 15
    environment:  # Set environment variables for the container
      POSTGRES_PASSWORD: example  # Set the password for the default PostgreSQL user
    volumes:  # Define volume mounts for persistent data storage
      - db-data:/var/lib/postgresql/data  # Mount the 'db-data' volume to store database data

volumes:  # Define named volumes
  db-data:  # This volume will persist data for the PostgreSQL service

Start all services docker compose up -d, visit localhost or your Docker host’s IP, and see your custom HTML.

Ollama Docker Compose YAML file

This configuration sets up both the Ollama model server and its associated web UI.

services: # Define the services that will be run
  ollama:  # Service for the Ollama model server
    image: ollama/ollama:latest  # Use the latest, official Ollama image
    container_name: ollama # Name of the container
    ports: # Map ports from the host to the container
      - "11434:11434"
      # Expose port 11434 on the host and map it to port 11434 on the container to allow API access
    volumes:
    # Define volume mounts for persistent data (i.e. Ollama models) storage
      - ollama_data:/root/.ollama  # Mount the 'ollama_data' volume to store Ollama data
    environment:  # Set environment variables for the container (enable better performance)
      - OLLAMA_NUM_PARALLEL=2 # Limits how many parallel requests each model can handle
      - OLLAMA_MAX_LOADED_MODELS=3  # Limits how many models can be loaded simultaneously to 3
    restart: unless-stopped  # Restart the container unless it is explicitly stopped

  webui: # Service for Web UI, one of the most popular Ollama web UI.
    image: ghcr.io/ollama-webui/ollama-webui:main  # Use the main branch of the Ollama web UI image
    container_name: ollama-webui # Name of the container
    ports: # Map ports from the host to the container
      - "3000:8080" # Expose port 3000 on the host and map it to port 8080 on the container
    depends_on:  # Ensure the 'ollama' service starts before this service
      - ollama
    environment:  # Set environment variables for the container
      - OLLAMA_API_BASE_URL=http://ollama:11434/api  # Set the base URL for the API to communicate with the Ollama service
    restart: unless-stopped  # Restart the container unless it is explicitly stopped

volumes:  # Define named volumes
  ollama_data:  # Persistent storage for Ollama data
    name: ollama_data  # Name of the volume

Start all services: docker-compose up -d, and use the Ollama CLI through Docker (docker exec -it ollama ollama pull llama3.2) or via web accessible at [http://] + localhost + [:3000].

image info

Building a simple Flask web app with compose

  1. Create a new directory for your project (e.g., myflask) and navigate to it: mkdir myflask,cd myflask. This directory will contain all your project files.

  2. Create a new file named Dockerfile with the following content:

    # This line specifies the base image to use. Here, it’s the official Python image with version 3.12.
    FROM python:3.12
    # Sets the working directory inside the container to /app.
    # All subsequent commands will be run in this directory.
    WORKDIR /app
    # Copies the requirements.txt file (Python app dependencies, e.g., flask) from the local directory to the container’s working directory.
    COPY requirements.txt .
    # Installs the Python packages specified in requirements.txt.
    RUN pip install -r requirements.txt
    # Copies all files from the local directory to the container’s working directory
    COPY . .
    #  CMD specifies the command to run when the container starts.
    # In this case, it runs the app.py file.
    CMD ["python", "app.py"]
    
  3. Create a requirements.txt file with the following content: flask. This file lists the Python packages our application depends on. Flask is a lightweight WSGI web application framework. It is designed to make getting started quick and easy, with the ability to scale up to complex applications.

  4. Create an app.py Python file with a very basic Flask application.

    from flask import Flask
    # Imports the Flask class from the Flask module.
    import random
    
    app = Flask(__name__)
    # Creates an instance of the Flask class.
    
    def get_random_quote():
    """
    Returns a random tech/programming quote.
    No external API needed - uses a predefined list.
    """
    quotes = [
        "Code is like humor. When you have to explain it, it's bad.",
        "First, solve the problem. Then, write the code.",
        "The best error message is the one that never shows up.",
        "Programs must be written for people to read, and only incidentally for machines to execute.",
        "Any fool can write code that a computer can understand. Good programmers write code that humans can understand.",
        "The most important property of a program is whether it accomplishes the intention of its user.",
        "Simplicity is the ultimate sophistication.",
        "Code never lies, comments sometimes do.",
        "Programming is not about typing, it's about thinking.",
        "The computer was born to solve problems that did not exist before."
    ]
    
    return "Hello, World! My quote: " + get_random_quote()
    
    # Defines the route for the root URL. When accessed, it will call the hello function.
    @app.route("/")
    def hello():
        """This function returns Hello, World! when the root URL is accessed."""
        return "Hello, World!"
    
    if __name__ == "__main__":
        # Ensures that the application runs only if the script is executed directly.
        app.run(host="0.0.0.0", port=5000)
        # Runs the application on all available IP addresses on port 5000,...
        # making it accessible from outside the container.
    
  5. Build the Docker Image: docker build -t flask-app . This command builds a Docker image from the Dockerfile in the current directory (.). The -t flask-app flag tags the image with the name flask-app, making it easier to reference later.

  6. Run the Docker Container: docker run -p 5000:5000 flask-app. This command runs a new container based on the flask-app image. The -p 5000:5000 option maps port 5000 on your host machine to port 5000 in the container, allowing you to access the Flask application from your browser.

  7. Access the Application. Open your favorite web browser and navigate to [http://] + localhost + [:5000]. You should be able to see the message “Hello, World!” displayed on the page.

  8. Using Docker Compose. Adopting Docker Compose streamlines the process of managing your application. Instead of executing multiple and lengthier commands to build and run your container, you can simply use docker-compose up -d to access our app now. Create and Edit the Docker Compose File: vim docker-compose.yml

    version: '3' # Specify the version of Docker Compose
    
    services: # This docker-compose.yml file defines a single service named web that builds the Flask application from the current directory.
      web: # Service for the web application
        build: '.' # Build the Docker image using the current directory (where the Dockerfile is located)
        ports: # Map ports from the host to the container
          - '5000:5000' # Expose port 5000 on the host and map it to port 5000 on the container
    

image info

There is a common issue when developing with Docker Compose: changes to your application code (like app.py) aren't being reflected in the running container after rebuilding the image or restarting with docker-compose up -d. When you build your Docker image using docker build -t flask-app ., Docker uses a caching mechanism.

# Stop and remove previous containers
docker-compose down
# --build: This flag tells docker-compose up to explicitly rebuild the images for the services defined in docker-compose.yml before starting the containers.
docker-compose up -d --build
Bitcoin donation

JustToThePoint Copyright © 2011 - 2025 Anawim. ALL RIGHTS RESERVED. Bilingual e-books, articles, and videos to help your child and your entire family succeed, develop a healthy lifestyle, and have a lot of fun. Social Issues, Join us.

This website uses cookies to improve your navigation experience.
By continuing, you are consenting to our use of cookies, in accordance with our Cookies Policy and Website Terms and Conditions of use.