Docker 容器技术 #

轻量级容器化技术,应用打包、部署、运行的标准解决方案


📋 目录 #


核心概念 #

Docker vs 虚拟机 #

传统虚拟机:

虚拟机层

OS A

Hypervisor

OS B

OS C

宿主机操作系统

硬件

特点: 每个虚拟机独立操作系统,资源占用大,启动慢

Docker容器:

Docker Engine

Docker Container Runtime (共享内核)

共享内核

App A

App B

App C

宿主机操作系统

硬件

特点: 共享宿主机内核,轻量级,启动快

核心组件 #

组件 说明 作用
Docker Client 客户端 用户与Docker交互的接口
Docker Daemon 守护进程 管理容器、镜像、网络
Docker Image 镜像 只读模板,包含运行环境
Docker Container 容器 镜像的运行实例
Docker Registry 仓库 存储和分发镜像

镜像与容器关系 #

镜像 (Image):
  - 只读模板
  - 分层存储 (Union FS)
  - 通过Dockerfile构建

容器 (Container):
  - 镜像的运行实例
  - 可读写层
  - 通过镜像启动

关系:
  Image + 启动命令 = Container
  Image ≈ 类
  Container ≈ 对象

Docker命令 #

镜像操作 #

# 搜索镜像
docker search redis

# 拉取镜像
docker pull redis:7.0
docker pull nginx:latest

# 查看本地镜像
docker images
docker image ls

# 删除镜像
docker rmi redis:7.0
docker image prune  # 删除未使用的镜像

# 构建镜像
docker build -t my-app:1.0 .

# 导出/导入镜像
docker save -o my-app.tar my-app:1.0
docker load -i my-app.tar

容器操作 #

# 运行容器
docker run -d \
  --name my-redis \
  -p 6379:6379 \
  -v /data/redis:/data \
  redis:7.0

# 查看运行中的容器
docker ps

# 查看所有容器(包括已停止)
docker ps -a

# 停止容器
docker stop my-redis

# 启动容器
docker start my-redis

# 重启容器
docker restart my-redis

# 删除容器
docker rm my-redis
docker container prune  # 删除已停止的容器

# 查看容器日志
docker logs my-redis
docker logs -f my-redis  # 实时跟踪
docker logs --tail 100 my-redis

# 进入容器
docker exec -it my-redis /bin/bash

# 查看容器详细信息
docker inspect my-redis

网络操作 #

# 查看网络
docker network ls

# 创建网络
docker network create my-network

# 连接容器到网络
docker network connect my-network my-redis

# 断开网络
docker network disconnect my-network my-redis

数据卷操作 #

# 创建数据卷
docker volume create my-volume

# 查看数据卷
docker volume ls

# 删除数据卷
docker volume rm my-volume

Dockerfile #

基本结构 #

# 多阶段构建示例 - Spring Boot应用
FROM maven:3.9-eclipse-temurin-21 AS builder

WORKDIR /app
COPY pom.xml .
COPY src ./src

# 依赖缓存优化:先下载依赖再构建
RUN mvn dependency:go-offline -B
RUN mvn clean package -DskipTests

# 运行阶段
FROM eclipse-temurin:21-jre

WORKDIR /app

# 从builder阶段复制jar包
COPY --from=builder /app/target/*.jar app.jar

# 暴露端口
EXPOSE 8080

# 启动命令
ENTRYPOINT ["java", "-jar", "app.jar"]

常用指令 #

指令 说明 示例
FROM 基础镜像 FROM openjdk:21-jre
WORKDIR 工作目录 WORKDIR /app
COPY 复制文件 COPY target/app.jar /app/
ADD 复制+解压 ADD app.tar.gz /app/
RUN 执行命令(构建时) RUN mvn package
CMD 启动命令(可被覆盖) CMD ["java", "-jar", "app.jar"]
ENTRYPOINT 入口点(不可覆盖) ENTRYPOINT ["java"]
ENV 环境变量 ENV JAVA_OPTS="-Xmx512m"
EXPOSE 暴露端口 EXPOSE 8080
VOLUME 数据卷 VOLUME /data

最佳实践 #

# ✅ 好的实践
FROM eclipse-temurin:21-jre-alpine

# 设置标签
LABEL maintainer="your-email@example.com"
LABEL version="1.0.0"

# 非root用户
RUN addgroup -S appuser && adduser -S appuser -G appuser
USER appuser

# 工作目录
WORKDIR /app

# 依赖缓存:分层COPY
COPY pom.xml .
RUN mvn dependency:go-offline -B

COPY . .
RUN mvn clean package -DskipTests

# 清理
RUN mv target/*.jar app.jar \
    && rm -rf target/

HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:8080/actuator/health || exit 1

EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Docker Compose #

基本示例 #

version: '3.8'

services:
  # 应用服务
  app:
    build: .
    container_name: spring-boot-app
    ports:
      - "8080:8080"
    environment:
      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/mydb
      - REDIS_HOST=redis
    depends_on:
      - mysql
      - redis
    networks:
      - app-network
    restart: unless-stopped

  # MySQL数据库
  mysql:
    image: mysql:8.0
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: root123
      MYSQL_DATABASE: mydb
    volumes:
      - mysql-data:/var/lib/mysql
    ports:
      - "3306:3306"
    networks:
      - app-network
    restart: unless-stopped

  # Redis缓存
  redis:
    image: redis:7.0
    container_name: redis
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    command: redis-server --appendonly yes
    networks:
      - app-network
    restart: unless-stopped

# 数据卷
volumes:
  mysql-data:
  redis-data:

# 网络
networks:
  app-network:
    driver: bridge

常用命令 #

# 启动服务(后台运行)
docker-compose up -d

# 停止服务
docker-compose stop

# 停止并删除容器
docker-compose down

# 停止删除容器和数据卷
docker-compose down -v

# 查看日志
docker-compose logs -f app

# 重新构建并启动
docker-compose up -d --build

# 扩容服务
docker-compose up -d --scale app=3

# 查看服务状态
docker-compose ps

生产实践 #

国内镜像加速 #

{
  "registry-mirrors": [
    "https://docker.mirrors.sjtug.sjtu.edu.cn",
    "https://docker.imroc.io"
  ]
}

配置位置:

  • Mac/Linux: ~/.docker/daemon.json
  • Windows: C:\ProgramData\docker\config\daemon.json

多阶段构建 #

优势:
  - 减小镜像体积
  - 分离构建环境和运行环境
  - 不需要构建工具运行时

优化对比:

单阶段:
  Docker Image Size: ~800MB
  - 包含Maven、JDK、工具类

多阶段:
  Docker Image Size: ~200MB
  - 仅包含JRE和应用

安全最佳实践 #

# 1. 使用最小化基础镜像
FROM alpine:latest

# 2. 非root用户运行
RUN addgroup -S appuser && adduser -S appuser -G appuser
USER appuser

# 3. 只读文件系统
READONLY_ROOT_FILESYSTEM=true

# 4. 限制资源
--memory="512m"
--cpus="1.5"

# 5. 扫描镜像漏洞
docker scan my-app:1.0

# 6. 定期更新基础镜像

监控与日志 #

services:
  app:
    image: my-app:1.0
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M
        reservations:
          cpus: '0.5'
          memory: 256M

容器编排选择 #

规模 推荐方案
单机 Docker Compose
小集群 Docker Swarm
大规模 Kubernetes

面试题汇总 #

基础篇 #

  1. Docker vs 虚拟机区别?
  2. Docker核心组件有哪些?
  3. 镜像与容器关系?
  4. 容器之间如何通信?

实践篇 #

  1. 如何优化Dockerfile?
  2. 如何减小镜像体积?
  3. 如何实现持久化存储?
  4. 如何实现容器编排?

进阶篇 #

  1. Docker网络模式有哪些?
  2. 如何实现容器安全?
  3. 生产环境Docker部署方案?
  4. 如何排查容器问题?

面试题答案详解 #

基础篇 #

  1. Docker vs 虚拟机区别?

答案:

对比项 Docker容器 虚拟机
隔离级别 进程级隔离 完全隔离
内核 共享宿主机内核 独立内核
镜像体积 小(MB级) 大(GB级)
启动速度 秒级 分钟级
性能开销 低(几乎无) 高(Hypervisor层)
资源利用率

架构对比:

  • 虚拟机:Hypervisor虚拟化硬件,每个VM有完整OS
  • Docker:容器共享宿主机内核,通过Cgroups和Namespace隔离

  1. Docker核心组件有哪些?

答案:

组件 说明 作用
Docker Client 客户端 命令行工具,用户与Docker交互
Docker Daemon 守护进程 运行在后台,管理容器、镜像、网络
Docker Image 镜像 只读模板,分层存储,构建容器的基础
Docker Container 容器 镜像的运行实例,有独立的可写层
Docker Registry 仓库 存储和分发镜像(Docker Hub、私有仓库)

交互流程:

Client → Daemon → Registry
       ↓
    Container

  1. 镜像与容器关系?

答案:

镜像(Image):

  • 只读模板
  • 分层存储(Union FS)
  • 通过Dockerfile构建
  • 类似面向对象中的"类"

容器(Container):

  • 镜像的运行实例
  • 有独立的可写层
  • 类似面向对象中的"对象"

关系:

  • 一个镜像可以启动多个容器
  • 容器可以基于镜像创建新镜像(docker commit)
  • 镜像 ≈ 类,容器 ≈ 对象

  1. 容器之间如何通信?

答案:

方法1:同一网络内通过容器名访问

docker network create my-network
docker run --network my-network --name container1 ...
docker run --network my-network --name container2 ...
# container2可以通过container1访问container1

方法2:端口映射

docker run -p 8080:80 ...  # 宿主机8080映射到容器80

方法3:通过宿主机IP访问

# 容器内访问宿主机
host.docker.internal

方法4:使用Docker Compose网络

services:
  app:
    networks:
      - app-network
  db:
    networks:
      - app-network
# app和db可以通过服务名互相访问

实践篇 #

  1. 如何优化Dockerfile?

答案:

优化策略:

  1. 多阶段构建
FROM maven:3.9 AS builder
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package

FROM eclipse-temurin:21-jre
COPY --from=builder /app/target/*.jar app.jar
  1. 分层缓存
COPY pom.xml .          # 依赖层,不变则不重构建
RUN mvn dependency:go-offline
COPY src ./src          # 代码层,变化才重构建
RUN mvn package
  1. 使用最小化基础镜像
FROM eclipse-temurin:21-jre-alpine  # Alpine比Ubuntu小很多
  1. 清理缓存
RUN apt-get update && apt-get install -y \
    package1 \
    package2 \
    && rm -rf /var/lib/apt/lists/*  # 清理apt缓存

  1. 如何减小镜像体积?

答案:

方法对比:

方法 效果
多阶段构建 减小50-80%
使用Alpine镜像 减小60-70%
合并RUN指令 减小层数
清理缓存 减小10-30%
使用.dockerignore 减小构建上下文

示例:

# ❌ 不好的实践
FROM ubuntu:22.04
RUN apt-get update
RUN apt-get install -y openjdk-21-jdk
COPY . .
RUN mvn package

# ✅ 好的实践
FROM maven:3.9-eclipse-temurin-21 AS builder
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package

FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

  1. 如何实现持久化存储?

答案:

三种方式:

  1. Volume(推荐)
docker volume create my-volume
docker run -v my-volume:/data ...
# 生命周期独立于容器,适合生产
  1. Bind Mount
docker run -v /host/data:/container/data ...
# 挂载宿主机目录,适合开发
  1. Tmpfs Mount
docker run --tmpfs /data ...
# 内存存储,容器删除即丢失,适合临时数据

Docker Compose示例:

volumes:
  mysql-data:       # 声明Volume

services:
  mysql:
    volumes:
      - mysql-data:/var/lib/mysql  # 使用Volume

  1. 如何实现容器编排?

答案:

方案选择:

规模 推荐方案 特点
单机 Docker Compose YAML定义,简单易用
小集群 Docker Swarm 内置,简单但功能有限
大规模 Kubernetes 功能强大,生产标准

Docker Compose示例:

version: '3.8'
services:
  app:
    image: my-app:1.0
    ports:
      - "8080:8080"
    depends_on:
      - mysql
      - redis
  mysql:
    image: mysql:8.0
    volumes:
      - mysql-data:/var/lib/mysql
  redis:
    image: redis:7.0
volumes:
  mysql-data:

进阶篇 #

  1. Docker网络模式有哪些?

答案:

模式 说明 特点
bridge 默认模式,桥接网络 容器间可通过IP/容器名访问
host 共享宿主机网络 性能好,无隔离
container 共享其他容器网络 与指定容器共用网络栈
none 无网络 完全隔离
自定义网络 用户定义的bridge网络 更好的隔离和DNS解析

使用示例:

# 自定义网络
docker network create --driver bridge my-network
docker run --network my-network ...

# host网络
docker run --network host ...

  1. 如何实现容器安全?

答案:

最佳实践:

  1. 使用非root用户
RUN addgroup -S appuser && adduser -S appuser -G appuser
USER appuser
  1. 最小化基础镜像
FROM alpine:latest  # Alpine比Ubuntu安全
  1. 限制资源
docker run --memory="512m" --cpus="1.5" ...
  1. 只读文件系统
services:
  app:
    read_only: true
    tmpfs:
      - /tmp
      - /run
  1. 扫描镜像漏洞
docker scan my-app:1.0
  1. 定期更新基础镜像

  1. 生产环境Docker部署方案?

答案:

生产架构:

组件 推荐方案
容器运行时 containerd
编排 Kubernetes
镜像仓库 Harbor / Docker Registry
监控 Prometheus + Grafana
日志 ELK Stack / Loki
安全扫描 Clair / Trivy

部署建议:

  1. 使用K8s编排,不要手动管理容器
  2. 资源限制,设置requests和limits
  3. 健康检查,配置liveness和readiness探针
  4. 滚动更新,保证服务不中断
  5. 持久化存储,使用PV/PVC

  1. 如何排查容器问题?

答案:

排查步骤:

  1. 查看容器状态
docker ps -a
docker inspect container-name
  1. 查看容器日志
docker logs container-name
docker logs -f container-name  # 实时
docker logs --tail 100 container-name  # 最后100行
  1. 进入容器调试
docker exec -it container-name /bin/bash
docker exec -it container-name /bin/sh  # Alpine用sh
  1. 查看资源使用
docker stats
docker top container-name
  1. 查看网络
docker network ls
docker network inspect my-network

常见问题:

  • 容器启动失败:看logs,检查CMD/ENTRYPOINT
  • 无法访问:检查端口映射、网络模式
  • 性能问题:看stats,检查资源限制

实战案例 #

本地 AI 环境:Ollama + Open-WebUI + Portainer #

完全离线的本地 AI 开发环境,保护数据隐私。

组件说明 #

组件 作用 端口 官网
Ollama 大模型运行时,提供 OpenAI 兼容 API 11434 https://ollama.com
Open-WebUI 美观的 Web 聊天界面(类似 ChatGPT) 3000 或 8080 https://openwebui.com
Portainer Docker 容器可视化管理 9443 (HTTPS) https://www.portainer.io

架构 #

浏览器 → Open-WebUI (Web UI) → Ollama (LLM 后端)
           ↓
      Portainer (管理界面)

访问地址 #

服务 地址
Open-WebUI http://localhost:3000
Ollama API http://localhost:11434
Portainer https://localhost:9443

Ollama 常用命令 #

# 拉取模型
ollama pull llama3.1
ollama pull qwen2.5
ollama pull qwen2.5:7b
ollama pull deepseek-coder-v2

# 运行模型交互
ollama run llama3.1

# 列出已安装模型
ollama list

# 删除模型
ollama rm model-name

# 查看 Ollama 状态
ollama serve

推荐模型 #

模型 说明
llama3.1 Meta 官方,综合能力强
qwen2.5 阿里通义千问,中文友好
deepseek-coder-v2 代码生成专用

Docker 管理命令 #

# 查看运行中的容器
docker ps

# 查看所有容器
docker ps -a

# 查看日志
docker logs ollama
docker logs open-webui
docker logs portainer

# 重启容器
docker restart ollama
docker restart open-webui
docker restart portainer

🔗 相关笔记 #


最后更新: 2026-05-08