Skip to content

No .dockerignore; web Docker build stage copies entire directory into image build context #27

Open

Description

@jsawyerdev

Summary

There is no .dockerignore file anywhere in the repository, and web/Dockerfile's build stage copies the entire web/ directory into the build context after installing dependencies — so any locally-present secrets or build artifacts on a developer's machine (.env.local, node_modules, .next) get pulled into the image build.

Evidence

  • find . -iname "*.dockerignore" (repo root, web/, server/) returns no results — confirmed no .dockerignore exists anywhere in the repo.
  • web/Dockerfile:1-6:
    FROM node:22-slim AS build
    WORKDIR /app
    COPY web/package.json ./
    RUN npm install
    COPY web/ ./
    RUN npm run build
    COPY web/ ./ copies the entire web/ directory as it exists on the machine running docker build, with nothing excluding .env.local, a stray node_modules/, or .next/ build cache from a prior local npm run dev/npm run build.
  • server/Dockerfile avoids this pattern by copying explicit files only (package.json, tsconfig.json, src/), so this specific gap is scoped to the web image.

Why this matters

Docker image layers are cached and can be exported/inspected even after later layers "remove" a file — anything copied in at this step becomes part of the image's layer history. If a developer builds the image locally while a web/.env.local (holding, e.g., a locally-set API_KEY for testing) or other sensitive local file exists on disk, it gets baked into the built image layer, and could be extracted by anyone with access to that image (e.g., if it's later pushed to a registry).

Attack or failure scenario

A developer runs docker compose up --build locally while web/.env.local (containing a real API_KEY or other local secret) or a stale web/node_modules happens to exist in the working tree. Both get copied into the build stage's layer. If that image is later pushed anywhere (a registry, shared with a teammate, uploaded for a bug report), the secret is now embedded in a distributable artifact rather than confined to the developer's local filesystem.

Root cause

No .dockerignore exists to scope COPY web/ ./ down to only the files actually needed for the build (source, config), so it depends entirely on the local working tree being clean at build time.

Recommended fix

Add a .dockerignore (repo root, applying to the whole build context per docker-compose.yml's context: .) excluding at minimum: node_modules, .next, .env, .env.local, data/, .git. This mirrors the same categories already excluded from version control in .gitignore.

Acceptance criteria

  • A .dockerignore file exists and excludes local env files, node_modules, and build caches from the Docker build context.
  • Rebuilding with a stray web/.env.local present no longer results in that file appearing inside the built image (verifiable with docker run --rm <image> find / -name ".env.local" finding nothing).

Suggested labels

docker, security (neither exists on this repo; recommend bug)

Priority

P3

Severity

Medium — situational (depends on what's present in the local working tree at build time), but a real and easily-fixed gap given the project already treats these same file categories as sensitive in .gitignore.

Confidence

Confirmed — verified no .dockerignore exists anywhere in the repo via find, and read web/Dockerfile's broad COPY web/ ./ directly.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions