第4章 Docker镜像基础:分层原理、镜像仓库、私有仓库搭建
这一章我们聊聊Docker镜像最核心的东西。说它基础,是因为后面所有质控流程都踩在这些概念上。我见过不少团队镜像越做越大、构建越来越慢,根源就是没吃透分层原理。咱们把底打牢,后面才省心。
4.1 分层原理——镜像为什么这么“轻”
Docker镜像不是一个大文件,而是一堆只读层的堆叠。每层记录文件系统的增量变化。你写一条RUN指令,Docker就会在已有层上面加一层新层。容器启动时,联合挂载(UnionFS)把这些层合并成完整的根文件系统。
这个机制带来了两个好处:
- 复用缓存——层没变,构建时直接用缓存,不用重跑。
- 节省空间——多个镜像共享相同的底层(比如Ubuntu基础层),磁盘上只存一份。
RUN指令之间权衡,太多就合并一下。
每层都是只读的。容器运行时再叠加一层可写层(容器层)。你改文件、删文件都只影响这一层,不影响镜像本身。这就是容器与镜像分离的关键——镜像不变,实例随便改。
来看一个简单的例子,看看分层长什么样:
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3
COPY app.py /app/
CMD ["python3", "/app/app.py"]
这个Dockerfile实际上构建出四层:
- ubuntu:22.04 基础镜像(层1)
- apt-get 安装python3(层2)
- COPY app.py(层3)
- CMD 元数据层(层4,只记录指令,不占空间)
RUN里既装包又删缓存,但忘了清理/var/cache/apt。结果每层都保存了缓存文件,镜像体积翻了一倍。正确做法是apt-get clean在同一层里做。
4.2 镜像仓库——去哪找镜像、怎么推送
镜像仓库就是Docker镜像的存储和分发中心。最常用的是Docker Hub(公共的),但你想想看,企业内部质控环境肯定不能全用公网仓库——延迟、安全、限速都是问题。
仓库的命名规则很简单:<仓库地址>/<用户名>/<镜像名>:<标签>。不加仓库地址就默认Docker Hub。例如:
docker pull ubuntu:22.04
docker pull registry.example.com/qa-team/app:v1.2
第一条是从Docker Hub拉,第二条是从私有仓库拉。我这里强调一下:在质控环境里,一定要给镜像打上明确版本标签,别用latest。我有个项目就因为latest指向了不同时间点的镜像,导致测试环境炸了两次。从那以后,我定了个规矩:所有镜像必须带YYYYMMDD-{build}或vX.Y.Z标签。
常用仓库操作
| 命令 | 说明 |
|---|---|
| docker pull 镜像名 | 拉取镜像 |
| docker push 镜像名 | 推送镜像 |
| docker tag 源镜像 目标镜像 | 给镜像重打标签 |
| docker search 关键词 | 搜索公共镜像 |
| docker login 仓库地址 | 登录仓库 |
4.3 私有仓库搭建——用Harbor给质控环境加把锁
私有仓库在质控场景里是刚需。你想想看:测试镜像、内部工具、合规版本,都不能暴露到公网。我建议用Harbor——这是目前最成熟的企业级镜像仓库。它支持RBAC、镜像漏洞扫描、复制、垃圾回收。
咱们这里只讲快速搭建,够质控团队用就行。Harbor依赖Docker Compose,安装方式如下:
# 下载离线安装包(选最新稳定版)
wget https://github.com/goharbor/harbor/releases/download/v2.9.0/harbor-offline-installer-v2.9.0.tgz
tar -xzf harbor-offline-installer-v2.9.0.tgz
cd harbor
# 复制配置模板并修改
cp harbor.yml.tmpl harbor.yml
# 修改 hostname、端口、管理员密码等
# 比如:
# hostname: registry.qa.internal
# http.port: 8080
# harbor_admin_password: Qa@2024!
# 准备安装
./prepare
# 安装(会启动所有容器)
sudo ./install.sh
insecure-registries。否则会报证书错误。
安装完成后,浏览器访问http://你的主机IP:8080,默认账户admin登录。然后创建项目(比如qa-env),把用户拉入项目,就能推送镜像了:
# 先打标签,注意要包含仓库地址
docker tag nginx:alpine registry.qa.internal/qa-env/nginx:3.2
# 登录
docker login registry.qa.internal
# 推送
docker push registry.qa.internal/qa-env/nginx:3.2
insecure-registries,记得重启Docker服务。我曾经因为忘了重启,排查了半天,发现推送一直报x509错误……重启后就好了。
4.4 本章知识结构
下面这张图把分层原理、公共仓库、私有仓库的关系串起来了。你看一遍就明白:镜像从Dockerfile构建出来,经过分层缓存,可以推送到Docker Hub也能推到内部Harbor,质控流水线再从Harbor拉取进行测试。
4.5 多节点同步与垃圾回收
当质控团队规模大了,一台Harbor可能不够。你要在多个机房部署Harbor实例,通过复制规则同步镜像。Harbor支持两种模式:
- 推模式——主Harbor主动推给备节点
- 拉模式——备节点主动去主节点拉
我建议质控环境用拉模式,因为备节点离线时不影响主节点的写入。配置复制规则在Harbor Web界面的“系统管理→复制管理”里,填上远端仓库地址和项目映射即可。
还有一个容易忽略的点:垃圾回收。镜像删除后,底层数据还在磁盘上,需要手动触发GC:
# 在Harbor主机上执行
docker run --rm -v /data/harbor:/data -v /var/run/docker.sock:/var/run/docker.sock \
goharbor/registry-photon:v2.9.0 garbage-collect /etc/registry/config.yml
好了,这章的内容就这些。记住三点:分层是镜像设计的灵魂,仓库是分发的枢纽,私有仓库是质控的基石。把这几个概念理清了,后面搭建批量质控环境就顺理成章了。