Docker
build optimization
grpcio
pip installation
performance issues

Docker build taking too long when installing grpcio via pip

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Installing grpcio in Docker is fast when pip can download a prebuilt wheel and painfully slow when it has to compile from source. Most "Docker is hanging on grpcio" reports come down to that one difference.

Why grpcio sometimes compiles instead of downloading a wheel

grpcio contains native code. If your image uses a Python version, CPU architecture, or C library combination that has no matching wheel, pip falls back to building the package locally.

That is expensive because it pulls in a C and C++ toolchain and compiles a large dependency tree. In containers, this is even more noticeable because:

  • build CPUs may be limited
  • Docker layer caching may be invalidated often
  • minimal images may be missing build prerequisites
  • network retries can make dependency resolution look slower than it is

The most common trigger is using Alpine Linux. Alpine uses musl instead of glibc, and many Python packages historically had better wheel coverage on Debian or Ubuntu based images. A very new Python release can also trigger source builds until wheels catch up.

A Dockerfile pattern that stays fast

If you want predictable install times, use a base image with broad wheel support and structure the layers so the dependency install can be cached.

dockerfile
1FROM python:3.12-slim
2
3WORKDIR /app
4
5COPY requirements.txt .
6
7RUN python -m pip install --upgrade pip setuptools wheel \
8    && python -m pip install --no-cache-dir -r requirements.txt
9
10COPY . .
11
12CMD ["python", "app.py"]

A matching requirements.txt might look like this:

text
grpcio==1.74.0
protobuf==5.29.3

There are two important details here:

  • 'COPY requirements.txt . happens before copying the full source tree, so Docker can reuse the install layer when application code changes'
  • upgrading pip helps it recognize the newest wheel formats and available binary distributions

How to tell whether you are building from source

You can force pip to require a wheel. That is a quick diagnostic step during local testing:

bash
python -m pip install --only-binary=:all: grpcio

If that command fails, your environment probably does not have a compatible wheel available. In that case, your Docker build will likely compile grpcio unless you change one of these variables:

  • Python version
  • base image family
  • package version
  • target architecture

Practical fixes when builds are slow

The first fix is usually to stop using Alpine unless image size is worth the build complexity. python:slim images are often a better tradeoff for Python services with native dependencies.

If you must stay on a platform that compiles from source, use a multi-stage build so the compiler stays out of the final runtime image:

dockerfile
1FROM python:3.12-slim AS builder
2
3WORKDIR /build
4RUN apt-get update && apt-get install -y build-essential python3-dev
5COPY requirements.txt .
6RUN python -m pip wheel --wheel-dir /wheels -r requirements.txt
7
8FROM python:3.12-slim
9
10WORKDIR /app
11COPY --from=builder /wheels /wheels
12COPY requirements.txt .
13RUN python -m pip install --no-cache-dir --no-index --find-links=/wheels -r requirements.txt
14COPY . .

That does not make compilation free, but it makes rebuilds more predictable and keeps the final image cleaner.

Common Pitfalls

The biggest mistake is copying the full application source before running pip install. That forces Docker to reinstall dependencies every time any source file changes.

Another common issue is pinning a very new Python version while using older package pins. The package may work, but wheels may not exist for that exact combination yet.

It is also easy to blame grpcio when the real issue is an outdated pip. If the installer is too old to understand available wheels, it may compile unnecessarily.

Finally, avoid assuming the smallest base image is always the fastest. Alpine can produce smaller images, but native Python packages often build slower there and require more troubleshooting.

Summary

  • Slow grpcio installs usually mean pip is compiling from source instead of downloading a wheel.
  • Alpine, new Python versions, and unusual architectures are common causes.
  • Use python:slim or another wheel-friendly base image when possible.
  • Copy dependency files before application code so Docker can reuse cached layers.
  • If compilation is unavoidable, use a multi-stage build to isolate the toolchain.

Course illustration
Course illustration

All Rights Reserved.