掌握基础镜像制作,让你的容器化部署更高效、更可控。

目录

前言

一、基础概念:什么是基础镜像?

二、使用Dockerfile从现有镜像定制

2.1 创建Ubuntu基础镜像

2.2 以root用户运行

2.3 创建更小的Alpine基础镜像

2.4 构建和测试

2.5 错误解决

2.5.1 软件源问题

2.5.2 下载库包问题

三、使用Docker Commit从容器创建

四、使用debootstrap从头构建最小系统


前言

在Docker容器化实践中,基础镜像是构建应用的基石。虽然Docker Hub提供了丰富的官方镜像,但在企业级开发中,我们经常需要定制自己的基础镜像。为什么?因为我们需要:

  • 📦 统一环境:确保团队使用相同的软件版本

  • 🔒 安全合规:预装安全补丁,移除不必要的组件

  • ⚡ 提升效率:避免重复安装常用工具,加速CI/CD流程

  • 🎯 优化大小:只包含业务必需的最小组件

本文将详细介绍构建基础镜像的方法,从简单到复杂,满足不同场景的需求。


一、基础概念:什么是基础镜像?

基础镜像(Base Image)是Docker镜像的起点,它通常包含:

  • 一个最小的操作系统(如Alpine、Ubuntu)

  • 必要的系统库和工具

  • 配置好的环境变量和工作目录

官方镜像如 ubuntu:22.04alpine:3.18python:3.11-slim 都是常见的基础镜像。

二、使用Dockerfile从现有镜像定制

这是最推荐的方法,易于维护和版本控制。

2.1 创建Ubuntu基础镜像

# Dockerfile.ubuntu
FROM ubuntu:22.04

# 设置环境变量
ENV DEBIAN_FRONTEND=noninteractive \
    TZ=Asia/Shanghai \
    LANG=C.UTF-8

# 更新源并安装基础包
RUN apt-get update && apt-get install -y \
    # 基础工具
    curl \
    wget \
    vim \
    git \
    htop \
    tree \
    # 网络工具
    iputils-ping \
    net-tools \
    dnsutils \
    # 开发工具
    python3 \
    python3-pip \
    python3-venv \
    build-essential \
    # 系统工具
    ca-certificates \
    locales \
    tzdata \
    unzip \
    sudo \ 
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# 设置时区和locale
RUN ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime \
    && dpkg-reconfigure -f noninteractive tzdata \
    && locale-gen en_US.UTF-8

# 创建非root用户并给予sudo权限
RUN useradd -m -s /bin/bash appuser && \
    echo "appuser:appuser" | chpasswd && \
    usermod -aG sudo appuser

# 设置工作目录
WORKDIR /workspace

# 切换到非root用户
USER appuser

# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD curl -f http://localhost/ || exit 1

CMD ["/bin/bash"]

2.2 以root用户运行

如果希望Docker容器直接以root用户运行,Dockerfile可以更简洁。

# Dockerfile.ubuntu
FROM ubuntu:22.04

# 设置环境变量
ENV DEBIAN_FRONTEND=noninteractive \
    TZ=Asia/Shanghai \
    LANG=C.UTF-8

# 更新源并安装基础包
RUN apt-get update && apt-get install -y \
    # 基础工具
    curl \
    wget \
    vim \
    git \
    htop \
    tree \
    # 网络工具
    iputils-ping \
    net-tools \
    dnsutils \
    # 开发工具
    python3 \
    python3-pip \
    python3-venv \
    build-essential \
    # 系统工具
    ca-certificates \
    locales \
    tzdata \
    unzip \
    # 可选:如果需要sudo给其他用户使用,可以安装
    # sudo \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# 设置时区和locale
RUN ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime \
    && dpkg-reconfigure -f noninteractive tzdata \
    && locale-gen en_US.UTF-8

# 设置工作目录
WORKDIR /workspace

# 注意:这里不切换用户,保持默认的root

# 健康检查(可选,根据实际需要)
# HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
#     CMD curl -f http://localhost/ || exit 1

CMD ["/bin/bash"]

2.3 创建更小的Alpine基础镜像

# Dockerfile.alpine
FROM alpine:3.18

# 安装基础包
RUN apk update && apk add --no-cache \
    bash \
    curl \
    wget \
    vim \
    git \
    htop \
    python3 \
    py3-pip \
    build-base \
    tzdata \
    ca-certificates \
    iputils \
    net-tools

# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# 设置bash为默认shell
RUN sed -i 's/ash/bash/g' /etc/passwd

# 创建非root用户
RUN adduser -D -s /bin/bash appuser && \
    echo "appuser:appuser" | chpasswd

WORKDIR /workspace
USER appuser

CMD ["/bin/bash"]

2.4 构建和测试

#!/bin/bash
# build.sh

echo "=== 构建Ubuntu基础镜像 ==="
docker build -t my-base:ubuntu-22.04 -f Dockerfile.ubuntu .

echo "=== 构建Alpine基础镜像 ==="
docker build -t my-base:alpine-3.18 -f Dockerfile.alpine .

echo "=== 查看镜像大小 ==="
docker images my-base:*

echo "=== 测试镜像功能 ==="
docker run --rm my-base:ubuntu-22.04 bash -c "python3 --version && curl --version"
docker run --rm my-base:alpine-3.18 bash -c "python3 --version && curl --version"

2.5 错误解决

2.5.1 软件源问题

如果出现软件源下载问题:

ERROR: failed to build: failed to solve: process "/bin/sh -c apt-get update && apt-get install -y curl wget vim git htop tree iputils-ping net-tools dnsutils python3 python3-pip python3-venv build-essential ca-certificates locales tzdata unzip && apt-get clean && rm -rf /var/lib/apt/lists/*" did not complete successfully: exit code: 100 View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/nfhtzocvel9l6n7wpsk30kjav

使用国内镜像源

FROM ubuntu:24.04

# 设置环境变量
ENV DEBIAN_FRONTEND=noninteractive \
    TZ=Asia/Shanghai \
    LANG=C.UTF-8

# 1. 首先替换为国内镜像源
RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list && \
    sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list

# 2. 更新源并安装基础包
RUN apt-get update && apt-get install -y \
    curl \
    wget \
    vim \
    git \
    htop \
    tree \
    iputils-ping \
    net-tools \
    dnsutils \
    python3 \
    python3-pip \
    python3-venv \
    build-essential \
    ca-certificates \
    locales \
    tzdata \
    unzip \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# ... 其余内容保持不变

使用清华大学源

FROM ubuntu:24.04

ENV DEBIAN_FRONTEND=noninteractive \
    TZ=Asia/Shanghai \
    LANG=C.UTF-8

# 使用清华大学源
RUN sed -i 's@//.*archive.ubuntu.com@//mirrors.tuna.tsinghua.edu.cn@g' /etc/apt/sources.list && \
    sed -i 's@//.*security.ubuntu.com@//mirrors.tuna.tsinghua.edu.cn@g' /etc/apt/sources.list

RUN apt-get update && apt-get install -y \
    # ... 所有包保持不变
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

2.5.2 下载库包问题

error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
    python3-xyz, where xyz is the package you are trying to
    install.
    
    If you wish to install a non-Debian-packaged Python package,
    create a virtual environment using python3 -m venv path/to/venv.
    Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
    sure you have python3-full installed.
    
    If you wish to install a non-Debian packaged Python application,
    it may be easiest to use pipx install xyz, which will manage a
    virtual environment for you. Make sure you have pipx installed.
    
    See /usr/share/doc/python3.12/README.venv for more information.

note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.

在 Ubuntu 24.04(及更高版本)中,系统 Python 默认处于“外部管理环境”模式。这是 Ubuntu 为防止通过 pip 安装的包与系统 apt 包管理器安装的包发生冲突、确保系统稳定而引入的新保护机制。

可以通过创建并使用 Python 虚拟环境,隔离项目依赖。

# 1. 确保安装了 python3-venv(你的Dockerfile中已包含)
# 2. 在项目目录(例如 /workspace)创建虚拟环境
python3 -m venv /workspace/venv

# 3. 激活虚拟环境
source /workspace/venv/bin/activate
# 激活后,命令行提示符前通常会出现 (venv)

# 4. 在虚拟环境中安装 vllm
pip install vllm
# 此时 pip 指向虚拟环境中的 pip,不会触发系统保护

# 5. 使用虚拟环境中的 Python 和 pip 运行你的应用
# /workspace/venv/bin/python your_script.py

# 退出虚拟环境(可选)
# deactivate

三、使用Docker Commit从容器创建

适合快速原型和测试环境。

#!/bin/bash
# create-base-commit.sh

# 1. 启动临时容器
echo "启动基础容器..."
docker run -it --name temp-base ubuntu:22.04 /bin/bash

# 在容器内执行以下命令:
# apt-get update
# apt-get install -y curl wget vim git python3 python3-pip
# apt-get clean
# rm -rf /var/lib/apt/lists/*
# exit

# 2. 提交为新镜像
echo "提交为新镜像..."
docker commit \
    --change="ENV LANG=C.UTF-8" \
    --change="WORKDIR /workspace" \
    --change="CMD ['/bin/bash']" \
    temp-base my-base:commit-$(date +%Y%m%d)

# 3. 清理临时容器
docker rm temp-base

echo "镜像创建完成!"
docker images my-base:commit-*

优点:快速直观
缺点:不可重复,不利于版本控制

四、使用debootstrap从头构建最小系统

适合需要完全控制操作系统组成的场景。

#!/bin/bash
# build-from-scratch.sh

set -e

# 配置参数
ARCH="amd64"
DISTRO="jammy"  # Ubuntu 22.04
MIRROR="http://archive.ubuntu.com/ubuntu"
TARGET_DIR="./ubuntu-rootfs"

echo "=== 步骤1: 安装依赖工具 ==="
sudo apt-get update
sudo apt-get install -y debootstrap qemu-user-static

echo "=== 步骤2: 创建最小Ubuntu系统 ==="
sudo rm -rf $TARGET_DIR
sudo mkdir -p $TARGET_DIR

sudo debootstrap \
    --arch=$ARCH \
    --variant=minbase \
    --include=curl,wget,vim,git,ca-certificates \
    $DISTRO \
    $TARGET_DIR \
    $MIRROR

echo "=== 步骤3: 配置系统 ==="
# 创建基础配置文件
sudo tee $TARGET_DIR/etc/passwd > /dev/null << EOF
root:x:0:0:root:/root:/bin/bash
appuser:x:1000:1000:App User:/home/appuser:/bin/bash
EOF

sudo tee $TARGET_DIR/etc/group > /dev/null << EOF
root:x:0:
appuser:x:1000:
EOF

# 设置主机名
echo "base-container" | sudo tee $TARGET_DIR/etc/hostname

echo "=== 步骤4: 创建Dockerfile ==="
cat > Dockerfile.scratch << EOF
FROM scratch
ADD ubuntu-rootfs.tar /
ENV LANG=C.UTF-8 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
WORKDIR /workspace
CMD ["/bin/bash"]
EOF

echo "=== 步骤5: 打包并导入 ==="
cd $TARGET_DIR
sudo tar --numeric-owner --exclude='./dev/*' --exclude='./proc/*' --exclude='./sys/*' -cf ../ubuntu-rootfs.tar .
cd ..

docker import ubuntu-rootfs.tar my-base:scratch-$(date +%Y%m%d)

echo "=== 步骤6: 清理 ==="
sudo rm -rf $TARGET_DIR ubuntu-rootfs.tar Dockerfile.scratch

echo "=== 构建完成! ==="
docker images my-base:scratch-*

更多推荐