Use pip's only-deps option. It takes the dependencies of the requirements you provide and installs them, without installing those requirements themselves. That lets a container build cache a dependency layer and add your own code afterwards, but it does not add hash checking or review on its own.
What the option does
The pip install reference describes it: take only the dependencies of the provided requirements into account, not the requirements themselves. It cannot be combined with the no-deps option, a dependency group, a requirements file, or the requirements from script option. Requirements you supply are not handled, even if they were dependencies of other requirements you supplied. The environment variable is PIP_ONLY_DEPS.
A typical use is a project directory:
python -m pip install --only-deps .
Pip resolves the dependencies declared by the project in the current directory and installs them, leaving the project itself out.
Why people use it in containers
Container builds cache layers. If your dependency list rarely changes but your source changes constantly, you want dependencies in an early layer that stays cached. Installing the project itself in the same step would invalidate the layer on every code change.
A common shape:
- Copy only the project metadata file into the image.
- Run the dependency install. This layer stays cached while dependencies are unchanged.
- Copy the source.
- Install the project with dependencies disabled, as the pip secure installs guide recommends.
Where security can slip
The convenience has a catch. The option resolves from the project's declared dependencies, which are often ranges, not pins. Each time the layer is rebuilt without cache, you may get newer versions. That gives you three problems:
| Problem | Result |
|---|---|
| Declared ranges, not pins | Different versions on each uncached build |
| No hashes in play | Nothing checks the files that arrive |
| Hidden cache | An old layer can keep a version that has since been flagged |
Use only-deps for layer structure, not as your pinning strategy. Pin first. Pip's lock command can produce a resolved file, and a requirements file with hashes remains the stronger control. See can pip create a lock file and make pip installs in a Dockerfile repeatable.
A safer pattern
- Generate a pinned and hashed requirements file in CI, and commit it.
- In the Dockerfile, install from that file in hash-checking mode, in its own cached layer.
- Install your project last with the no-deps option.
- Use the only-deps route only for local convenience, where a quick resolve is the goal.
Notice that when you rely on a hashed requirements file, you do not need only-deps at all. The file already lists exactly what to install.
Rebuild on a schedule
Layer caching is also a security concern. A cached dependency layer can hide a vulnerable version for months. Rebuild with no cache on a schedule, and rescan the image so a stale layer does not sit unnoticed.
Safeguard's container image scanning and dependency scanning can check what a built image contains, and its continuous monitoring flags new advisories against components you already shipped. A free scan is available at gold.safeguard.sh/scan.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how packages inside an image layer are reported.
Quick check
Can I combine only-deps with a requirements file?
The pip reference says it cannot be used with the requirement option, so use it with a project path or package specifiers.
Does only-deps pin versions?
No. It installs what resolution picks from declared ranges. Pin and hash separately.
Sources
Last reviewed: 19 October 2026.