Docker 镜像管理
核心知识点
1. 镜像基础概念
1.1 镜像结构
Docker 镜像采用分层存储结构,每一层都是只读的:
┌─────────────────────────────────────┐
│ 可写容器层 │
├─────────────────────────────────────┤
│ 镜像层 4 (应用层) │
├─────────────────────────────────────┤
│ 镜像层 3 (依赖层) │
├─────────────────────────────────────┤
│ 镜像层 2 (运行时层) │
├─────────────────────────────────────┤
│ 镜像层 1 (基础层) │
├─────────────────────────────────────┤
│ 镜像层 0 (Bootfs) │
└─────────────────────────────────────┘1.2 镜像标签
镜像标签用于标识镜像的不同版本:
# 格式:仓库名:标签
nginx:latest # 最新版本
nginx:1.21 # 指定主版本
nginx:1.21.6 # 指定完整版本
nginx:alpine # 使用 Alpine 基础镜像
myregistry.com/myapp:v1.0 # 私有仓库镜像2. 镜像搜索与拉取
2.1 搜索镜像
# 搜索 Nginx 镜像
docker search nginx
# 搜索并限制结果数量
docker search --limit 5 nginx
# 搜索官方镜像
docker search --filter is-official=true nginx
# 搜索自动化构建的镜像
docker search --filter is-automated=true nginx
# 搜索特定星数的镜像
docker search --filter stars=100 nginx2.2 拉取镜像
# 拉取最新版本
docker pull nginx
# 拉取指定版本
docker pull nginx:1.21.6
# 拉取所有标签
docker pull --all-tags nginx
# 拉取私有仓库镜像
docker pull myregistry.com/myapp:v1.03. 镜像查看与管理
3.1 查看镜像列表
# 查看所有镜像
docker images
# 查看镜像摘要
docker images --digests
# 查看镜像详细信息
docker image inspect nginx:latest
# 格式化输出
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"3.2 镜像历史与层级
# 查看镜像构建历史
docker history nginx:latest
# 查看镜像层级
docker image inspect nginx:latest | jq '.[0].RootFS.Layers'4. 镜像构建
4.1 Dockerfile 基础
Dockerfile 是用于构建 Docker 镜像的文本文件:
# 基础镜像
FROM ubuntu:20.04
# 维护者信息
LABEL maintainer="your-email@example.com"
# 设置工作目录
WORKDIR /app
# 复制文件
COPY . /app
# 安装依赖
RUN apt-get update && \
apt-get install -y python3 python3-pip && \
pip3 install flask
# 暴露端口
EXPOSE 5000
# 设置环境变量
ENV FLASK_APP=app.py
ENV FLASK_ENV=production
# 运行命令
CMD ["python3", "app.py"]4.2 常用 Dockerfile 指令
# FROM: 指定基础镜像
FROM ubuntu:20.04
# LABEL: 添加元数据
LABEL version="1.0" \
description="My custom image"
# RUN: 执行命令
RUN apt-get update && apt-get install -y nginx
# CMD: 容器启动时执行的命令
CMD ["nginx", "-g", "daemon off;"]
# ENTRYPOINT: 容器启动入口点
ENTRYPOINT ["/entrypoint.sh"]
# COPY: 复制文件到镜像
COPY index.html /usr/share/nginx/html/
# ADD: 复制文件并支持自动解压
ADD app.tar.gz /app/
# ENV: 设置环境变量
ENV APP_ENV=production
# ARG: 构建参数
ARG VERSION=1.0
ENV APP_VERSION=$VERSION
# EXPOSE: 声明暴露端口
EXPOSE 80 443
# VOLUME: 创建挂载点
VOLUME ["/data"]
# USER: 指定运行用户
USER nginx
# WORKDIR: 设置工作目录
WORKDIR /app
# HEALTHCHECK: 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost/ || exit 1
# ONBUILD: 触发器指令
ONBUILD COPY . /app5. 镜像优化
5.1 多阶段构建
多阶段构建可以减小最终镜像大小:
# 构建阶段
FROM node:16-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 运行阶段
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]5.2 镜像层优化
# 不好的写法:创建多个层
RUN apt-get update
RUN apt-get install -y nginx
RUN apt-get clean
# 好的写法:合并为一个层
RUN apt-get update && \
apt-get install -y nginx && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*5.3 使用 Alpine 基础镜像
# 使用 Ubuntu 基础镜像(约 70MB)
FROM ubuntu:20.04
# 使用 Alpine 基础镜像(约 5MB)
FROM alpine:3.146. 镜像导出与导入
6.1 导出镜像
# 导出镜像为 tar 文件
docker save -o myapp.tar myapp:v1.0
# 导出多个镜像
docker save -o images.tar nginx:latest redis:latest
# 使用 gzip 压缩
docker save myapp:v1.0 | gzip > myapp.tar.gz6.2 导入镜像
# 从 tar 文件导入
docker load -i myapp.tar
# 从压缩文件导入
docker load < myapp.tar.gz
# 从标准输入导入
docker load < images.tar7. 镜像删除
7.1 删除单个镜像
# 删除指定镜像
docker rmi nginx:latest
# 强制删除(即使有容器在使用)
docker rmi -f nginx:latest
# 删除多个镜像
docker rmi nginx:latest redis:latest7.2 批量删除镜像
# 删除所有未使用的镜像
docker image prune
# 删除所有未使用的镜像(包括未标记的)
docker image prune -a
# 删除所有悬空镜像
docker rmi $(docker images -f "dangling=true" -q)
# 按模式删除镜像
docker rmi $(docker images | grep "myapp" | awk '{print $3}')实用案例分析
案例 1:构建 Node.js 应用镜像
场景描述
将一个简单的 Node.js Web 应用打包为 Docker 镜像。
项目结构
my-node-app/
├── app.js
├── package.json
└── Dockerfile操作步骤
# 1. 创建项目目录
mkdir ~/my-node-app
cd ~/my-node-app
# 2. 创建 package.json
cat > package.json << 'EOF'
{
"name": "my-node-app",
"version": "1.0.0",
"description": "Simple Node.js app",
"main": "app.js",
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "^4.18.0"
}
}
EOF
# 3. 创建 app.js
cat > app.js << 'EOF'
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('Hello from Docker!');
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
EOF
# 4. 创建 Dockerfile
cat > Dockerfile << 'EOF'
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
EOF
# 5. 构建镜像
docker build -t my-node-app:v1.0 .
# 6. 查看构建的镜像
docker images my-node-app
# 7. 运行容器
docker run -d -p 3000:3000 --name my-node-app my-node-app:v1.0
# 8. 测试访问
curl http://localhost:3000
# 9. 查看容器日志
docker logs my-node-app
# 10. 清理
docker stop my-node-app
docker rm my-node-app案例 2:多阶段构建优化
场景描述
使用多阶段构建优化 React 应用的镜像大小。
操作步骤
# 1. 创建 React 应用
npx create-react-app my-react-app
cd my-react-app
# 2. 创建多阶段 Dockerfile
cat > Dockerfile << 'EOF'
# 构建阶段
FROM node:16-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:alpine
# 复制构建产物
COPY --from=builder /app/build /usr/share/nginx/html
# 复制自定义 nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
EOF
# 3. 创建 nginx 配置
cat > nginx.conf << 'EOF'
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
}
EOF
# 4. 构建镜像
docker build -t my-react-app:v1.0 .
# 5. 查看镜像大小
docker images my-react-app
# 6. 运行容器
docker run -d -p 80:80 --name my-react-app my-react-app:v1.0
# 7. 测试访问
curl http://localhost
# 8. 清理
docker stop my-react-app
docker rm my-react-app案例 3:镜像版本管理
场景描述
管理应用的不同版本镜像,支持版本回滚。
操作步骤
# 1. 构建不同版本的镜像
docker build -t myapp:1.0.0 .
docker build -t myapp:1.1.0 .
docker build -t myapp:latest .
# 2. 为镜像添加标签
docker tag myapp:latest myapp:stable
docker tag myapp:latest myapp:production
# 3. 查看所有标签
docker images myapp
# 4. 导出镜像备份
docker save -o myapp-backup.tar myapp:1.0.0 myapp:1.1.0 myapp:stable
# 5. 模拟镜像丢失
docker rmi myapp:1.0.0 myapp:1.1.0 myapp:stable
# 6. 从备份恢复
docker load -i myapp-backup.tar
# 7. 验证恢复
docker images myapp
# 8. 清理
rm myapp-backup.tar最佳实践
使用具体版本标签:避免使用
latest标签,确保构建的可重复性。优化镜像大小:
- 使用 Alpine 基础镜像
- 合并 RUN 指令
- 使用多阶段构建
- 清理不必要的文件
合理利用缓存:将变化少的指令放在前面,提高构建速度。
使用 .dockerignore:排除不必要的文件,减小构建上下文大小。
# .dockerignore 文件示例
node_modules
npm-debug.log
.git
.env
*.md- 安全扫描:定期扫描镜像漏洞。
# 使用 Docker Scout 扫描
docker scout quickview myapp:v1.0
# 使用 Trivy 扫描
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image myapp:v1.0总结
本教程详细介绍了 Docker 镜像的管理方法,包括搜索、拉取、构建、查看、删除等操作。通过实际案例,我们学习了如何构建 Node.js 和 React 应用镜像、使用多阶段构建优化镜像大小以及管理镜像版本。掌握这些技能后,可以高效地管理和分发 Docker 镜像。