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
🌐
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.
🌐
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
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
🌐
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
🌐
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 **/.env **/.aws **/.ssh Dockerfile README.md docker-compose.yml **/.DS_Store **/venv **/env ·
🌐
PyPI
pypi.org › project › dockerignore-generate
dockerignore-generate
August 14, 2018 - JavaScript is disabled in your browser. Please enable JavaScript to proceed · A required part of this site couldn’t load. This may be due to a browser extension, network issues, or browser settings. Please check your connection, disable any ad blockers, or try using a different browser
🌐
Codefinity
codefinity.com › courses › v2 › 1b3ab5c8-4816-472a-800a-5504df606754 › b881f527-09f4-4a90-8233-d62037eff3ff › c4cc10a0-4848-463f-9432-bbd883990211
Learn Dockerignore File | Docker for Flask
Docker for Python Developers · Start Learning · Swipe to show menu · Previously, we used the command COPY . . to copy all files from the directory of our project to our container. However, it's not always necessary to copy all files, for example, the venv folder, database files, or files created by your development environment (e.g., .idea). To avoid copying such files, we use a .dockerignore file.
Find elsewhere
🌐
GeeksforGeeks
geeksforgeeks.org › how-to-use-a-dockerignore-file
How to Use a .dockerignore File? - GeeksforGeeks
April 8, 2024 - Now, similar to a .gitignore file that is commonly used when you build Git repositories, a .dockerignore file is used to ignore files and folders when you try to build a Docker Image. You can specify the list of files and directories inside the .dockerignore file. Let's look at an example of .dockerignore file.
🌐
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 ... using a .dockerignore file to exclude unnecessary files from being added to the Docker build context and the final image. More on this here shortly. So, in the above Dockerfile, you should move the COPY sample.py . command to the bottom: FROM python:3.12.2-slim ...
🌐
DEV Community
dev.to › francescoxx › dockerize-a-django-application-4fa
Dockerize a Django Application - DEV Community
April 12, 2023 - RUN pip install -r requirements.txt This will install the python dependencies INSIDE the Docker Image · COPY . . This command will copy all the file and folders (included the Dockerfile) in the Image filesystem. al files and folders included in the .dockerignore file will be ignored
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.

🌐
Sourcegraph
sourcegraph.com › github.com › python-gitlab › python-gitlab › - › blob › .dockerignore
.dockerignore - python-gitlab/python-gitlab - Sourcegraph
January 21, 2022 - Search across 2 million+ open source repositories for free. Powered by Sourcegraph Code Search.
🌐
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 - For example, let’s say you want to ignore all .env files except for .env.production. You can use negation for this: # Ignore all .env files *.env # But include .env.production !.env.production · This gives you the flexibility to fine-tune which files are excluded and which are included in your Docker build context. ... Using a .dockerignore file is one of the easiest ways to optimize your Docker builds.
🌐
Hasura
hasura.io › blog › how-to-write-dockerfiles-for-python-web-apps-6d173842ae1d
How to Write Dockerfiles for Python Web Apps
For the base image, we have used the latest version python:3.6 · During image build, docker takes all files in the context directory. To increase the docker build’s performance, exclude files and directories by adding a .dockerignore file to the context directory.
🌐
GitHub
github.com › armadaplatform › example-python › blob › master › .dockerignore
example-python/.dockerignore at master · armadaplatform/example-python
Contribute to armadaplatform/example-python development by creating an account on GitHub.
Author   armadaplatform
🌐
CyberPanel
cyberpanel.net › blog › dockerignore-file
Mastering the .dockerignore file for Optimized Docker builds
July 17, 2025 - Dot files are usually hidden in Unix-based systems where files whose names start with a dot are not shown. Make sure that you are excluding all the dot files in your .dockerignore file: ... In this example, the .dockerignore file failed to exclude hidden files due to incorrect configuration, leading to a larger build context.
🌐
GitHub
github.com › unit9 › boilerplate-python › blob › master › .dockerignore
boilerplate-python/.dockerignore at master · unit9/boilerplate-python
To make starting new projects fast & easy :). Contribute to unit9/boilerplate-python development by creating an account on GitHub.
Author   unit9