Docker镜像
一、基础入门:理解核心概念
1.1 什么是Docker镜像?
- 定义:一个轻量级、可执行的独立软件包,包含运行某软件所需的所有内容(代码、运行时、库、环境变量、配置文件)。
- 与容器的关系:镜像是静态的模板,容器是镜像的运行实例(可读写层)。
- 分层结构:镜像由多个只读层(Layer)叠加组成,每一层代表一个Dockerfile指令。
1.2 核心概念
- Dockerfile:构建镜像的自动化脚本,包含一系列指令(FROM, RUN, COPY, CMD等)。
- Registry:镜像仓库(如Docker Hub, Harbor, AWS ECR),用于存储和分发镜像。
- Tag :镜像的版本标识(如
nginx:1.21)。 - Base Image :基础镜像,通常是操作系统或语言运行时(如
ubuntu:22.04,node:18-alpine)。
1.3 推荐学习资源
- 官方文档 :Docker Overview(权威、系统)
- 视频教程 :Docker for Beginners(TechWorld with Nana,英文)
- 互动练习 :Play with Docker(在线环境,无需安装,已废弃)
二、镜像构建:从Dockerfile到高效镜像
2.1 Dockerfile最佳实践
- 减少层数 :合并RUN命令(
&&连接),使用.dockerignore排除无用文件。 - 使用多阶段构建:分离构建环境和运行环境,大幅减小镜像体积。
- 选择合适的基础镜像:优先使用Alpine(5MB左右)或slim版本,避免臃肿的完整系统。
- 缓存利用:将变化少的指令(如安装依赖)放在前面,变化多的(如COPY代码)放在后面。
2.2 示例:Node.js应用多阶段构建
dockerfile
# 第一阶段:构建
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# 第二阶段:运行
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/index.js"]
2.3 推荐学习资源
- 官方文档 :Best practices for writing Dockerfiles
- 实战教程 :Dockerfile Optimization Guide(Nginx官方博客)
- 工具 :Dive(分析镜像层大小,优化构建)
三、镜像管理:存储、分发与安全
3.1 镜像仓库操作
- 推送/拉取 :
docker push/pull <image>,需先登录(docker login)。 - 私有仓库:部署Harbor或使用云服务(AWS ECR, Azure Container Registry)。
- 镜像标签 :
docker tag <source> <target>,用于重命名或标记版本。
3.2 镜像安全
- 漏洞扫描 :使用
docker scan(集成Snyk)或Trivy(开源)。 - 签名与验证:Docker Content Trust(DCT)或Notary。
- 最小权限原则 :避免以root运行容器,使用
USER指令。
3.3 推荐学习资源
- 安全工具 :Trivy(快速镜像漏洞扫描)
- 仓库搭建 :Harbor官方文档(企业级镜像仓库)
- 安全实践 :Docker Security Cheat Sheet(OWASP)
四、进阶主题:镜像优化与调试
4.1 镜像体积优化
- Alpine vs Debian:Alpine体积小但兼容性可能差(musl libc),Debian slim是折中方案。
- 清理缓存 :
apt-get clean、npm cache clean --force。 - 压缩工具 :
docker-slim(自动分析并瘦身镜像)。
4.2 镜像调试
- 进入运行中容器 :
docker exec -it <container> sh。 - 查看镜像历史 :
docker history <image>。 - 导出镜像为文件 :
docker save -o <file>.tar <image>(用于离线传输)。
4.3 推荐学习资源
- 优化案例 :Docker Image Size Optimization(Ian Lewis博客)
- 调试工具 :Docker Debug(Docker CLI内置调试)
- 书籍:《Docker Deep Dive》(Nigel Poulton,深度解析镜像层原理)
五、实战项目:从零构建完整镜像
5.1 项目示例1:配置SSH镜像
项目背景:官方下载的centos镜像默认不带ssh,管理起来不方便,自己制作一个带SSH功能的
centos镜像
创建dockerfile
bash
[root@docker ~]# vim centos.ssh.dockerfile
FROM centos:8.4.2105
MAINTAINER Harvy
RUN minorver=8.4.2105 && \
sed -e "s|^mirrorlist=|#mirrorlist=|g" \
-e "s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://mirrors.aliyun.com/centos-vault/$minorver|g" \
-i.bak \
/etc/yum.repos.d/CentOS-*.repo
RUN yum install -y openssh-server
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
RUN echo "root:huawei" | chpasswd
EXPOSE 22
CMD ["/usr/sbin/sshd","-D"]
构建镜像
bash
[root@docker ~]# docker build -t centos:ssh -f centos.ssh.dockerfile .
[+] Building 0.6s (10/10) FINISHED
docker:default
=> [internal] load build definition from centos.ssh.dockerfile
0.0s
=> => transferring dockerfile: 604B
0.0s
=> [internal] load metadata for docker.io/library/centos:8.4.2105
0.0s
=> [internal] load .dockerignore
0.0s
=> => transferring context: 2B
0.0s
=> [1/6] FROM docker.io/library/centos:8.4.2105
0.0s
=> CACHED [2/6] RUN minorver=8.4.2105 && sed -e "s|^mirrorlist=|#mirrorlist=|g"
-e "s|^#baseurl=http://mirror.centos.org/$contentdir/$releasever|baseurl=h 0.0s
=> CACHED [3/6] RUN yum install -y openssh-server
0.0s
=> CACHED [4/6] RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
0.0s
=> [5/6] RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
0.3s
=> [6/6] RUN echo "root:huawei" | chpasswd
0.3s
=> exporting to image
0.0s
=> => exporting layers
0.0s
=> => writing image
sha256:cc138c4d3c36fe82eab32dd80549707c8bfe99ddcb6d3882319a10283bb1a864
0.0s
=> => naming to docker.io/library/centos:ssh
查看现象
bash
[root@docker ~]# docker history centos:ssh
IMAGE CREATED CREATED BY
SIZE COMMENT
cc138c4d3c36 36 seconds ago CMD ["/usr/sbin/sshd" "-D"]
0B buildkit.dockerfile.v0
<missing> 36 seconds ago EXPOSE map[22/tcp:{}]
0B buildkit.dockerfile.v0
<missing> 36 seconds ago RUN /bin/sh -c echo "root:huawei" | chpasswd...
1.77kB buildkit.dockerfile.v0
<missing> 36 seconds ago RUN /bin/sh -c ssh-keygen -t ecdsa -f /etc/s...
695B buildkit.dockerfile.v0
<missing> 47 minutes ago RUN /bin/sh -c ssh-keygen -t rsa -f /etc/ssh...
3.18kB buildkit.dockerfile.v0
<missing> 47 minutes ago RUN /bin/sh -c yum install -y openssh-server...
51.9MB buildkit.dockerfile.v0
<missing> About an hour ago RUN /bin/sh -c minorver=8.4.2105 && sed -e "...
17.6kB buildkit.dockerfile.v0
<missing> About an hour ago MAINTAINER Harvy
0B buildkit.dockerfile.v0
<missing> 3 years ago /bin/sh -c #(nop) CMD ["/bin/bash"]
0B
<missing> 3 years ago /bin/sh -c #(nop) LABEL org.label-schema.sc...
0B
<missing> 3 years ago /bin/sh -c #(nop) ADD file:805cb5e15fb6e0bb0...
231MB
测试
bash
#基于刚才dockerfile创建的镜像centos:ssh创建容器sshtest
[root@docker ~]# docker run -d -p 2022:22 --name sshtest centos:ssh
73d963d15407a1e73097540bb320b9edf05b468001bd707abf01bc7be5e54bcb
#创建出来的容器
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
73d963d15407 centos:ssh "/usr/sbin/sshd -D" 6 seconds ago Up 5 seconds
0.0.0.0:2022->22/tcp, :::2022->22/tcp sshtest
#ssh登录容器测试ssh,能够成功登录
[root@docker ~]# ssh root@localhost -p 2022
The authenticity of host '[localhost]:2022 ([::1]:2022)' can't be established.
ECDSA key fingerprint is SHA256:z1owYLOuClnbPrZwXxgy1jcItQT1k+QX6LxosydT64A.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[localhost]:2022' (ECDSA) to the list of known hosts.
root@localhost's password:
"System is booting up. Unprivileged users are not permitted to log in yet. Please
come back later. For technical details, see pam_nologin(8)."
[root@73d963d15407 ~]#
5.2 项目示例2:自定义httpd镜像
创建dockerfile
bash
# 提前在工作目录下创建index.html
[root@docker ~]# vim httpd.dockerfile
FROM centos:8.4.2105
MAINTAINER gaoqiaodong
RUN minorver=8.4.2105 \
&& sed -e "s|^mirrorlist=|#mirrorlist=|g" -e
"s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://m
irrors.aliyun.com/centos-vault/$minorver|g" -i.bak /etc/yum.repos.d/CentOS-*.repo
RUN yum install -y httpd && yum clean all && rm -rf /var/cache/yum
COPY index.html /var/www/html/
EXPOSE 80
CMD ["/usr/sbin/httpd", "-DFOREGROUND"]
构建镜像
bash
[root@docker ~]# docker build -t httpd:centos -f httpd.dockerfile .
查看现象
bash
[root@docker ~]# docker history httpd:centos
测试
bash
#基于刚才dockerfile创建的镜像httpd:centos创建容器myweb
[root@docker ~]# docker run -d -p 80:80 --name myweb httpd:centos
1e0b0631cf708bcc0a162d56b936a12cd06c9bcdebcc2594b23c2fbee3ed8894
#创建出来的容器
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
1e0b0631cf70 httpd:centos "/usr/sbin/httpd -DF..." About a minute ago Up
About a minute 0.0.0.0:80->80/tcp, :::80->80/tcp myweb
#访问测试

5.3 推荐学习资源
- 项目模板 :Docker官方示例(多服务编排)
- CI/CD集成 :GitHub Actions构建镜像
- 课程 :Docker Mastery(Udemy,含镜像构建实战)
六、常见问题与故障排查
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 镜像体积过大 | 未使用多阶段构建或基础镜像过大 | 改用Alpine/slim,合并RUN命令 |
| 构建缓存失效 | COPY代码层变化导致后续层全部重建 | 先COPY依赖文件,再COPY源码 |
| 容器启动失败 | CMD/ENTRYPOINT路径错误或缺少依赖 | 使用docker logs查看错误日志 |
| 镜像漏洞多 | 基础镜像未更新或包含未使用组件 | 定期扫描,使用最小化基础镜像 |
七、学习路径总结
- 第1周 :理解镜像分层原理,掌握
docker build、docker pull等基础命令。 - 第2周:编写Dockerfile,实践多阶段构建和体积优化。
- 第3周:学习镜像仓库操作(推送/拉取),部署私有仓库。
- 第4周:集成安全扫描(Trivy),学习镜像签名和验证。
- 第5周:参与开源项目或自建项目,将镜像构建集成到CI/CD流水线。
八、推荐工具与资源汇总
- 学习平台:Docker官方文档、Play with Docker(已废弃)、Katacoda(已停更,但仍有存档)。
- 书籍:《Docker in Action》(第二版)、《The Docker Book》。
- 社区:Docker官方论坛、Reddit r/docker、Stack Overflow。
- 监控工具:Docker Desktop Dashboard、Portainer(可视化管理)。