> ## Documentation Index
> Fetch the complete documentation index at: https://felimet-hub.jmcores.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Choosing a Prebuilt Image

> How to judge whether an image is trustworthy, and how to pick between the full, slim, and alpine variants of the official Python image.

export const OptionPicker = ({options = [], lang = "zh", label}) => {
  const t = lang === "en" ? {
    pick: label || "Pick an option to compare",
    rec: "Recommended"
  } : {
    pick: label || "點選項目比較",
    rec: "推薦"
  };
  const opts = Array.isArray(options) ? options : [];
  const [sel, setSel] = useState(0);
  if (opts.length === 0) return null;
  const idx = Math.min(sel, opts.length - 1);
  const cur = opts[idx];
  const css = `
  .op-root{--op-bg:#FAF8F3;--op-surface:rgba(0,0,0,0.025);--op-border:rgba(0,0,0,0.09);--op-text:#2b2722;--op-dim:#6f6a62;--op-faint:#8a8378;--op-accent:#bf7551;border:1px solid var(--op-border);border-radius:14px;background:var(--op-bg);color:var(--op-text);overflow:hidden;}
  .dark .op-root{--op-bg:#1b1a18;--op-surface:rgba(255,255,255,0.03);--op-border:rgba(255,255,255,0.08);--op-text:#e7e3da;--op-dim:#a8a299;--op-faint:#8a8378;--op-accent:#cf8a68;}
  .op-head{padding:12px 16px 11px;border-bottom:1px solid var(--op-border);font-size:12.5px;color:var(--op-dim);display:flex;align-items:center;gap:8px;}
  .op-head-ic{color:var(--op-accent);flex-shrink:0;}
  .op-tabs{display:flex;gap:8px;padding:14px 16px 4px;flex-wrap:wrap;}
  .op-tab{position:relative;flex:1 1 130px;min-width:120px;text-align:left;background:transparent;border:1px solid var(--op-border);border-radius:11px;padding:11px 13px;cursor:pointer;color:inherit;font:inherit;transition:border-color .15s,background .15s,box-shadow .15s;}
  .op-tab:hover{background:var(--op-surface);}
  .op-tab-on{border-color:rgba(191,117,81,.5);background:rgba(191,117,81,.07);box-shadow:0 0 0 3px rgba(191,117,81,.1);}
  .op-tab-name{font-size:14.5px;font-weight:600;line-height:1.3;}
  .op-tab-on .op-tab-name{color:var(--op-accent);}
  .op-badge{display:inline-block;margin-top:6px;font-size:10.5px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;padding:2px 7px;border-radius:20px;background:rgba(191,117,81,.14);color:var(--op-accent);}
  .op-rec{position:absolute;top:10px;right:11px;font-size:10px;font-weight:700;letter-spacing:.3px;text-transform:uppercase;color:var(--op-accent);}
  .op-body{padding:6px 16px 16px;}
  .op-specs{border:1px solid var(--op-border);border-radius:10px;overflow:hidden;margin-bottom:11px;}
  .op-row{display:flex;border-top:1px solid var(--op-border);font-size:13px;}
  .op-row:first-child{border-top:none;}
  .op-k{width:42%;flex-shrink:0;padding:8px 12px;color:var(--op-dim);background:var(--op-surface);}
  .op-v{flex:1 1 0;min-width:0;padding:8px 12px;font-weight:500;}
  .op-note{font-size:13px;line-height:1.6;color:var(--op-dim);padding:0 2px;}
  `;
  return <div className="op-root">
      <style>{css}</style>
      <div className="op-head"><svg className="op-head-ic" xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z" /><path d="m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65" /><path d="m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65" /></svg>{t.pick}</div>
      <div className="op-tabs">
        {opts.map((o, i) => <button key={i} type="button" className={"op-tab" + (i === idx ? " op-tab-on" : "")} onClick={() => setSel(i)}>
            {o.recommend && <span className="op-rec">★ {t.rec}</span>}
            <div className="op-tab-name">{o.name}</div>
            {o.badge && <span className="op-badge">{o.badge}</span>}
          </button>)}
      </div>
      <div className="op-body">
        <div className="op-specs">
          {(cur.specs || []).map((row, i) => <div className="op-row" key={i}>
              <div className="op-k">{row[0]}</div>
              <div className="op-v">{row[1]}</div>
            </div>)}
        </div>
        {cur.note && <div className="op-note">{cur.note}</div>}
      </div>
    </div>;
};

`Image` `Python`

You do not write everything from scratch every time; most of the time you stand on a prebuilt image (`FROM`). Picking one comes down to two things: **trust** and **variant**.

## Trust: three tiers

| Tier                   | How to spot it                                      | Maintainer                                           |
| ---------------------- | --------------------------------------------------- | ---------------------------------------------------- |
| Docker Official Images | No user prefix (`python`, `ubuntu`), official badge | Curated by Docker                                    |
| Verified Publisher     | "Verified Publisher" badge, vendor name in the path | Reviewed commercial vendor                           |
| Community images       | Format `username/image`, no badge                   | Individual users, judged by downloads and reputation |

How to confirm trust is covered in [Docker Hub](/en/notes/docker/guide/hub/).

## Python image variants

Take the official Python image as the example; toggle below to see the differences:

<OptionPicker
  lang="en"
  label="Toggle a variant to compare the official Python image"
  options={[
{
  name: "python:3.12",
  badge: "Full",
  specs: [
    ["Base", "Debian bookworm (with build tools)"],
    ["Compressed size", "~350-400 MB"],
    ["Best for", "Compiling C extensions, scientific computing"],
  ],
  note: "Includes full Debian and build tools: the largest, but least likely to be missing something. Easiest when you need to compile native packages inside the image.",
},
{
  name: "python:3.12-slim",
  badge: "Slim",
  recommend: true,
  specs: [
    ["Base", "Slimmed Debian bookworm"],
    ["Compressed size", "~50-70 MB"],
    ["Best for", "Production default, most web/API services"],
  ],
  note: "The slim version with docs and build tools stripped: the production default. Just apt install build-essential when you need to compile.",
},
{
  name: "python:3.12-alpine",
  badge: "Smallest",
  specs: [
    ["Base", "Alpine (musl libc)"],
    ["Compressed size", "~20-25 MB"],
    ["Best for", "Pure Python, willing to pay compile cost"],
  ],
  note: "The smallest, but musl libc forces many binary wheels (numpy / pandas / scipy, etc.) to fall back to source builds, making builds slow or even larger. Not recommended for scientific or ML packages.",
},
]}
/>

## The Alpine trap

Alpine uses **musl libc** rather than glibc, which causes:

* Prebuilt binary wheels on PyPI (manylinux, targeting glibc) **fall back to source builds** on Alpine, requiring `gcc` / `musl-dev` and each package's C headers in the image, so build time soars and the final image may not be smaller.
* numpy, scipy, pandas, PyTorch, TensorFlow and similar scientific / ML packages need self-compiling or unofficial packages on Alpine: **not recommended**.
* Alpine suits pure Python (no C-extension deps), a hard size requirement, and willingness to accept the compile cost in a multi-stage build.

## Rules of thumb for picking a version

```
Need scientific packages (numpy / pandas / scipy / torch)?
  → Yes → python:3.X (full) or python:3.X-slim + manually install build-essential
  → No  → python:3.X-slim (default)
          └→ Hard size requirement + confirmed no C extensions?
                → Yes → python:3.X-alpine (accept self-compiling)
```

* **Pin a `major.minor` tag** (`python:3.12-slim`), not `latest` or `python:3`.
* **Default to slim**, adding build tools yourself when compiling native packages.
* `bookworm` = Debian 12, `bullseye` = Debian 11; use a codename tag (`python:3.12-slim-bookworm`) to lock the Debian version.

## Next

* [A Python app Dockerfile](/en/notes/docker/dockerfile/python/): writing a real Dockerfile with slim.
* [Layer cache and best practices](/en/notes/docker/dockerfile/caching/): pinning tags, non-root, and more.

Reference: [hub.docker.com/\_/python](https://hub.docker.com/_/python), [Docker Official Images](https://docs.docker.com/trusted-content/official-images/)
