Docker镜像操作
🎯 学习目标
- 掌握Docker镜像的查找、拉取和管理
- 学会构建自定义Docker镜像
- 理解Dockerfile的编写和最佳实践
- 掌握镜像的版本管理和分发
📚 镜像基础操作
1. 镜像查找和拉取
bash
# 搜索镜像
docker search nginx
docker search --limit 10 node
docker search --filter stars=100 python
# 拉取镜像
docker pull nginx # 默认拉取latest标签
docker pull nginx:1.21-alpine # 拉取指定版本
docker pull nginx:latest nginx:stable # 同时拉取多个版本
# 查看拉取进度
docker pull --progress plain ubuntu:20.04
# 从私有仓库拉取
docker pull myregistry.com/myapp:v1.0
2. 镜像管理操作
bash
# 列出本地镜像
docker images
docker images -a # 显示所有镜像(包括中间层)
docker images --no-trunc # 显示完整镜像ID
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
# 查看镜像详细信息
docker inspect nginx:latest
docker inspect --format='{{.Config.ExposedPorts}}' nginx
# 查看镜像历史
docker history nginx:latest
docker history --no-trunc nginx:latest
# 镜像标签管理
docker tag nginx:latest myapp:v1.0
docker tag nginx:latest localhost:5000/nginx:v1.0
# 删除镜像
docker rmi nginx:latest
docker rmi -f nginx:latest # 强制删除
docker rmi $(docker images -q) # 删除所有镜像
3. 镜像清理和优化
bash
# 清理悬空镜像
docker image prune
# 清理所有未使用的镜像
docker image prune -a
# 清理指定时间前的镜像
docker image prune --filter "until=24h"
# 查看镜像占用空间
docker system df
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
🏗️ 构建自定义镜像
1. Dockerfile基础
Dockerfile是用于构建镜像的文本文件,包含了一系列指令。
dockerfile
# 基础镜像
FROM node:16-alpine
# 设置工作目录
WORKDIR /app
# 复制依赖文件
COPY package*.json ./
# 安装依赖
RUN npm ci --only=production
# 复制应用代码
COPY . .
# 暴露端口
EXPOSE 3000
# 创建非root用户
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# 切换用户
USER nextjs
# 启动命令
CMD ["npm", "start"]
2. Dockerfile指令详解
javascript
// Dockerfile指令说明
const dockerfileInstructions = {
FROM: {
purpose: '指定基础镜像',
syntax: 'FROM <image>[:<tag>] [AS <name>]',
examples: [
'FROM ubuntu:20.04',
'FROM node:16-alpine AS builder',
'FROM scratch' // 空镜像
]
},
WORKDIR: {
purpose: '设置工作目录',
syntax: 'WORKDIR /path/to/workdir',
note: '目录不存在会自动创建'
},
COPY: {
purpose: '复制文件到镜像',
syntax: 'COPY [--chown=<user>:<group>] <src>... <dest>',
examples: [
'COPY package.json .',
'COPY --chown=node:node . /app'
]
},
ADD: {
purpose: '复制文件(支持URL和解压)',
syntax: 'ADD [--chown=<user>:<group>] <src>... <dest>',
note: '推荐使用COPY,除非需要解压功能'
},
RUN: {
purpose: '执行命令',
forms: {
shell: 'RUN <command>',
exec: 'RUN ["executable", "param1", "param2"]'
},
examples: [
'RUN apt-get update && apt-get install -y curl',
'RUN ["npm", "install"]'
]
},
CMD: {
purpose: '指定容器启动命令',
syntax: 'CMD ["executable","param1","param2"]',
note: 'Dockerfile中只能有一个CMD指令'
},
ENTRYPOINT: {
purpose: '配置容器启动程序',
syntax: 'ENTRYPOINT ["executable", "param1", "param2"]',
note: '与CMD配合使用,ENTRYPOINT不会被覆盖'
},
ENV: {
purpose: '设置环境变量',
syntax: 'ENV <key>=<value>',
examples: [
'ENV NODE_ENV=production',
'ENV PATH="/app/bin:$PATH"'
]
},
ARG: {
purpose: '定义构建参数',
syntax: 'ARG <name>[=<default value>]',
note: '只在构建时使用,运行时不可见'
},
EXPOSE: {
purpose: '声明端口',
syntax: 'EXPOSE <port> [<port>/<protocol>...]',
note: '仅用于文档,不会自动发布端口'
},
VOLUME: {
purpose: '创建挂载点',
syntax: 'VOLUME ["/data"]',
note: '创建匿名卷挂载点'
},
USER: {
purpose: '指定运行用户',
syntax: 'USER <user>[:<group>]',
examples: ['USER node', 'USER 1001:1001']
},
HEALTHCHECK: {
purpose: '健康检查',
syntax: 'HEALTHCHECK [OPTIONS] CMD command',
example: 'HEALTHCHECK --interval=30s CMD curl -f http://localhost/ || exit 1'
}
};
console.log('Dockerfile指令详解:', dockerfileInstructions);
3. 构建镜像
bash
# 基本构建
docker build -t myapp:v1.0 .
# 指定Dockerfile
docker build -f Dockerfile.prod -t myapp:prod .
# 使用构建参数
docker build --build-arg NODE_ENV=production -t myapp:prod .
# 不使用缓存构建
docker build --no-cache -t myapp:v1.0 .
# 设置构建上下文
docker build -t myapp:v1.0 https://github.com/user/repo.git
# 多平台构建
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:v1.0 .
🛠️ 实际构建示例
1. Node.js应用镜像
dockerfile
# Dockerfile for Node.js App
FROM node:16-alpine AS builder
# 设置工作目录
WORKDIR /app
# 复制package文件
COPY package*.json ./
# 安装依赖
RUN npm ci --only=production && npm cache clean --force
# 生产阶段
FROM node:16-alpine AS production
# 安装dumb-init
RUN apk add --no-cache dumb-init
# 创建应用用户
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# 设置工作目录
WORKDIR /app
# 从builder阶段复制依赖
COPY --from=builder --chown=nextjs:nodejs /app/node_modules ./node_modules
# 复制应用代码
COPY --chown=nextjs:nodejs . .
# 切换到非root用户
USER nextjs
# 暴露端口
EXPOSE 3000
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# 启动应用
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "server.js"]
2. 静态网站镜像
dockerfile
# Dockerfile for Static Website
FROM nginx:alpine
# 删除默认配置
RUN rm -rf /usr/share/nginx/html/*
# 复制静态文件
COPY dist/ /usr/share/nginx/html/
# 复制nginx配置
COPY nginx.conf /etc/nginx/nginx.conf
# 创建nginx用户
RUN addgroup -g 1001 -S nginx-group
RUN adduser -S nginx-user -u 1001 -G nginx-group
# 设置文件权限
RUN chown -R nginx-user:nginx-group /usr/share/nginx/html
RUN chown -R nginx-user:nginx-group /var/cache/nginx
RUN chown -R nginx-user:nginx-group /var/log/nginx
# 切换用户
USER nginx-user
# 暴露端口
EXPOSE 8080
# 启动nginx
CMD ["nginx", "-g", "daemon off;"]
3. Python应用镜像
dockerfile
# Dockerfile for Python App
FROM python:3.9-slim AS base
# 设置环境变量
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1
# 安装系统依赖
RUN apt-get update && apt-get install -y \
build-essential \
&& rm -rf /var/lib/apt/lists/*
# 依赖构建阶段
FROM base AS dependencies
# 安装Python依赖
COPY requirements.txt .
RUN pip install --user -r requirements.txt
# 生产阶段
FROM base AS production
# 创建应用用户
RUN useradd --create-home --shell /bin/bash app
# 设置工作目录
WORKDIR /home/app
# 从dependencies阶段复制依赖
COPY --from=dependencies --chown=app:app /root/.local /home/app/.local
# 复制应用代码
COPY --chown=app:app . .
# 切换用户
USER app
# 更新PATH
ENV PATH=/home/app/.local/bin:$PATH
# 暴露端口
EXPOSE 8000
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD python -c "import requests; requests.get('http://localhost:8000/health')"
# 启动应用
CMD ["python", "app.py"]
🔧 多阶段构建
多阶段构建可以显著减小镜像大小,提高安全性。
1. 基本多阶段构建
dockerfile
# 构建阶段
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
2. 复杂多阶段构建
dockerfile
# 依赖安装阶段
FROM node:16-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# 构建阶段
FROM node:16-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 运行时阶段
FROM node:16-alpine AS runner
WORKDIR /app
# 创建用户
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# 复制必要文件
COPY --from=deps --chown=nextjs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
COPY --chown=nextjs:nodejs package.json ./
USER nextjs
EXPOSE 3000
CMD ["npm", "start"]
📦 镜像优化技巧
1. 减小镜像大小
dockerfile
# 使用Alpine Linux基础镜像
FROM node:16-alpine
# 合并RUN指令
RUN apk add --no-cache \
curl \
git \
&& npm install -g pm2 \
&& rm -rf /var/cache/apk/*
# 使用.dockerignore
# .dockerignore文件内容:
# node_modules
# npm-debug.log
# .git
# .gitignore
# README.md
# .env
# coverage
# .nyc_output
2. 优化层缓存
dockerfile
# 先复制依赖文件(变化频率低)
COPY package*.json ./
RUN npm ci --only=production
# 后复制源代码(变化频率高)
COPY . .
3. 使用distroless镜像
dockerfile
# 使用Google的distroless镜像
FROM gcr.io/distroless/nodejs:16
COPY package*.json ./
COPY node_modules ./node_modules
COPY dist ./dist
EXPOSE 3000
CMD ["dist/index.js"]
🏷️ 镜像标签管理
1. 标签策略
bash
# 语义化版本标签
docker tag myapp:latest myapp:1.0.0
docker tag myapp:latest myapp:1.0
docker tag myapp:latest myapp:1
# 环境标签
docker tag myapp:latest myapp:dev
docker tag myapp:latest myapp:staging
docker tag myapp:latest myapp:prod
# Git标签
docker tag myapp:latest myapp:commit-abc123
docker tag myapp:latest myapp:branch-feature
2. 自动化标签脚本
bash
#!/bin/bash
# build-and-tag.sh
set -e
IMAGE_NAME="myapp"
GIT_COMMIT=$(git rev-parse --short HEAD)
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
VERSION=$(cat package.json | grep version | cut -d '"' -f 4)
# 构建镜像
docker build -t ${IMAGE_NAME}:${GIT_COMMIT} .
# 添加标签
docker tag ${IMAGE_NAME}:${GIT_COMMIT} ${IMAGE_NAME}:${VERSION}
docker tag ${IMAGE_NAME}:${GIT_COMMIT} ${IMAGE_NAME}:${GIT_BRANCH}
if [ "$GIT_BRANCH" = "main" ]; then
docker tag ${IMAGE_NAME}:${GIT_COMMIT} ${IMAGE_NAME}:latest
fi
echo "Built and tagged image: ${IMAGE_NAME}:${GIT_COMMIT}"
🚀 镜像分发
1. 推送到Docker Hub
bash
# 登录Docker Hub
docker login
# 推送镜像
docker push username/myapp:v1.0
docker push username/myapp:latest
# 推送所有标签
docker push --all-tags username/myapp
2. 私有仓库管理
bash
# 登录私有仓库
docker login myregistry.com
# 标签私有仓库镜像
docker tag myapp:v1.0 myregistry.com/myapp:v1.0
# 推送到私有仓库
docker push myregistry.com/myapp:v1.0
# 从私有仓库拉取
docker pull myregistry.com/myapp:v1.0
3. 镜像签名和验证
bash
# 启用Docker Content Trust
export DOCKER_CONTENT_TRUST=1
# 推送签名镜像
docker push username/myapp:v1.0
# 验证镜像签名
docker trust inspect --pretty username/myapp:v1.0
🔍 镜像安全扫描
1. 使用Docker Scout
bash
# 扫描镜像漏洞
docker scout cves myapp:latest
# 查看镜像构成
docker scout sbom myapp:latest
# 比较镜像
docker scout compare myapp:v1.0 myapp:v2.0
2. 使用Trivy扫描
bash
# 安装Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
# 扫描镜像
trivy image myapp:latest
# 扫描并生成报告
trivy image --format json --output report.json myapp:latest
📋 最佳实践
1. Dockerfile最佳实践
dockerfile
# ✅ 好的做法
FROM node:16-alpine AS base
# 使用特定版本而不是latest
FROM node:16.14.2-alpine
# 创建非root用户
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001
# 设置工作目录
WORKDIR /app
# 先复制依赖文件,利用缓存
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
# 复制源代码
COPY --chown=nextjs:nodejs . .
# 切换到非root用户
USER nextjs
# 使用ENTRYPOINT和CMD组合
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["npm", "start"]
2. 镜像安全最佳实践
dockerfile
# 使用官方基础镜像
FROM node:16-alpine
# 及时更新基础镜像
RUN apk update && apk upgrade
# 删除不必要的包
RUN apk add --no-cache --virtual .build-deps \
python3 \
make \
g++ \
&& npm install \
&& apk del .build-deps
# 不在镜像中存储敏感信息
# 使用ARG而不是ENV传递构建时密钥
ARG API_KEY
RUN echo "API_KEY=${API_KEY}" > /tmp/config && \
# 使用API_KEY \
rm /tmp/config
# 设置只读根文件系统
USER nobody
📝 下一步
现在您已经掌握了Docker镜像的操作,接下来学习:
- Docker容器操作 - 深入学习容器的运行和管理
- Dockerfile详解 - 高级Dockerfile编写技巧
🎯 本章要点
- ✅ 掌握镜像的查找、拉取和管理操作
- ✅ 学会编写高效的Dockerfile
- ✅ 理解多阶段构建的优势和用法
- ✅ 掌握镜像优化和安全最佳实践
- ✅ 了解镜像标签管理和分发流程
继续深入学习Docker容器操作!🐳