为什么我的 .Dockerignore 文件不忽略文件?

Why isn't my .Dockerignore file ignoring files?

我构建容器的时候检查了应该忽略的文件,大部分都没有被忽略。

这是我的文件夹结构

Root/

  data/

  project/
    __pycache__/
    media/
    static/

  app/
    __pycache__/
    migrations/
    templates/

  .dockerignore
  .gitignore
  .env
  docker-compose.yml
  Dockerfile
  requirements.txt
  manage.py

假设我想忽略 __pycache__data(创建容器时将使用 docker-compose up 命令创建数据)文件夹和 .gitignore & .env 个文件。

我将在下一个 .docker忽略 文件

中忽略这些
.git
.gitignore

.docker

*/__pycache__/
**/__pycache__/

.env/
.venv/
venv/

data/

最后的结果是只有git & .env两个文件被忽略了。数据文件夹并未被忽略,但无法从容器中访问它。 __pycache__ 文件夹也没有被忽略。

这是 docker 个文件。

docker-compose.yml

version: "3.8"

services: 

  app: 
    build: .
    volumes: 
      - .:/django-app
    ports: 
      - 8000:8000
    command: /bin/bash -c "sleep 7; python manage.py migrate; python manage.py runserver 0.0.0.0:8000"
    container_name: app-container
    depends_on: 
      - db

  db:
    image: postgres
    volumes:
      - ./data:/var/lib/postgresql/data
    environment: 
      - POSTGRES_DB=${DB_NAME}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    container_name: postgres_db_container

Dockerfile

FROM python:3.9-slim-buster

ENV PYTHONUNBUFFERED=1

WORKDIR /django-app
EXPOSE 8000

COPY requirements.txt requirements.txt

RUN apt-get update \
    && adduser --disabled-password --no-create-home userapp \
    && apt-get -y install libpq-dev \
    && apt-get -y install apt-file \
    && apt-get -y install python3-dev build-essential \
    && pip install -r requirements.txt

USER userapp

您实际上是在使用 volumes: 注入您的源代码,而不是在映像构建期间,这不符合 .dockerignore

运行 像这样的 Docker 应用程序分两个阶段进行:

  1. 您构建了一个可重复使用的映像,其中包含应用程序 运行时间、任何 OS 和特定语言的库依赖项以及应用程序代码;然后
  2. 您 运行 基于该图像的容器。

.dockerignore 文件仅在第一个构建阶段考虑。 在您的设置中,您实际上 COPY 图像中 requirements.txt 文件之外的任何内容。相反,您使用 volumes: 将宿主系统的一部分注入到容器中。这发生在第二阶段,并忽略 .dockerignore.

为此我推荐的方法是跳过 volumes:,而是 COPY Docker 文件中的所需源代码。您通常还应该在 Docker 文件中指明默认的 CMD 容器将 运行,而不是要求它使用 docker-compose.ymldocker run 命令。

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

这意味着,在 docker-compose.yml 设置中,您不需要 volumes:;应用程序代码已经在您构建的映像中。

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']

这种方法还意味着您需要 docker-compose build 在您的应用程序更改时创建新图像。这在 Docker.

中是正常的

对于日常开发,一种有用的方法是 运行 所有非应用程序依赖项都在 Docker 中,但应用程序本身在容器之外。

# 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

这样做需要使数据库从外部可见 Docker(通过 ports:),并使数据库位置可配置(可能通过环境变量,在 Compose with environment: 中设置) .