当前位置:首页 > 学习笔记 > 正文内容

Docker 容器化部署完全指南

Docker 作为容器化技术的代表,彻底改变了现代软件开发和部署的方式。通过轻量级的容器隔离,开发者可以在任何环境中保持应用的一致性运行,实现"一次构建,到处运行"的理想状态。本文将从核心概念、基础命令、实战案例等多个维度,带你全面掌握 Docker 容器化部署技术。

一、核心概念

在深入 Docker 实战之前,我们需要理解几个核心概念,这些概念构成了 Docker 技术体系的基石。

1.1 容器与镜像

镜像(Image)是一个只读的模板,包含了运行应用所需的所有内容:代码、运行时环境、库、配置文件等。可以把镜像理解为"应用程序的安装包",它是静态的、不可变的。

容器(Container)是镜像的运行实例。如果说镜像是"类",那么容器就是"对象"。容器之间相互隔离,拥有自己的文件系统、网络配置和进程空间,确保了应用的安全性和独立性。

1.2 Dockerfile

Dockerfile 是一个文本文件,包含了一系列指令,用于自动化构建 Docker 镜像。通过 Dockerfile,我们可以精确控制镜像的内容和构建过程,实现基础设施即代码(IaC)的理念。

1.3 仓库与注册表

仓库(Repository)是存放镜像的地方,类似于代码仓库。注册表(Registry)则是仓库的集合,Docker Hub 是最大的公共注册表,我们也可以搭建私有注册表来存储内部镜像。

1.4 Docker 与虚拟机的区别

与传统虚拟机相比,Docker 容器具有以下优势:

  • 启动速度快:容器直接运行在宿主机内核上,无需启动完整的操作系统,通常在毫秒级启动
  • 资源占用少:容器共享宿主机内核,无需为每个应用分配独立的操作系统资源
  • 体积小:Docker 镜像通常只有几十 MB 到几百 MB,而虚拟机镜像往往达到 GB 级别
  • 可移植性强:容器屏蔽了底层环境差异,确保应用在任何地方都能一致运行

二、核心内容

2.1 Docker 安装与配置

在不同操作系统上安装 Docker 的方式略有不同,下面分别介绍主流平台的安装方法。

Ubuntu/Debian 系统:

# 更新软件包索引
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=$(dpkg --print-architecture) 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

# 验证安装
sudo docker run hello-world

macOS 系统:

在 macOS 上,推荐安装 Docker Desktop for Mac,它提供了图形界面和完整的 Docker 运行环境。直接从 Docker 官网下载 .dmg 安装包,双击安装即可。

Windows 系统:

Windows 10/11 专业版和企业版可以安装 Docker Desktop for Windows,需要启用 WSL2(Windows Subsystem for Linux 2)来获得最佳性能。

2.2 Docker 基础命令

掌握以下核心命令,可以覆盖 Docker 日常使用的 90% 场景。

镜像管理命令:

# 从 Docker Hub 拉取镜像
docker pull nginx:latest

# 查看本地镜像列表
docker images

# 删除本地镜像
docker rmi nginx:latest

# 搜索 Docker Hub 上的镜像
docker search python

# 构建镜像(在 Dockerfile 所在目录执行)
docker build -t myapp:v1.0 .

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

容器管理命令:

# 创建并启动容器
docker run -d --name mynginx -p 8080:80 nginx:latest

# 查看运行中的容器
docker ps

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

# 停止容器
docker stop mynginx

# 启动已停止的容器
docker start mynginx

# 重启容器
docker restart mynginx

# 删除容器
docker rm mynginx

# 强制删除运行中的容器
docker rm -f mynginx

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

# 查看容器日志
docker logs mynginx

# 实时查看日志
docker logs -f mynginx

数据管理命令:

# 创建数据卷
docker volume create mydata

# 查看数据卷列表
docker volume ls

# 查看数据卷详情
docker volume inspect mydata

# 挂载数据卷运行容器
docker run -d --name myapp -v mydata:/app/data myapp:v1.0

# 挂载宿主机目录
docker run -d --name myapp -v /host/path:/container/path myapp:v1.0

2.3 Dockerfile 编写指南

Dockerfile 是构建镜像的核心,掌握其语法对于容器化部署至关重要。

# 指定基础镜像
FROM python:3.11-slim

# 设置工作目录
WORKDIR /app

# 设置环境变量
ENV PYTHONUNBUFFERED=1
ENV APP_ENV=production

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

# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 8000

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

# 启动命令
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

Dockerfile 最佳实践:

  1. 使用精简基础镜像:选择 alpine 或 slim 版本,减小镜像体积
  2. 合并 RUN 指令:减少镜像层数,使用 && 连接多个命令
  3. 利用构建缓存:将不常变化的指令放在前面
  4. 使用 .dockerignore:排除不必要的文件,加快构建速度
  5. 不要在镜像中存储敏感信息:使用环境变量或挂载配置文件

2.4 Docker Compose 多容器编排

对于复杂的微服务架构,Docker Compose 提供了便捷的多容器编排能力。

version: 3.8

services:
  # Web 应用服务
  web:
    build: .
    container_name: myapp-web
    ports:
      - "8000:8000"
    environment:
      - DEBUG=0
      - DATABASE_URL=postgres://user:pass@db:5432/mydb
      - REDIS_URL=redis://redis:6379/0
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    volumes:
      - ./media:/app/media
    restart: unless-stopped
    networks:
      - app-network

  # PostgreSQL 数据库
  db:
    image: postgres:15-alpine
    container_name: myapp-db
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=mydb
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped
    networks:
      - app-network

  # Redis 缓存
  redis:
    image: redis:7-alpine
    container_name: myapp-redis
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data
    restart: unless-stopped
    networks:
      - app-network

# 数据卷定义
volumes:
  postgres-data:
  redis-data:

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

常用 Compose 命令:

# 启动所有服务
docker-compose up -d

# 查看服务状态
docker-compose ps

# 查看服务日志
docker-compose logs -f

# 停止所有服务
docker-compose down

# 停止并删除数据卷
docker-compose down -v

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

# 扩展服务实例数量
docker-compose up -d --scale web=3

三、实战案例:部署 Python Web 应用

3.1 项目结构

myproject/
├── app/
│   ├── __init__.py
│   ├── main.py
│   └── config.py
├── requirements.txt
├── Dockerfile
├── docker-compose.yml
└── .dockerignore

3.2 应用代码

main.py

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import os
import redis
import logging

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = FastAPI(title="My Docker App", version="1.0.0")

# CORS 中间件配置
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Redis 连接
redis_host = os.getenv("REDIS_HOST", "localhost")
redis_client = redis.Redis(host=redis_host, port=6379, db=0, decode_responses=True)

@app.get("/")
async def root():
    """根路径健康检查"""
    return {"message": "Hello, Docker!", "status": "healthy"}

@app.get("/health")
async def health_check():
    """健康检查端点"""
    try:
        # 测试 Redis 连接
        redis_client.ping()
        return {"status": "healthy", "redis": "connected"}
    except Exception as e:
        logger.error(f"Health check failed: {e}")
        return {"status": "unhealthy", "error": str(e)}, 503

@app.get("/counter")
async def counter():
    """Redis 计数器示例"""
    try:
        count = redis_client.incr("visit_count")
        return {"visit_count": count}
    except Exception as e:
        logger.error(f"Counter error: {e}")
        return {"error": str(e)}, 500

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

requirements.txt

fastapi==0.109.0
uvicorn==0.27.0
redis==5.0.1

3.3 Dockerfile

# 使用 Python 3.11 精简版作为基础镜像
FROM python:3.11-slim

# 设置工作目录
WORKDIR /app

# 设置环境变量
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV TZ=Asia/Shanghai

# 安装系统依赖
RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc \
    && rm -rf /var/lib/apt/lists/*

# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

# 复制应用代码
COPY app/ ./app/

# 暴露端口
EXPOSE 8000

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

# 启动命令
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

3.4 docker-compose.yml

version: 3.8

services:
  web:
    build: .
    container_name: fastapi-app
    ports:
      - "8000:8000"
    environment:
      - REDIS_HOST=redis
    depends_on:
      - redis
    restart: unless-stopped
    networks:
      - app-net

  redis:
    image: redis:7-alpine
    container_name: fastapi-redis
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data
    restart: unless-stopped
    networks:
      - app-net

volumes:
  redis-data:

networks:
  app-net:
    driver: bridge

3.5 部署命令

# 构建并启动服务
docker-compose up -d --build

# 查看运行状态
docker-compose ps

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

# 测试应用
curl http://localhost:8000/
curl http://localhost:8000/counter

# 停止服务
docker-compose down

四、进阶技巧与最佳实践

4.1 多阶段构建优化镜像体积

# 构建阶段
FROM golang:1.21-alpine AS builder

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# 运行阶段
FROM alpine:latest

RUN apk --no-cache add ca-certificates
WORKDIR /root/

# 只复制编译好的二进制文件
COPY --from=builder /app/main .

EXPOSE 8080
CMD ["./main"]

4.2 安全最佳实践

  1. 使用非 root 用户运行容器
# 创建非 root 用户
RUN useradd -m -u 1000 appuser
USER appuser
  1. 限制容器资源使用
docker run -d \
  --name myapp \
  --memory="512m" \
  --cpus="0.5" \
  --pids-limit=100 \
  myapp:v1.0
  1. 使用只读文件系统
docker run -d --read-only --tmpfs /tmp myapp:v1.0

4.3 日志管理

配置日志驱动和日志轮转,避免日志文件无限增长:

docker run -d \
  --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  myapp:v1.0

4.4 网络管理

Docker 提供了多种网络模式,适应不同的应用场景:

# 创建自定义网络
docker network create mynetwork

# 连接容器到网络
docker network connect mynetwork mycontainer

# 查看网络详情
docker network inspect mynetwork

总结

Docker 容器化技术已经成为现代软件开发的标准实践。通过本文的学习,你应该掌握了:

  • 核心概念:理解了镜像、容器、Dockerfile、仓库等基本概念
  • 基础操作:熟练使用镜像管理、容器管理、数据管理等核心命令
  • Dockerfile 编写:能够编写符合最佳实践的 Dockerfile
  • 多容器编排:使用 Docker Compose 管理复杂的微服务架构
  • 实战部署:完整部署了一个 FastAPI + Redis 的 Web 应用
  • 进阶技巧:多阶段构建、安全配置、日志管理等最佳实践

容器化是一个持续演进的领域,建议继续深入学习 Kubernetes 容器编排、Docker Swarm 集群管理、CI/CD 流水线集成等高级主题,不断提升自己的云原生技术能力。

希望这篇指南能帮助你快速上手 Docker,在实际项目中灵活运用容器化技术,提升开发效率和应用的可维护性。

本文链接:https://www.kkkliao.cn/?id=897 转载需授权!

分享到:

版权声明:本文由廖万里的博客发布,如需转载请注明出处。


发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。