Understand Dockerfile and Docker Compose responsibilities

Build an application image with a Dockerfile, then describe service configuration and dependencies with Compose.

Best practices
Illustration of container operations and troubleshooting

A Dockerfile describes how to build an image and its default startup behavior. A Compose file describes services, networks, mounts, and other settings for running an application. Compose can also invoke image builds, so the two responsibilities often appear in the same project.

Package the application

For a Python WSGI application with a compatible requirements.txt containing Gunicorn:

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "2", "app:app"]

This assumes the module exposes app:app. Select worker counts and dependency versions for the actual application, add an appropriate non-root user, and exclude secrets and unrelated files with .dockerignore.

RUN executes during the build. CMD supplies a default container command; it does not start the server while building. Binding Gunicorn to 0.0.0.0:8000 allows the mapped container port to reach it instead of relying on its loopback default.

Describe the services

services:
  web:
    build: .
    ports:
      - "127.0.0.1:8000:8000"
    environment:
      DB_HOST: db
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set a database password}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -h 127.0.0.1 -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 10
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:

This illustrates the relationship between build and runtime configuration. The application still needs its actual database name, credentials, and connection logic; DB_HOST alone is not a complete database setup. The password must be supplied before rendering the configuration, and production secret handling should be chosen deliberately.

PostgreSQL 16 uses the shown data path. Check the chosen image version before changing it, especially across major versions. The health check tests TCP acceptance, not successful application authentication or schema readiness. The application must also handle later database failures.

Build and run deliberately

docker compose build
docker compose up -d

Alternatively, docker compose up -d --build requests a build before startup. Compose does not automatically rebuild every image whenever a source file changes. Development bind mounts and watch workflows have separate behavior.

build: points to build configuration. image: identifies a prebuilt image or can name a build result when combined with build; pull/build policy determines how that combination behaves. A Compose application can consist entirely of existing images, with no project Dockerfile. Conversely, a single image can be built and launched with docker build and docker run without Compose.

Defaults versus runtime overrides

Compose command overrides the image's default CMD. It does not automatically replace an existing entrypoint or evaluate shell syntax such as &&. An explicit entrypoint override can skip initialization supplied by the image.

Dockerfile ENV records default environment values in the image. Runtime configuration can override them; do not bake credentials into image layers. A named volume has a lifecycle separate from the image and container, and backup requirements remain even when Compose declares it.

A Dockerfile can contain several build stages, and Compose can manage even a single service. Their roles are more useful distinctions than “one container versus many.”

See Dockerfile reference, Compose build specification, and Compose service configuration.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting