You're actually injecting your source code using volumes:, not during the image build, and this doesn't honor .dockerignore.

Running a Docker application like this happens in two phases:

  1. You build a reusable image that contains the application runtime, any OS and language-specific library dependencies, and the application code; then
  2. You run a container based on that image.

The .dockerignore file is only considered during the first build phase. In your setup, you don't actually COPY anything in the image beyond the requirements.txt file. Instead, you use volumes: to inject parts of the host system into the container. This happens during the second phase, and ignores .dockerignore.

The approach I'd recommend for this is to skip the volumes:, and instead COPY the required source code in the Dockerfile. You should also generally indicate the default CMD the container will run in the Dockerfile, rather than requiring it it the docker-compose.yml or docker run command.

FROM python:3.9-slim-buster

# Do the OS-level setup _first_ so that it's not repeated
# if Python dependencies change
RUN apt-get update && apt-get install -y ...

WORKDIR /django-app

# Then install Python dependencies
COPY requirements.txt .
RUN pip install -r requirements.txt

# Then copy in the rest of the application
# NOTE: this _does_ honor .dockerignore
COPY . .

# And explain how to run it
ENV PYTHONUNBUFFERED=1
EXPOSE 8000
USER userapp
# consider splitting this into an ENTRYPOINT that waits for the
# the database, runs migrations, and then `exec "$@"` to run the CMD
CMD sleep 7; python manage.py migrate; python manage.py runserver 0.0.0.0:8000

This means, in the docker-compose.yml setup, you don't need volumes:; the application code is already inside the image you built.

version: "3.8"
services:
  app: 
    build: .
    ports: 
      - 8000:8000
    depends_on: 
      - db
    # environment: [PGHOST=db]
    # no volumes: or container_name:

  db:
    image: postgres
    volumes: # do keep for persistent database data
      - ./data:/var/lib/postgresql/data
    environment: 
      - POSTGRES_DB=${DB_NAME}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    # ports: ['5433:5432']

This approach also means you need to docker-compose build a new image when your application changes. This is normal in Docker.

For day-to-day development, a useful approach here can be to run all of the non-application dependencies in Docker, but the application itself outside a container.

# Start the database but not the application
docker-compose up -d db

# Create a virtual environment and set it up
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt

# Set environment variables to point at the Docker database
export PGHOST=localhost PGPORT=5433

# Run the application locally
./manage.py runserver

Doing this requires making the database visible from outside Docker (via ports:), and making the database location configurable (probably via environment variables, set in Compose with environment:).

Answer from David Maze on Stack Overflow
🌐
TestDriven.io
testdriven.io › blog › docker-best-practices
Docker Best Practices for Python Developers | TestDriven.io
February 12, 2024 - You can also help prevent unwanted cache invalidations by using a .dockerignore file to exclude unnecessary files from being added to the Docker build context and the final image.
🌐
GitHub
gist.github.com › KernelA › 04b4d7691f28e264f72e76cfd724d448
.dockerignore example for Python projects · GitHub
.dockerignore example for Python projects. GitHub Gist: instantly share code, notes, and snippets.
Discussions

docker - Should I add Python's pyc files to .dockerignore? - Stack Overflow
I've seen several examples of .dockerignore files for Python projects where *.pyc files and/or __pycache__ folders are ignored: ... Since these files/folders are going to be recreated in the container anyway, I wonder if it's a good practice to do so. More on stackoverflow.com
🌐 stackoverflow.com
Is .dockerignore treated differently using docker compose?
Please clarify: However, when looking inside my container, everything inside my .dockerignore is still prevent such as my migration folders, venv, etc... Fwiw i dont think volume mounts are taken into account with a dockerignore, as it is used for the build context. The volume mount is a runtime thing. Also, as a performance boost, do this: WORKDIR /app COPY requirements.txt . RUN pip ... COPY . . This way your cache for PIP installs is only invalidated when your requirements change and not while doing some coding. Saves you time and some cycles. More on reddit.com
🌐 r/docker
7
1
March 24, 2024
python - Where to put .dockerignore? - Stack Overflow
Consider the following typical python project structure: fooproject - main.py - src/ - test/ - logs/ - Dockerfile - .dockerignore - README.md The .dockerfile should prevent test/ an... More on stackoverflow.com
🌐 stackoverflow.com
docker - What files do you typically put in .dockerignore - Stack Overflow
I am building a Django application with docker. I would like to know for Django or general development work using docker, what files are typically included in the .dockerignore. I am thinking of the More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 2
21

You're actually injecting your source code using volumes:, not during the image build, and this doesn't honor .dockerignore.

Running a Docker application like this happens in two phases:

  1. You build a reusable image that contains the application runtime, any OS and language-specific library dependencies, and the application code; then
  2. You run a container based on that image.

The .dockerignore file is only considered during the first build phase. In your setup, you don't actually COPY anything in the image beyond the requirements.txt file. Instead, you use volumes: to inject parts of the host system into the container. This happens during the second phase, and ignores .dockerignore.

The approach I'd recommend for this is to skip the volumes:, and instead COPY the required source code in the Dockerfile. You should also generally indicate the default CMD the container will run in the Dockerfile, rather than requiring it it the docker-compose.yml or docker run command.

FROM python:3.9-slim-buster

# Do the OS-level setup _first_ so that it's not repeated
# if Python dependencies change
RUN apt-get update && apt-get install -y ...

WORKDIR /django-app

# Then install Python dependencies
COPY requirements.txt .
RUN pip install -r requirements.txt

# Then copy in the rest of the application
# NOTE: this _does_ honor .dockerignore
COPY . .

# And explain how to run it
ENV PYTHONUNBUFFERED=1
EXPOSE 8000
USER userapp
# consider splitting this into an ENTRYPOINT that waits for the
# the database, runs migrations, and then `exec "$@"` to run the CMD
CMD sleep 7; python manage.py migrate; python manage.py runserver 0.0.0.0:8000

This means, in the docker-compose.yml setup, you don't need volumes:; the application code is already inside the image you built.

version: "3.8"
services:
  app: 
    build: .
    ports: 
      - 8000:8000
    depends_on: 
      - db
    # environment: [PGHOST=db]
    # no volumes: or container_name:

  db:
    image: postgres
    volumes: # do keep for persistent database data
      - ./data:/var/lib/postgresql/data
    environment: 
      - POSTGRES_DB=${DB_NAME}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    # ports: ['5433:5432']

This approach also means you need to docker-compose build a new image when your application changes. This is normal in Docker.

For day-to-day development, a useful approach here can be to run all of the non-application dependencies in Docker, but the application itself outside a container.

# Start the database but not the application
docker-compose up -d db

# Create a virtual environment and set it up
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt

# Set environment variables to point at the Docker database
export PGHOST=localhost PGPORT=5433

# Run the application locally
./manage.py runserver

Doing this requires making the database visible from outside Docker (via ports:), and making the database location configurable (probably via environment variables, set in Compose with environment:).

2 of 2
14

That's not actually your case, but in general an additional cause of ".dockerignore not ignoring" is that it applies the filters to whole paths relative to the context dir, not just basenames, so the pattern:

__pycache__
*.pyc

applies only to the docker context's root directory, not to any of subdirectories.

In order to make it recursive, change it to:

**/__pycache__
**/*.pyc
Top answer
1 of 1
22

Yes, it's a recommended practice. There are several reasons:

Reduce the size of the resulting image

In .dockerignore you specify files that won't go to the resulting image, it may be crucial when you're building the smallest image. Roughly speaking the size of bytecode files is equal to the size of actual files. Bytecode files aren't intended for distribution, that's why we usually put them into .gitignore as well.


Cache related problems

In earlier versions of Python 3.x there were several cached related issues:

Python’s scheme for caching bytecode in .pyc files did not work well in environments with multiple Python interpreters. If one interpreter encountered a cached file created by another interpreter, it would recompile the source and overwrite the cached file, thus losing the benefits of caching.

Since Python 3.2 all the cached files prefixed with interpreter version as mymodule.cpython-32.pyc and presented under __pychache__ directory. By the way, starting from Python 3.8 you can even control a directory where the cache will be stored. It may be useful when you're restricting write access to the directory but still want to get benefits of cache usage.

Usually, the cache system works perfectly, but someday something may go wrong. It worth to note that the cached .pyc (lives in the same directory) file will be used instead of the .py file if the .py the file is missing. In practice, it's not a common occurrence, but if some stuff keeps up being "there", thinking about remove cache files is a good point. It may be important when you're experimenting with the cache system in Python or executing scripts in different environments.


Security reasons

Most likely that you don't even need to think about it, but cache files can contain some sort of sensitive information. Due to the current implementation, in .pyc files presented an absolute path to the actual files. There are situations when you don't want to share such information.


It seems that interacting with bytecode files is a quite frequent necessity, for example, django-extensions have appropriate options compile_pyc and clean_pyc.

🌐
.dockerignore
dockerignore.com › dockerignores › languages-python
Python .dockerignore
# ============================... ... CONSIDERATIONS: Security patterns not included (use common/security.dockerignore) # • BEST PRACTICES: Always combine ......
🌐
Medium
medium.com › analytics-vidhya › containerizing-python-flask-application-19faa9db031c
Containerizing python flask application | by Augustas Berneckas | Analytics Vidhya | Medium
April 30, 2021 - Let’s create .dockerignore file and ignore unnecessary files: .idea/ .vscode/ .git/ .venv/ __pycache__/ .gitignore Dockerfile · docker build -t python-demo-app:init .
🌐
Medium
medium.com › @bounouh.fedi › mastering-the-dockerignore-file-boosting-docker-build-efficiency-398719f4a0e1
Mastering the .dockerignore File: Boosting Docker Build Efficiency | by Fedi Bounouh | Medium
November 9, 2024 - In this article, we will dive deep into what a .dockerignore file is, why it’s important, and how to use it effectively with real-life examples.
🌐
Vokal
engineering.vokal.io › Systems › docker.md.html
Docker best practices
The official Docker documentation ... items while also pointing out some Vokal specific practices. You can easily exclude unnecessary files and directories from a Docker image you are building by using a .dockerignore file....
Find elsewhere
🌐
DEV Community
dev.to › francescoxx › dockerize-a-django-application-4fa
Dockerize a Django Application - DEV Community
April 12, 2023 - Note that the best way to do this is to create a virtual environment first, here is a link https://docs.python.org/3/library/venv.html · Let's start the process of containerization for our Python application. ... this file, in a way similar to .gitignore, is to ignore some file when we will copy files inside the Docker image. For example, we don't want the .git folder in our image, so we can populate the .dockerignore file with
🌐
GitHub
github.com › themattrix › python-pypi-template › blob › master › .dockerignore
python-pypi-template/.dockerignore at master · themattrix/python-pypi-template
Template for quickly creating a new Python project and publishing it to PyPI. - python-pypi-template/.dockerignore at master · themattrix/python-pypi-template
Author   themattrix
🌐
TestDriven.io
testdriven.io › tips › 6850ab62-9323-4dca-8ddf-8db1d479accc
Tips and Tricks - Use a .dockerignore File | TestDriven.io
A properly structured .dockerignore file can help: Decrease the size of the Docker image · Speed up the build process · Prevent unnecessary cache invalidation · Prevent leaking secrets · Example: **/.git **/.gitignore **/.vscode **/coverage ...
🌐
Reddit
reddit.com › r/docker › is .dockerignore treated differently using docker compose?
r/docker on Reddit: Is .dockerignore treated differently using docker compose?
March 24, 2024 -

Previously, using a single Dockerfile with it's associated .dockerignore, it worked fine. However, when trying to follow this through with docker compose, it now fails to work. I will provide my structure.

I have uploaded my folder structure to https://imgur.com/65bjhat for easy reading.

My Dockerfile is,

# Use the official Python image as a base image
FROM python:3.9

Prevents Python from writing pyc files to disc (equivalent to python -B option)
ENV PYTHONDONTWRITEBYTECODE 1

Prevents Python from buffering stdout and stderr (equivalent to python -u option)
ENV PYTHONUNBUFFERED 1

WORKDIR /app

COPY . /app/

RUN pip install -r requirements.txt

My .dockerignore is,

venv/*
**/migrations
.dockerignore
Dockerfile
images/*

My docker-compose.yaml is

services:
  web:
    build: ./app
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - ./app:/usr/src/app/
    ports:
      - "8000:8000"
    env_file:
      - ./.dev.env
    depends_on:
      - db
  db:
    image: postgres:16
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    environment:
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=admin
      - POSTGRES_DB=radix_fitness_postgresql_db

volumes:
  postgres_data:

I run this using,

docker compose -f compose-dev.yaml up

However, when looking inside my container, everything inside my .dockerignore is still prevent such as my migration folders, venv, etc...

The only thing I did was switch to docker compose, but it seems to be treated identically as my Dockerfile inside of the app directory should be using the .dockerignore. I wonder if COPY is overriding the behaviour of .dockerignore?

🌐
GeeksforGeeks
geeksforgeeks.org › how-to-use-a-dockerignore-file
How to Use a .dockerignore File? - GeeksforGeeks
April 8, 2024 - It is true that you can also mention the dockerfile inside the .dockerignore file and exclude it from the Docker build context. In fact, it is a common practice than you might have thought.
🌐
Collabnix
collabnix.com › 10-essential-docker-best-practices-for-python-developers-in-2025
Top 10 Docker Best Practices for Python Developers
August 4, 2025 - . RUN chown -R appuser:appuser /app # Switch to non-root user USER appuser CMD ["python", "app.py"] Create a .dockerignore file to prevent sensitive files from being copied into the image: .git .env .env.local __pycache__ *.pyc .pytest_cache .coverage .vscode .idea node_modules README.md Dockerfile ...
🌐
GitHub
github.com › GoogleCloudPlatform › getting-started-python › blob › main › optional-kubernetes-engine › .dockerignore
getting-started-python/optional-kubernetes-engine/.dockerignore at main · GoogleCloudPlatform/getting-started-python
Code samples for using Python on Google Cloud Platform - getting-started-python/optional-kubernetes-engine/.dockerignore at main · GoogleCloudPlatform/getting-started-python
Author   GoogleCloudPlatform
🌐
GitHub
github.com › upenn-libraries › DevOps › blob › master › docker-best-practices › dockerignore.md
DevOps/docker-best-practices/dockerignore.md at master · upenn-libraries/DevOps
Exclude any file or directory not required by the container runtime. Common examples are the .git directory, Dockerfile, .dockerignore, .gitignore, README.md, etc.
Author   upenn-libraries
🌐
CyberPanel
cyberpanel.net › blog › dockerignore-file
Mastering the .dockerignore file for Optimized Docker builds
July 17, 2025 - The .dockerignore is a simple text file Docker uses to tell it which files and directories should not be included in the build context when performing a build of a Docker image. In practice, it works pretty much the same way as a .gitignore in a Git repository, using patterns that match unnecessary files to ensure you only copy over relevant code and assets into your Docker image, which can speed up your builds and shave valuable bytes off your image size.