基础概念类
1. 什么是Docker?它解决了什么问题?
解析:
Docker是一个开源的容器化平台,用于开发、交付和运行应用程序。
主要解决的问题:
- 环境一致性:解决"在我机器上能跑"的问题
- 资源利用率:比虚拟机更轻量,启动更快
- 应用隔离:不同应用间互不干扰
- 部署简化:一次构建,到处运行
- 微服务架构:支持服务拆分和独立部署
2. Docker容器和虚拟机有什么区别?
解析:
特性 | Docker容器 | 虚拟机 |
---|---|---|
隔离级别 | 进程级隔离 | 硬件级隔离 |
启动时间 | 秒级 | 分钟级 |
资源占用 | 轻量(MB级) | 重量(GB级) |
性能损耗 | 几乎无损耗 | 5-20%损耗 |
操作系统 | 共享宿主机内核 | 独立操作系统 |
详细说明:
- 容器直接运行在宿主机操作系统上,共享内核
- 虚拟机需要完整的Guest OS,通过Hypervisor管理
- 容器更适合微服务架构,虚拟机更适合完全隔离的场景
3. 解释Docker的核心组件
解析:
Docker Engine: Docker的核心运行时
- Docker Daemon (dockerd):后台进程,管理容器生命周期
- Docker CLI:命令行接口
- REST API:程序化接口
关键对象:
- Image(镜像):只读模板,包含运行应用所需的一切
- Container(容器):镜像的运行实例
- Registry(注册表):存储和分发镜像的服务
- Dockerfile:构建镜像的脚本文件
4. 什么是Docker镜像的分层结构?
解析:
Docker镜像采用联合文件系统(Union File System),具有分层结构:
分层原理:
应用层 ← 可写层(Container Layer)
├── App层 ← FROM ubuntu:18.04
├── 依赖层 ← RUN apt-get install
├── 基础层 ← Ubuntu系统文件
└── 内核层 ← 宿主机内核(共享)
优势:
- 空间效率:相同的层可以被多个镜像共享
- 构建速度:只重新构建改变的层
- 网络效率:只传输变化的层
- 版本管理:每层都有唯一ID
5. Dockerfile中的关键指令及其作用
解析:
# 基础镜像
FROM ubuntu:20.04
# 维护者信息
LABEL maintainer="developer@example.com"
# 工作目录
WORKDIR /app
# 复制文件
COPY . /app
ADD https://example.com/file.tar.gz /tmp/
# 执行命令
RUN apt-get update && apt-get install -y python3
RUN pip install -r requirements.txt
# 环境变量
ENV NODE_ENV=production
ENV PATH=$PATH:/app/bin
# 暴露端口
EXPOSE 3000 8080
# 挂载点
VOLUME ["/data", "/logs"]
# 用户切换
USER nobody
# 启动命令
CMD ["python3", "app.py"]
ENTRYPOINT ["./entrypoint.sh"]
CMD vs ENTRYPOINT 区别:
- CMD:可被docker run参数覆盖
- ENTRYPOINT:不可覆盖,run参数作为ENTRYPOINT的参数
实操命令类
6. 常用的Docker命令有哪些?
解析:
镜像管理:
# 拉取镜像
docker pull nginx:1.20
# 查看镜像
docker images
docker image ls
# 构建镜像
docker build -t myapp:1.0 .
docker build -f Dockerfile.prod -t myapp:prod .
# 删除镜像
docker rmi image_id
docker image prune # 删除悬挂镜像
容器管理:
# 运行容器
docker run -d -p 8080:80 --name web nginx
docker run -it ubuntu bash # 交互模式
# 查看容器
docker ps # 运行中的容器
docker ps -a # 所有容器
# 容器操作
docker start/stop/restart container_id
docker exec -it container_id bash
docker logs container_id
docker inspect container_id
7. 如何进入正在运行的容器?
解析:
方法一:docker exec (推荐)
# 启动新的bash会话
docker exec -it container_name bash
docker exec -it container_name sh
# 执行单个命令
docker exec container_name ls -la /app
方法二:docker attach
# 附加到容器主进程
docker attach container_name
# 注意:Ctrl+C会停止容器
区别:
exec
:创建新进程,不影响容器主进程attach
:连接到主进程,退出可能影响容器运行
8. 如何实现容器间通信?
解析:
方法一:自定义网络(推荐)
# 创建网络
docker network create mynetwork
# 运行容器并加入网络
docker run -d --network mynetwork --name web nginx
docker run -d --network mynetwork --name db mysql
# 容器间可通过服务名通信
# web容器内可以通过 'db:3306' 访问数据库
方法二:Link (已废弃)
docker run -d --name db mysql
docker run -d --link db:database nginx
方法三:共享网络栈
docker run -d --name web nginx
docker run -d --network container:web redis
9. Docker数据持久化的方式
解析:
Volume (推荐方式)
# 创建命名卷
docker volume create mydata
# 使用卷
docker run -d -v mydata:/data nginx
docker run -d --mount source=mydata,target=/data nginx
# 匿名卷
docker run -d -v /data nginx
Bind Mount
# 绑定宿主机目录
docker run -d -v /host/path:/container/path nginx
docker run -d --mount type=bind,source=/host/path,target=/container/path nginx
tmpfs Mount
# 内存文件系统
docker run -d --tmpfs /tmp nginx
docker run -d --mount type=tmpfs,destination=/tmp nginx
区别对比:
- Volume:Docker管理,跨平台,性能好
- Bind Mount:直接映射宿主机路径,灵活但依赖宿主机
- tmpfs:内存存储,重启后数据丢失
10. 如何查看容器资源使用情况?
解析:
实时监控:
# 查看所有容器资源使用
docker stats
# 查看特定容器
docker stats container_name
# 不持续刷新
docker stats --no-stream
详细信息:
# 查看容器详细配置
docker inspect container_name
# 查看容器进程
docker top container_name
# 查看端口映射
docker port container_name
系统级监控:
# 查看Docker系统信息
docker system df # 磁盘使用
docker system events # 事件流
docker system info # 系统信息
网络和存储
11. Docker的网络模式有哪些?
解析:
Bridge模式 (默认)
docker run -d --network bridge nginx
- 容器连接到docker0网桥
- 容器间可通信,需端口映射访问外部
Host模式
docker run -d --network host nginx
- 容器直接使用宿主机网络
- 性能最好,但端口冲突风险高
None模式
docker run -d --network none nginx
- 容器无网络接口
- 适用于批处理作业
Container模式
docker run -d --network container:other_container nginx
- 共享其他容器的网络栈
自定义网络
# 创建bridge网络
docker network create --driver bridge mynet
# 创建overlay网络(Swarm)
docker network create --driver overlay --attachable myoverlay
12. 如何配置容器的资源限制?
解析:
内存限制:
# 限制内存使用
docker run -d --memory 512m nginx
docker run -d -m 1g --memory-swap 2g nginx
# 内存交换配置
--memory-swap=2g # 总计2G(包含内存)
--memory-swap=0 # 禁用交换
--memory-swap=-1 # 无限制交换
CPU限制:
# CPU份额(相对权重)
docker run -d --cpu-shares 512 nginx
# CPU核心数
docker run -d --cpus 1.5 nginx
docker run -d --cpuset-cpus 0,1 nginx
# CPU配额
docker run -d --cpu-period 100000 --cpu-quota 50000 nginx
磁盘IO限制:
# 读写速率限制
docker run -d --device-read-bps /dev/sda:1mb nginx
docker run -d --device-write-bps /dev/sda:1mb nginx
# IOPS限制
docker run -d --device-read-iops /dev/sda:1000 nginx
13. Docker Compose的作用和基本使用
解析:
作用:
- 定义和运行多容器应用
- 使用YAML文件配置服务
- 一键启动整个应用栈
基本配置示例:
version: '3.8'
services:
web:
build: .
ports:
- "8000:8000"
volumes:
- .:/app
environment:
- DEBUG=1
depends_on:
- db
- redis
db:
image: postgres:13
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:6-alpine
ports:
- "6379:6379"
volumes:
postgres_data:
networks:
default:
driver: bridge
常用命令:
# 启动服务
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs web
# 停止和清理
docker-compose down
docker-compose down -v # 同时删除卷
14. 如何实现Docker容器的健康检查?
解析:
在Dockerfile中定义:
FROM nginx
# HTTP健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost/ || exit 1
# 命令执行检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD service nginx status || exit 1
# 自定义脚本检查
COPY healthcheck.sh /usr/local/bin/
HEALTHCHECK --interval=30s --timeout=10s \
CMD /usr/local/bin/healthcheck.sh
在docker run中定义:
docker run -d \
--health-cmd "curl -f http://localhost/ || exit 1" \
--health-interval 30s \
--health-timeout 3s \
--health-retries 3 \
nginx
在docker-compose中定义:
services:
web:
image: nginx
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
健康检查脚本示例:
#!/bin/bash
# healthcheck.sh
# 检查进程
if ! pgrep nginx > /dev/null; then
exit 1
fi
# 检查端口
if ! nc -z localhost 80; then
exit 1
fi
# 检查HTTP响应
if ! curl -f http://localhost/health; then
exit 1
fi
exit 0
15. Docker镜像的多阶段构建
解析:
传统单阶段构建问题:
- 镜像包含构建工具,体积大
- 安全风险,包含不必要的依赖
多阶段构建解决方案:
# 第一阶段:构建阶段
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# 第二阶段:生产阶段
FROM nginx:alpine AS production
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# 第三阶段:开发阶段
FROM node:16 AS development
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
构建不同目标:
# 构建生产镜像
docker build --target production -t myapp:prod .
# 构建开发镜像
docker build --target development -t myapp:dev .
复杂示例 (Go应用):
# 编译阶段
FROM golang:1.19 AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o app .
# 运行阶段
FROM alpine:latest AS runner
WORKDIR /root/
RUN apk --no-cache add ca-certificates tzdata
COPY --from=builder /src/app .
CMD ["./app"]
高级特性
16. Docker Swarm集群的基本概念
解析:
核心概念:
- Node: 集群中的Docker引擎实例
- Manager Node: 管理集群状态,调度任务
- Worker Node: 执行任务
- Service: 在集群上运行的应用定义
- Task: Service的最小调度单位
- Stack: 相关服务的集合
集群初始化:
# 初始化Swarm集群
docker swarm init --advertise-addr 192.168.1.100
# 加入Worker节点
docker swarm join --token SWMTKN-xxx 192.168.1.100:2377
# 加入Manager节点
docker swarm join-token manager
服务管理:
# 创建服务
docker service create --name web --replicas 3 -p 80:80 nginx
# 扩缩容
docker service scale web=5
# 更新服务
docker service update --image nginx:1.20 web
# 查看服务
docker service ls
docker service ps web
17. 如何实现Docker镜像的安全扫描?
解析:
使用Docker Scan (已集成Snyk):
# 扫描本地镜像
docker scan myapp:latest
# 扫描指定层级
docker scan --severity high myapp:latest
# 输出JSON格式
docker scan --json myapp:latest
使用Trivy进行扫描:
# 安装Trivy
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image myapp:latest
# 扫描特定漏洞类型
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image --vuln-type os,library myapp:latest
安全最佳实践:
# 使用官方基础镜像
FROM node:16-alpine
# 创建非root用户
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# 最小化安装
RUN apk add --no-cache libc6-compat
# 复制必要文件
COPY --chown=nextjs:nodejs package*.json ./
RUN npm ci --only=production && npm cache clean --force
# 切换到非root用户
USER nextjs
# 不暴露敏感信息
ARG BUILD_TIME
ENV NODE_ENV=production
18. Docker的日志管理策略
解析:
默认日志驱动 (json-file):
# 配置日志大小和轮转
docker run -d \
--log-opt max-size=10m \
--log-opt max-file=3 \
nginx
# 查看日志
docker logs container_name
docker logs -f --tail 100 container_name
其他日志驱动:
# Syslog
docker run -d --log-driver syslog --log-opt syslog-address=tcp://192.168.1.42:123 nginx
# Journald
docker run -d --log-driver journald nginx
# Fluentd
docker run -d --log-driver fluentd --log-opt fluentd-address=localhost:24224 nginx
# 禁用日志
docker run -d --log-driver none nginx
集中化日志方案:
# docker-compose.yml
version: '3.8'
services:
app:
image: myapp
logging:
driver: "fluentd"
options:
fluentd-address: localhost:24224
tag: myapp
fluentd:
image: fluent/fluentd:v1.14
ports:
- "24224:24224"
volumes:
- ./fluentd.conf:/fluentd/etc/fluent.conf
- ./logs:/var/log
19. Docker性能优化技巧
解析:
镜像优化:
# 使用多阶段构建
FROM node:16 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
# 使用.dockerignore
# .dockerignore内容:
node_modules
.git
*.md
.env.local
层优化:
# 错误方式 - 每个RUN创建一层
RUN apt-get update
RUN apt-get install -y python3
RUN apt-get install -y pip
RUN apt-get clean
# 正确方式 - 合并RUN指令
RUN apt-get update && \
apt-get install -y python3 pip && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
运行时优化:
# 限制资源使用
docker run -d \
--memory 512m \
--cpus 1.0 \
--restart unless-stopped \
myapp
# 使用init进程处理僵尸进程
docker run -d --init myapp
构建缓存优化:
# 利用构建缓存
COPY package.json package-lock.json ./
RUN npm ci --only=production
# 应用代码最后复制
COPY . .
20. 容器编排和服务发现
解析:
Docker Compose服务发现:
version: '3.8'
services:
web:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/myapp
- REDIS_URL=redis://redis:6379
depends_on:
- db
- redis
db:
image: postgres:13
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
redis:
image: redis:6-alpine
nginx:
image: nginx
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- web
外部服务发现 (Consul示例):
version: '3.8'
services:
consul:
image: consul:1.11
ports:
- "8500:8500"
command: consul agent -dev -client=0.0.0.0
web:
build: .
environment:
- CONSUL_URL=consul:8500
depends_on:
- consul
registrator:
image: gliderlabs/registrator
volumes:
- /var/run/docker.sock:/tmp/docker.sock
command: consul://consul:8500
depends_on:
- consul
故障排查
21. 常见的Docker故障排查方法
解析:
容器启动失败:
# 查看容器详细信息
docker inspect container_name
# 查看容器日志
docker logs container_name
docker logs --details container_name
# 以交互模式调试
docker run -it --entrypoint sh image_name
docker run -it --entrypoint bash image_name
# 检查退出码
docker ps -a # 查看Exited状态和退出码
网络连接问题:
# 检查网络配置
docker network ls
docker network inspect bridge
# 测试容器间连通性
docker exec container1 ping container2
docker exec container1 nslookup container2
# 检查端口映射
docker port container_name
netstat -tlnp | grep :8080
资源问题:
# 检查资源使用
docker stats
docker system df
docker system events
# 清理资源
docker container prune # 清理停止的容器
docker image prune # 清理悬挂镜像
docker volume prune # 清理未使用卷
docker system prune # 全面清理
22. 容器内应用调试技巧
解析:
进入容器调试:
# 安装调试工具
docker exec -it container_name bash
apt-get update && apt-get install -y \
curl wget telnet netcat-openbsd \
htop strace lsof tcpdump
# 检查进程状态
docker exec container_name ps aux
docker exec container_name top
# 检查网络连接
docker exec container_name netstat -tlnp
docker exec container_name ss -tlnp
文件系统调试:
# 检查文件权限
docker exec container_name ls -la /app
docker exec container_name id
# 查看挂载点
docker exec container_name mount
docker exec container_name df -h
# 检查文件变化
docker diff container_name
调试容器启动:
# 在Dockerfile中添加调试信息
RUN echo "Debug: Installing dependencies" && \
apt-get update && \
echo "Debug: Update completed"
# 添加健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8080/health || exit 1
23. Docker性能监控和指标收集
解析:
基础监控:
# 实时资源监控
docker stats --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"
# 系统级信息
docker system info
docker version
Prometheus + cAdvisor监控:
version: '3.8'
services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
自定义指标收集:
# 收集容器指标到文件
docker stats --no-stream --format "{{.Container}},{{.CPUPerc}},{{.MemUsage}}" > stats.csv
# 使用脚本监控
#!/bin/bash
while true; do
echo "$(date): $(docker stats --no-stream --format '{{.Container}} CPU:{{.CPUPerc}} MEM:{{.MemUsage}}')"
sleep 60
done > docker-stats.log
24. Docker安全最佳实践
解析:
镜像安全:
# 使用官方基础镜像
FROM alpine:3.15
# 创建非特权用户
RUN addgroup -g 1001 appgroup && \
adduser -D -u 1001 -G appgroup appuser
# 安装必要软件并清理
RUN apk add --no-cache python3 py3-pip && \
pip3 install --no-cache-dir flask && \
rm -rf /var/cache/apk/*
# 复制文件并设置权限
COPY --chown=appuser:appgroup app.py /app/
WORKDIR /app
# 切换到非特权用户
USER appuser
# 设置只读文件系统
VOLUME ["/tmp"]
运行时安全:
# 限制容器权限
docker run -d \
--user 1001:1001 \
--read-only \
--tmpfs /tmp \
--tmpfs /var/run \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
--security-opt no-new-privileges \
--security-opt seccomp=default.json \
myapp
# 网络隔离
docker network create --internal secure-net
docker run -d --network secure-net myapp
secrets管理:
# Docker Swarm secrets
echo "mysecretpassword" | docker secret create db_password -
docker service create \
--name myapp \
--secret db_password \
myapp:latest
# 环境变量文件
docker run -d --env-file .env myapp
25. Docker在CI/CD中的实践
解析:
GitLab CI示例:
# .gitlab-ci.yml
stages:
- build
- test
- deploy
variables:
DOCKER_REGISTRY: registry.gitlab.com
IMAGE_NAME: $DOCKER_REGISTRY/$CI_PROJECT_PATH
DOCKER_DRIVER: overlay2
build:
stage: build
image: docker:20.10
services:
- docker:20.10-dind
before_script:
- echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
script:
- docker build -t $IMAGE_NAME:$CI_COMMIT_SHA .
- docker push $IMAGE_NAME:$CI_COMMIT_SHA
- docker tag $IMAGE_NAME:$CI_COMMIT_SHA $IMAGE_NAME:latest
- docker push $IMAGE_NAME:latest
test:
stage: test
image: $IMAGE_NAME:$CI_COMMIT_SHA
script:
- npm test
- npm run lint
deploy:
stage: deploy
script:
- docker pull $IMAGE_NAME:$CI_COMMIT_SHA
- docker stop myapp || true
- docker rm myapp || true
- docker run -d --name myapp -p 80:8080 $IMAGE_NAME:$CI_COMMIT_SHA
only:
- main
Jenkins Pipeline示例:
pipeline {
agent any
environment {
DOCKER_REGISTRY = 'your-registry.com'
IMAGE_NAME = 'myapp'
DOCKER_CREDENTIALS = credentials('docker-hub-credentials')
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build') {
steps {
script {
def image = docker.build("${DOCKER_REGISTRY}/${IMAGE_NAME}:${BUILD_NUMBER}")
docker.withRegistry('https://' + DOCKER_REGISTRY, 'docker-registry-credentials') {
image.push()
image.push('latest')
}
}
}
}
stage('Test') {
steps {
script {
docker.image("${DOCKER_REGISTRY}/${IMAGE_NAME}:${BUILD_NUMBER}").inside {
sh 'npm test'
sh 'npm run coverage'
}
}
}
}
stage('Deploy') {
when {
branch 'main'
}
steps {
script {
sh """
docker pull ${DOCKER_REGISTRY}/${IMAGE_NAME}:${BUILD_NUMBER}
docker stop myapp || true
docker rm myapp || true
docker run -d --name myapp \
-p 8080:8080 \
--restart unless-stopped \
${DOCKER_REGISTRY}/${IMAGE_NAME}:${BUILD_NUMBER}
"""
}
}
}
}
post {
always {
sh 'docker system prune -f'
}
}
}
GitHub Actions示例:
# .github/workflows/docker.yml
name: Docker Build and Deploy
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
myapp:latest
myapp:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Run tests
run: |
docker run --rm myapp:${{ github.sha }} npm test
- name: Deploy to staging
if: github.ref == 'refs/heads/develop'
run: |
echo "Deploy to staging environment"
# 部署逻辑
- name: Deploy to production
if: github.ref == 'refs/heads/main'
run: |
echo "Deploy to production environment"
# 生产部署逻辑
高级应用场景
26. 微服务架构中的Docker实践
解析:
服务拆分示例:
# docker-compose.microservices.yml
version: '3.8'
services:
# API网关
api-gateway:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- user-service
- order-service
- product-service
# 用户服务
user-service:
build: ./services/user
environment:
- DATABASE_URL=postgresql://user:pass@user-db:5432/users
- REDIS_URL=redis://redis:6379
depends_on:
- user-db
- redis
user-db:
image: postgres:13
environment:
POSTGRES_DB: users
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
volumes:
- user_data:/var/lib/postgresql/data
# 订单服务
order-service:
build: ./services/order
environment:
- DATABASE_URL=mongodb://order-db:27017/orders
- USER_SERVICE_URL=http://user-service:3000
depends_on:
- order-db
order-db:
image: mongo:5
volumes:
- order_data:/data/db
# 产品服务
product-service:
build: ./services/product
environment:
- DATABASE_URL=postgresql://product:pass@product-db:5432/products
depends_on:
- product-db
product-db:
image: postgres:13
environment:
POSTGRES_DB: products
POSTGRES_USER: product
POSTGRES_PASSWORD: pass
volumes:
- product_data:/var/lib/postgresql/data
# 共享服务
redis:
image: redis:6-alpine
volumes:
- redis_data:/data
# 消息队列
rabbitmq:
image: rabbitmq:3-management
ports:
- "15672:15672"
environment:
RABBITMQ_DEFAULT_USER: admin
RABBITMQ_DEFAULT_PASS: password
volumes:
user_data:
order_data:
product_data:
redis_data:
networks:
default:
driver: bridge
服务发现和配置管理:
# 使用Consul作为服务发现
consul:
image: consul:1.11
ports:
- "8500:8500"
command: consul agent -dev -client=0.0.0.0 -ui
# 配置中心
config-server:
image: springcloud/configserver
ports:
- "8888:8888"
environment:
- SPRING_CLOUD_CONFIG_SERVER_GIT_URI=https://github.com/myorg/config-repo
27. Docker的存储驱动和性能优化
解析:
存储驱动类型:
Overlay2 (推荐)
# 查看当前存储驱动
docker info | grep "Storage Driver"
# 配置overlay2
# /etc/docker/daemon.json
{
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
Device Mapper
{
"storage-driver": "devicemapper",
"storage-opts": [
"dm.thinpooldev=/dev/mapper/docker-thinpool",
"dm.use_deferred_removal=true",
"dm.use_deferred_deletion=true"
]
}
性能优化配置:
{
"storage-driver": "overlay2",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"live-restore": true,
"userland-proxy": false,
"experimental": true,
"metrics-addr": "127.0.0.1:9323",
"default-ulimits": {
"nofile": {
"Hard": 64000,
"Name": "nofile",
"Soft": 64000
}
}
}
磁盘清理策略:
# 自动清理脚本
#!/bin/bash
# docker-cleanup.sh
# 清理停止的容器
docker container prune -f
# 清理未使用的镜像
docker image prune -a -f
# 清理未使用的卷
docker volume prune -f
# 清理未使用的网络
docker network prune -f
# 清理构建缓存
docker builder prune -a -f
echo "Docker cleanup completed"
28. Docker安全扫描和合规性
解析:
镜像漏洞扫描流程:
# 使用Trivy进行全面扫描
trivy image --severity HIGH,CRITICAL myapp:latest
# Clair扫描
docker run -d --name clair-db postgres:latest
docker run -d --name clair --link clair-db:postgres quay.io/coreos/clair:latest
# Anchore扫描
docker run -d --name anchore-db postgres:latest
docker run -d --name anchore-engine --link anchore-db:anchore-db anchore/anchore-engine:latest
安全基线配置:
# 安全的Dockerfile模板
FROM alpine:3.15
# 创建非特权用户
RUN addgroup -g 1001 -S appgroup && \
adduser -S appuser -u 1001 -G appgroup
# 安装必要包并清理
RUN apk add --no-cache \
python3 \
py3-pip \
&& pip3 install --no-cache-dir flask \
&& rm -rf /var/cache/apk/* \
&& rm -rf ~/.cache/pip
# 设置工作目录和权限
WORKDIR /app
COPY --chown=appuser:appgroup . /app
# 移除不必要的权限
RUN chmod -R 755 /app && \
find /app -type f -name "*.py" -exec chmod 644 {} \;
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD python3 -c "import requests; requests.get('http://localhost:5000/health')" || exit 1
# 切换到非特权用户
USER appuser
# 暴露端口
EXPOSE 5000
# 启动应用
CMD ["python3", "app.py"]
运行时安全配置:
# 安全运行容器
docker run -d \
--name secure-app \
--user 1001:1001 \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=100m \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
--security-opt no-new-privileges:true \
--security-opt seccomp:default \
--security-opt apparmor:docker-default \
--ulimit nofile=1024:2048 \
--memory 512m \
--cpus 0.5 \
--restart on-failure:3 \
myapp:latest
29. Docker监控和日志聚合
解析:
ELK Stack日志聚合:
version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.15.0
environment:
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ports:
- "9200:9200"
volumes:
- es_data:/usr/share/elasticsearch/data
logstash:
image: docker.elastic.co/logstash/logstash:7.15.0
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
ports:
- "5000:5000"
depends_on:
- elasticsearch
kibana:
image: docker.elastic.co/kibana/kibana:7.15.0
ports:
- "5601:5601"
environment:
ELASTICSEARCH_HOSTS: http://elasticsearch:9200
depends_on:
- elasticsearch
# 应用容器
app:
image: myapp:latest
logging:
driver: syslog
options:
syslog-address: "tcp://logstash:5000"
tag: "myapp"
volumes:
es_data:
Logstash配置:
# logstash.conf
input {
syslog {
port => 5000
}
}
filter {
if [program] == "myapp" {
grok {
match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{GREEDYDATA:message}" }
}
date {
match => [ "timestamp", "ISO8601" ]
}
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "docker-logs-%{+YYYY.MM.dd}"
}
}
Prometheus监控栈:
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=200h'
- '--web.enable-lifecycle'
alertmanager:
image: prom/alertmanager:latest
ports:
- "9093:9093"
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=grafana
volumes:
- grafana_data:/var/lib/grafana
node-exporter:
image: prom/node-exporter:latest
ports:
- "9100:9100"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.rootfs=/rootfs'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($|/)'
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
volumes:
prometheus_data:
grafana_data:
30. Docker在不同云平台的部署
解析:
AWS ECS部署:
{
"family": "myapp-task",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"executionRoleArn": "arn:aws:iam::123456789:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789:role/ecsTaskRole",
"containerDefinitions": [
{
"name": "myapp",
"image": "123456789.dkr.ecr.us-west-2.amazonaws.com/myapp:latest",
"portMappings": [
{
"containerPort": 8080,
"protocol": "tcp"
}
],
"environment": [
{
"name": "NODE_ENV",
"value": "production"
}
],
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:ssm:us-west-2:123456789:parameter/myapp/db-password"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/myapp",
"awslogs-region": "us-west-2",
"awslogs-stream-prefix": "ecs"
}
},
"healthCheck": {
"command": ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3,
"startPeriod": 60
}
}
]
}
Google Cloud Run部署:
# cloudrun.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: myapp
annotations:
run.googleapis.com/ingress: all
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/maxScale: "100"
run.googleapis.com/cpu-throttling: "false"
run.googleapis.com/memory: "512Mi"
run.googleapis.com/cpu: "1000m"
spec:
containerConcurrency: 80
timeoutSeconds: 300
containers:
- image: gcr.io/my-project/myapp:latest
ports:
- containerPort: 8080
env:
- name: NODE_ENV
value: "production"
- name: DB_HOST
valueFrom:
secretKeyRef:
name: db-credentials
key: host
resources:
limits:
cpu: "1000m"
memory: "512Mi"
startupProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
timeoutSeconds: 5
periodSeconds: 10
failureThreshold: 3
Azure Container Instances:
# aci-template.yaml
apiVersion: 2019-12-01
location: eastus
name: myapp-group
properties:
containers:
- name: myapp
properties:
image: myregistry.azurecr.io/myapp:latest
resources:
requests:
cpu: 1.0
memoryInGb: 1.5
ports:
- port: 80
protocol: TCP
environmentVariables:
- name: NODE_ENV
value: production
- name: DB_PASSWORD
secureValue: mySecretPassword
osType: Linux
restartPolicy: Always
ipAddress:
type: Public
ports:
- protocol: tcp
port: 80
imageRegistryCredentials:
- server: myregistry.azurecr.io
username: myregistry
password: myPassword
面试技巧和总结 (31-35题)
31. Docker面试中的常见陷阱问题
解析:
问题1:容器和虚拟机的本质区别
陷阱:只说轻量、快速等表面特征
正确答案:
- 隔离级别:容器是进程级隔离,虚拟机是硬件级隔离
- 内核共享:容器共享宿主机内核,虚拟机有独立内核
- 资源开销:容器直接调用系统调用,虚拟机需要通过Hypervisor
- 安全边界:容器安全边界较弱,虚拟机安全边界更强
问题2:如何处理容器中的数据持久化
陷阱:只知道-v参数
完整答案:
1. Volume:Docker管理的数据卷,跨平台兼容性好
2. Bind Mount:直接挂载宿主机目录,性能好但依赖宿主机
3. tmpfs:内存文件系统,适合临时数据
4. 选择原则:
- 数据库数据:使用Volume
- 配置文件:使用Bind Mount
- 临时文件:使用tmpfs
问题3:容器启动失败如何排查
系统化排查方法:
1. 查看容器状态:docker ps -a
2. 查看详细信息:docker inspect container_name
3. 查看启动日志:docker logs container_name
4. 检查镜像构建:docker history image_name
5. 交互式调试:docker run -it --entrypoint sh image_name
6. 检查资源限制:内存、磁盘空间、文件描述符
7. 网络连通性测试:端口绑定、防火墙规则
32. Docker生产环境最佳实践总结
解析:
安全最佳实践:
# 1. 使用官方基础镜像
FROM node:16-alpine
# 2. 创建非root用户
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001 -g nodejs
# 3. 只安装必要的包
RUN apk add --no-cache libc6-compat
# 4. 复制文件时设置正确权限
COPY --chown=nextjs:nodejs package*.json ./
# 5. 切换到非root用户
USER nextjs
# 6. 设置健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:3000/api/health || exit 1
# 7. 使用多阶段构建减少攻击面
FROM node:16-alpine AS deps
# 安装依赖...
FROM node:16-alpine AS runner
# 只复制运行时需要的文件
COPY --from=deps /app/node_modules ./node_modules
性能优化策略:
# 1. 容器资源限制
docker run -d \
--memory 512m \
--cpus 1.0 \
--memory-swap 1g \
--oom-kill-disable \
myapp
# 2. 日志管理
docker run -d \
--log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
myapp
# 3. 网络优化
docker run -d \
--network custom-network \
--dns 8.8.8.8 \
myapp
监控和可观测性:
version: '3.8'
services:
app:
image: myapp:latest
labels:
- "prometheus.io/scrape=true"
- "prometheus.io/port=8080"
- "prometheus.io/path=/metrics"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
33. Docker与Kubernetes的关系和区别
解析:
Docker和Kubernetes的角色定位:
Docker:
- 容器运行时和镜像格式标准
- 单机容器管理
- 开发和测试环境的快速部署
Kubernetes:
- 容器编排平台
- 集群级别的容器管理
- 生产环境的大规模部署和运维
从Docker Compose到Kubernetes的迁移:
# Docker Compose
version: '3.8'
services:
web:
image: nginx
ports:
- "80:80"
replicas: 3
# 对应的Kubernetes资源
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80
type: LoadBalancer
什么时候选择Docker,什么时候选择Kubernetes:
选择Docker的场景:
- 单机应用部署
- 开发测试环境
- 简单的微服务架构
- 快速原型验证
选择Kubernetes的场景:
- 大规模集群管理
- 高可用服务部署
- 复杂的微服务架构
- 需要服务发现、负载均衡、自动扩缩容
34. Docker技术发展趋势和新特性
解析:
容器技术发展趋势:
1. 安全加强:
- Rootless容器
- 用户命名空间
- SELinux/AppArmor集成
2. 性能优化:
- 更快的镜像构建(BuildKit)
- 优化的存储驱动
- 更好的资源隔离
3. 标准化:
- OCI(开放容器倡议)标准
- CRI(容器运行时接口)
- CNI(容器网络接口)
Docker新特性介绍:
# BuildKit多平台构建
FROM --platform=$BUILDPLATFORM node:16 AS build
ARG TARGETPLATFORM
ARG BUILDPLATFORM
RUN echo "Building on $BUILDPLATFORM, targeting $TARGETPLATFORM"
# 构建缓存挂载
RUN --mount=type=cache,target=/root/.npm \
npm install
# Secret挂载
RUN --mount=type=secret,id=mypassword \
cat /run/secrets/mypassword
容器化未来发展方向:
1. Serverless容器:
- AWS Fargate、Google Cloud Run
- 按需计费,自动扩缩容
2. WebAssembly集成:
- 更轻量的运行时
- 更好的安全隔离
3. 边缘计算:
- IoT设备上的容器化
- 边缘节点的容器编排