Docker 完整学习指南

目录

Docker 基础概念

什么是 Docker?

Docker 是一个开源的容器化平台,它允许开发者将应用程序及其依赖项打包到一个轻量级、可移植的容器中。

核心概念

  • 镜像 (Image): 只读的模板,用于创建容器
  • 容器 (Container): 镜像的运行实例
  • 仓库 (Repository): 存储镜像的地方
  • Dockerfile: 构建镜像的脚本文件
  • Docker Hub: Docker 官方的公共镜像仓库

Docker vs 虚拟机

特性Docker 容器虚拟机
启动速度秒级分钟级
资源占用
隔离性进程级系统级
可移植性中等

Docker 安装

Windows 安装

  1. 下载 Docker Desktop for Windows
  2. 启用 WSL 2 功能
  3. 安装并重启系统
  4. 验证安装:
docker --version
docker run hello-world

Linux 安装 (Ubuntu)

# 更新包索引
sudo apt-get update

# 安装必要的包
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

# 添加 Docker 官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 设置稳定版仓库
echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装 Docker Engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

# 启动 Docker 服务
sudo systemctl start docker
sudo systemctl enable docker

# 将用户添加到 docker 组
sudo usermod -aG docker $USER

macOS 安装

  1. 下载 Docker Desktop for Mac
  2. 拖拽到 Applications 文件夹
  3. 启动应用并完成设置

Docker 核心命令

镜像管理

# 搜索镜像
docker search nginx

# 拉取镜像
docker pull nginx:latest

# 查看本地镜像
docker images

# 删除镜像
docker rmi nginx:latest

# 构建镜像
docker build -t myapp:v1.0 .

# 给镜像打标签
docker tag myapp:v1.0 myapp:latest

容器管理

# 运行容器
docker run -d --name mynginx -p 80:80 nginx

# 查看运行中的容器
docker ps

# 查看所有容器
docker ps -a

# 停止容器
docker stop mynginx

# 启动容器
docker start mynginx

# 重启容器
docker restart mynginx

# 删除容器
docker rm mynginx

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

# 查看容器日志
docker logs mynginx

# 查看容器详细信息
docker inspect mynginx

数据管理

# 创建数据卷
docker volume create myvolume

# 查看数据卷
docker volume ls

# 挂载数据卷
docker run -d -v myvolume:/data nginx

# 绑定挂载
docker run -d -v /host/path:/container/path nginx

# 删除数据卷
docker volume rm myvolume

Dockerfile 详解

基本结构

# 基础镜像
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 \
    && rm -rf /var/lib/apt/lists/*

# 安装 Python 依赖
RUN pip3 install -r requirements.txt

# 暴露端口
EXPOSE 8000

# 设置环境变量
ENV PYTHONPATH=/app

# 启动命令
CMD ["python3", "app.py"]

常用指令详解

  • FROM: 指定基础镜像
  • RUN: 执行命令并创建新的镜像层
  • CMD: 容器启动时执行的默认命令
  • ENTRYPOINT: 容器启动时执行的入口点
  • COPY: 复制文件到镜像中
  • ADD: 复制文件到镜像中(支持 URL 和自动解压)
  • WORKDIR: 设置工作目录
  • EXPOSE: 声明端口
  • ENV: 设置环境变量
  • VOLUME: 创建挂载点

多阶段构建示例

# 构建阶段
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/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Docker Compose

什么是 Docker Compose?

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。

docker-compose.yml 示例

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
    ports:
      - "5432:5432"

  redis:
    image: redis:alpine
    ports:
      - "6379:6379"

volumes:
  postgres_data:

Compose 常用命令

# 启动服务
docker-compose up -d

# 查看服务状态
docker-compose ps

# 查看日志
docker-compose logs

# 停止服务
docker-compose down

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

# 扩展服务
docker-compose up --scale web=3

项目部署实战

1. Python Flask 应用部署

项目结构
flask-app/
├── app.py
├── requirements.txt
├── Dockerfile
└── docker-compose.yml
app.py
from flask import Flask, jsonify
import os

app = Flask(__name__)

@app.route('/')
def hello():
    return jsonify({
        'message': 'Hello from Docker!',
        'environment': os.environ.get('ENV', 'development')
    })

@app.route('/health')
def health():
    return jsonify({'status': 'healthy'})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)
requirements.txt
Flask==2.3.3
gunicorn==21.2.0
Dockerfile
FROM python:3.9-slim

WORKDIR /app

# 复制依赖文件
COPY requirements.txt .

# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY . .

# 创建非 root 用户
RUN useradd --create-home --shell /bin/bash app && chown -R app:app /app
USER app

# 暴露端口
EXPOSE 5000

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:5000/health || exit 1

# 启动命令
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "4", "app:app"]
docker-compose.yml
version: '3.8'

services:
  web:
    build: .
    ports:
      - "5000:5000"
    environment:
      - ENV=production
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - web
    restart: unless-stopped

2. Node.js 应用部署

package.json
{
  "name": "node-docker-app",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js"
  },
  "dependencies": {
    "express": "^4.18.2",
    "cors": "^2.8.5"
  }
}
server.js
const express = require('express');
const cors = require('cors');

const app = express();
const PORT = process.env.PORT || 3000;

app.use(cors());
app.use(express.json());

app.get('/', (req, res) => {
  res.json({
    message: 'Node.js app running in Docker!',
    timestamp: new Date().toISOString()
  });
});

app.get('/health', (req, res) => {
  res.json({ status: 'OK' });
});

app.listen(PORT, '0.0.0.0', () => {
  console.log(`Server running on port ${PORT}`);
});
Dockerfile
FROM node:18-alpine

WORKDIR /usr/src/app

# 复制 package 文件
COPY package*.json ./

# 安装依赖
RUN npm ci --only=production

# 复制应用代码
COPY . .

# 创建非 root 用户
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
USER nextjs

EXPOSE 3000

CMD ["npm", "start"]

3. 全栈应用部署 (React + Node.js + PostgreSQL)

docker-compose.yml
version: '3.8'

services:
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      - REACT_APP_API_URL=http://localhost:5000
    depends_on:
      - backend

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    environment:
      - DATABASE_URL=postgresql://user:password@db:5432/myapp
      - JWT_SECRET=your-secret-key
    depends_on:
      - db
    volumes:
      - ./backend:/app
      - /app/node_modules

  db:
    image: postgres:15
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    ports:
      - "5432:5432"

  redis:
    image: redis:alpine
    ports:
      - "6379:6379"
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data

volumes:
  postgres_data:
  redis_data:

4. 微服务架构部署

docker-compose.microservices.yml
version: '3.8'

services:
  # API Gateway
  gateway:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - user-service
      - product-service
      - order-service

  # 用户服务
  user-service:
    build: ./services/user-service
    environment:
      - DB_HOST=user-db
      - REDIS_HOST=redis
    depends_on:
      - user-db
      - redis

  user-db:
    image: postgres:15
    environment:
      POSTGRES_DB: users
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - user_data:/var/lib/postgresql/data

  # 产品服务
  product-service:
    build: ./services/product-service
    environment:
      - DB_HOST=product-db
    depends_on:
      - product-db

  product-db:
    image: mongo:5
    environment:
      MONGO_INITDB_DATABASE: products
    volumes:
      - product_data:/data/db

  # 订单服务
  order-service:
    build: ./services/order-service
    environment:
      - DB_HOST=order-db
      - RABBITMQ_HOST=rabbitmq
    depends_on:
      - order-db
      - rabbitmq

  order-db:
    image: postgres:15
    environment:
      POSTGRES_DB: orders
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - order_data:/var/lib/postgresql/data

  # 消息队列
  rabbitmq:
    image: rabbitmq:3-management
    ports:
      - "15672:15672"
    environment:
      RABBITMQ_DEFAULT_USER: admin
      RABBITMQ_DEFAULT_PASS: password

  # 缓存
  redis:
    image: redis:alpine
    volumes:
      - redis_data:/data

volumes:
  user_data:
  product_data:
  order_data:
  redis_data:

最佳实践

1. Dockerfile 优化

使用多阶段构建
# 构建阶段
FROM node:16 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

# 生产阶段
FROM node:16-alpine
WORKDIR /app
COPY --from=build /app/node_modules ./node_modules
COPY . .
CMD ["npm", "start"]
减少镜像层数
# 不好的做法
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y vim

# 好的做法
RUN apt-get update && \
    apt-get install -y curl vim && \
    rm -rf /var/lib/apt/lists/*
使用 .dockerignore
node_modules
npm-debug.log
.git
.gitignore
README.md
.env
.nyc_output
coverage
.nyc_output

2. 安全最佳实践

使用非 root 用户
FROM node:16-alpine

# 创建应用用户
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

# 设置工作目录权限
WORKDIR /app
RUN chown nextjs:nodejs /app

# 切换到非 root 用户
USER nextjs

COPY --chown=nextjs:nodejs . .
扫描镜像漏洞
# 使用 Docker Scout
docker scout cves myapp:latest

# 使用 Trivy
trivy image myapp:latest

3. 性能优化

合理使用缓存
# 先复制依赖文件,利用 Docker 缓存
COPY package*.json ./
RUN npm ci --only=production

# 再复制应用代码
COPY . .
选择合适的基础镜像
# 开发环境
FROM node:16

# 生产环境
FROM node:16-alpine

# 最小化镜像
FROM scratch

4. 监控和日志

健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:3000/health || exit 1
日志管理
version: '3.8'
services:
  app:
    image: myapp
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

5. 环境管理

使用环境变量
# docker-compose.yml
version: '3.8'
services:
  app:
    image: myapp
    environment:
      - NODE_ENV=production
      - DATABASE_URL=${DATABASE_URL}
    env_file:
      - .env
多环境配置
# 开发环境
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up

# 生产环境
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up

常见问题解决

1. 容器无法启动

检查日志
docker logs container_name
docker logs -f container_name  # 实时查看
调试容器
# 进入容器调试
docker exec -it container_name /bin/bash

# 运行临时容器
docker run -it --rm image_name /bin/bash

2. 端口冲突

查看端口占用
# Linux/macOS
netstat -tulpn | grep :8080

# Windows
netstat -ano | findstr :8080
修改端口映射
docker run -p 8081:8080 myapp

3. 数据持久化问题

使用命名卷
docker volume create mydata
docker run -v mydata:/data myapp
绑定挂载
docker run -v /host/path:/container/path myapp

4. 网络连接问题

查看网络
docker network ls
docker network inspect bridge
创建自定义网络
docker network create mynetwork
docker run --network mynetwork myapp

5. 镜像构建失败

清理构建缓存
docker builder prune
docker system prune -a
查看构建过程
docker build --no-cache -t myapp .
docker build --progress=plain -t myapp .

6. 容器资源限制

设置内存限制
docker run -m 512m myapp
设置 CPU 限制
docker run --cpus="1.5" myapp
在 Compose 中设置
services:
  app:
    image: myapp
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: '0.5'

7. 清理 Docker 资源

清理未使用的资源
# 清理停止的容器
docker container prune

# 清理未使用的镜像
docker image prune

# 清理未使用的卷
docker volume prune

# 清理未使用的网络
docker network prune

# 清理所有未使用的资源
docker system prune -a

高级主题

1. Docker Swarm 集群

初始化 Swarm
docker swarm init --advertise-addr <MANAGER-IP>
部署服务
docker service create --name web --replicas 3 -p 80:80 nginx

2. 使用 Docker Registry

推送镜像到私有仓库
docker tag myapp:latest registry.example.com/myapp:latest
docker push registry.example.com/myapp:latest

3. CI/CD 集成

GitHub Actions 示例
name: Build and Deploy
on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Build Docker image
        run: docker build -t myapp .
      - name: Push to registry
        run: |
          echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
          docker push myapp

总结

Docker 是现代应用部署的重要工具,掌握 Docker 可以大大简化应用的部署和管理。通过本指南,您应该能够:

  1. 理解 Docker 的核心概念
  2. 熟练使用 Docker 命令
  3. 编写高质量的 Dockerfile
  4. 使用 Docker Compose 管理多容器应用
  5. 部署各种类型的项目
  6. 遵循最佳实践
  7. 解决常见问题

继续实践和学习,您将能够在生产环境中有效地使用 Docker!

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐