Docker 容器化部署实战完全指南
Docker 是现代软件开发和运维的核心技术,它通过容器化技术实现了"一次构建,到处运行"的理念。本文将从 Docker 基础概念讲起,深入讲解镜像管理、容器操作、网络配置、数据持久化、Docker Compose 多容器编排等核心技术,并通过实战案例演示如何将一个完整的 Web 应用容器化部署。
一、Docker 核心概念
在深入学习 Docker 之前,我们需要理解几个核心概念:
1.1 镜像(Image)
镜像是容器的蓝图,包含了运行应用所需的所有内容:代码、运行时、库、环境变量和配置文件。镜像是只读的,可以看作是一个轻量级的虚拟机快照。
1.2 容器(Container)
容器是镜像的运行实例。如果说镜像是"类",那容器就是"对象"。容器之间相互隔离,每个容器都有自己独立的文件系统、网络配置和进程空间。
1.3 仓库(Registry)
仓库是存储和分发镜像的地方。Docker Hub 是最大的公共仓库,企业也可以搭建私有仓库来存储自己的镜像。
1.4 Dockerfile
Dockerfile 是一个文本文件,包含了构建镜像的所有指令。通过 Dockerfile,我们可以将应用的运行环境标准化,实现环境的一致性。
二、Docker 安装与基础操作
2.1 安装 Docker
以 Ubuntu 为例,安装 Docker 的步骤如下:
# 更新软件包索引 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 # 添加 Docker 仓库 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 # 将当前用户加入 docker 组(避免每次使用 sudo) sudo usermod -aG docker $USER
2.2 镜像管理命令
# 搜索镜像 docker search nginx # 拉取镜像(默认 latest 版本) docker pull nginx # 拉取指定版本镜像 docker pull nginx:1.21-alpine # 查看本地镜像列表 docker images # 查看镜像详细信息 docker inspect nginx:latest # 删除镜像 docker rmi nginx:latest # 清理悬空镜像(没有标签的镜像) docker image prune # 导出镜像为 tar 文件 docker save -o nginx.tar nginx:latest # 从 tar 文件导入镜像 docker load -i nginx.tar
2.3 容器生命周期管理
# 运行容器(交互模式) docker run -it ubuntu:latest /bin/bash # 后台运行容器 docker run -d --name my-nginx -p 8080:80 nginx:latest # 查看运行中的容器 docker ps # 查看所有容器(包括停止的) docker ps -a # 停止容器 docker stop my-nginx # 启动已停止的容器 docker start my-nginx # 重启容器 docker restart my-nginx # 进入运行中的容器 docker exec -it my-nginx /bin/bash # 查看容器日志 docker logs my-nginx # 实时查看日志 docker logs -f my-nginx # 删除容器 docker rm my-nginx # 强制删除运行中的容器 docker rm -f my-nginx # 清理所有停止的容器 docker container prune
三、Dockerfile 编写最佳实践
3.1 基础指令详解
# 指定基础镜像 FROM python:3.9-slim # 设置工作目录 WORKDIR /app # 设置环境变量 ENV PYTHONUNBUFFERED=1 ENV APP_ENV=production # 复制依赖文件(利用 Docker 缓存层) COPY requirements.txt . # 安装依赖 RUN pip install --no-cache-dir -r requirements.txt # 复制应用代码 COPY . . # 暴露端口 EXPOSE 8000 # 设置启动命令 CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
3.2 多阶段构建优化镜像大小
多阶段构建可以显著减小最终镜像的体积,只保留运行时必需的文件:
# 构建阶段 FROM golang:1.19-alpine AS builder WORKDIR /build # 复制 go.mod 和 go.sum 以利用缓存 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 # 安装 ca-certificates(HTTPS 请求需要) RUN apk --no-cache add ca-certificates WORKDIR /root/ # 从构建阶段复制二进制文件 COPY --from=builder /build/main . # 暴露端口 EXPOSE 8080 # 运行应用 CMD ["./main"]
3.3 Dockerfile 最佳实践总结
- 使用官方基础镜像:优先选择官方维护的镜像,如 python、nginx、alpine
- 指定镜像版本:避免使用 latest 标签,明确指定版本号保证可重复性
- 使用 .dockerignore:排除不需要的文件,加快构建速度
- 合并 RUN 指令:减少镜像层数,减小镜像体积
- 利用构建缓存:将不常变化的指令放在前面
- 最小化镜像层数:每个指令都会创建一个新层
- 不要在镜像中存储敏感信息:使用环境变量或 secrets 管理
四、数据持久化与网络配置
4.1 数据卷管理
容器删除后,容器内的数据也会丢失。数据卷可以持久化存储数据,实现容器间的数据共享:
# 创建数据卷 docker volume create my-data # 查看数据卷列表 docker volume ls # 查看数据卷详情 docker volume inspect my-data # 使用数据卷运行容器 docker run -d --name mysql \ -v my-data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=root123 \ mysql:8.0 # 挂载主机目录到容器 docker run -d --name nginx \ -v /host/path:/usr/share/nginx/html:ro \ nginx:latest # 删除数据卷 docker volume rm my-data # 清理未使用的数据卷 docker volume prune
4.2 网络配置
Docker 提供了多种网络模式,满足不同的应用场景:
# 查看网络列表 docker network ls # 创建自定义网络 docker network create my-network # 创建指定子网的网络 docker network create --subnet=172.20.0.0/16 my-network # 运行容器并连接到网络 docker run -d --name web --network my-network nginx # 将运行中的容器连接到网络 docker network connect my-network existing-container # 断开容器网络连接 docker network disconnect my-network web # 查看网络详情 docker network inspect my-network # 删除网络 docker network rm my-network
4.3 网络模式详解
- bridge(桥接模式):默认模式,容器通过网桥连接到宿主机网络
- host(主机模式):容器直接使用宿主机网络,性能最佳但隔离性最差
- none(无网络):容器没有网络接口,适合完全隔离的场景
- overlay(覆盖网络):用于跨主机的容器通信,需要 Swarm 模式
五、Docker Compose 多容器编排
5.1 docker-compose.yml 编写
Docker Compose 可以定义和运行多容器应用,非常适合开发和测试环境:
version: '3.8'
services:
# Web 应用服务
web:
build: .
container_name: django-app
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/app
ports:
- "8000:8000"
environment:
- DEBUG=1
- DATABASE_URL=postgres://user:password@db:5432/mydb
depends_on:
- db
- redis
networks:
- app-network
# PostgreSQL 数据库服务
db:
image: postgres:14-alpine
container_name: postgres-db
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
- POSTGRES_DB=mydb
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- app-network
# Redis 缓存服务
redis:
image: redis:7-alpine
container_name: redis-cache
volumes:
- redis-data:/data
networks:
- app-network
# Nginx 反向代理
nginx:
image: nginx:alpine
container_name: nginx-proxy
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- web
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
postgres-data:
redis-data:
5.2 Docker Compose 常用命令
# 启动所有服务 docker-compose up -d # 查看服务状态 docker-compose ps # 查看服务日志 docker-compose logs # 实时查看特定服务日志 docker-compose logs -f web # 进入服务容器 docker-compose exec web /bin/bash # 停止所有服务 docker-compose stop # 启动已停止的服务 docker-compose start # 重启所有服务 docker-compose restart # 停止并删除所有服务 docker-compose down # 停止并删除所有服务和数据卷 docker-compose down -v # 重新构建服务镜像 docker-compose build --no-cache # 扩展服务(运行多个实例) docker-compose up -d --scale web=3
六、实战案例:部署完整的 Web 应用
6.1 项目结构
myproject/ ├── app/ │ ├── main.py │ ├── requirements.txt │ └── Dockerfile ├── nginx/ │ ├── nginx.conf │ └── Dockerfile ├── docker-compose.yml └── .env
6.2 应用 Dockerfile
# app/Dockerfile
FROM python:3.9-slim
WORKDIR /app
# 安装系统依赖
RUN apt-get update && apt-get install -y \
gcc \
&& rm -rf /var/lib/apt/lists/*
# 安装 Python 依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码
COPY . .
# 创建非 root 用户
RUN useradd -m appuser && chown -R appuser:appuser /app
USER appuser
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
6.3 应用主程序
# app/main.py
from fastapi import FastAPI
from pydantic import BaseModel
import redis
import os
# 创建 FastAPI 应用实例
app = FastAPI(title="Docker Demo API", version="1.0.0")
# 连接 Redis
redis_host = os.getenv("REDIS_HOST", "localhost")
redis_client = redis.Redis(host=redis_host, port=6379, db=0)
class Item(BaseModel):
"""数据模型定义"""
name: str
price: float
description: str = None
@app.get("/")
async def root():
"""根路径欢迎信息"""
return {"message": "Hello Docker!", "status": "running"}
@app.get("/health")
async def health_check():
"""健康检查接口"""
return {"status": "healthy"}
@app.post("/items/")
async def create_item(item: Item):
"""创建物品并存入 Redis"""
import json
item_key = f"item:{item.name}"
redis_client.set(item_key, json.dumps(item.dict()))
return {"message": "Item created", "item": item}
@app.get("/items/{item_name}")
async def get_item(item_name: str):
"""从 Redis 获取物品"""
import json
item_key = f"item:{item_name}"
item_data = redis_client.get(item_key)
if item_data:
return json.loads(item_data)
return {"error": "Item not found"}
@app.get("/counter")
async def counter():
"""访问计数器示例"""
count = redis_client.incr("visit_counter")
return {"visits": count}
6.4 Nginx 配置
# nginx/nginx.conf
events {
worker_connections 1024;
}
http {
upstream app {
server web:8000;
}
server {
listen 80;
server_name localhost;
# 静态文件缓存
location /static/ {
alias /app/static/;
expires 30d;
}
# 反向代理到应用
location / {
proxy_pass http://app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# 健康检查
location /health {
proxy_pass http://app/health;
access_log off;
}
}
}
6.5 完整的 docker-compose.yml
version: '3.8'
services:
web:
build: ./app
container_name: fastapi-app
environment:
- REDIS_HOST=redis
depends_on:
- redis
networks:
- backend
restart: unless-stopped
nginx:
image: nginx:alpine
container_name: nginx-lb
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- web
networks:
- backend
restart: unless-stopped
redis:
image: redis:7-alpine
container_name: redis-cache
volumes:
- redis-data:/data
networks:
- backend
restart: unless-stopped
networks:
backend:
driver: bridge
volumes:
redis-data:
6.6 部署流程
# 1. 克隆项目 git clonecd myproject # 2. 创建环境变量文件 cat > .env << EOF REDIS_HOST=redis EOF # 3. 构建并启动所有服务 docker-compose up -d --build # 4. 查看服务状态 docker-compose ps # 5. 查看日志 docker-compose logs -f # 6. 测试 API curl http://localhost/health curl http://localhost/counter # 7. 扩展 Web 服务 docker-compose up -d --scale web=3
七、Docker 性能优化技巧
7.1 镜像优化
- 使用 alpine 基础镜像,大幅减小镜像体积
- 多阶段构建,只保留运行时必需的文件
- 合并 RUN 指令,减少镜像层数
- 清理缓存和临时文件
7.2 运行时优化
# 限制容器资源使用 docker run -d \ --name app \ --memory="512m" \ --cpus="1.0" \ --cpu-shares=512 \ --pids-limit=100 \ my-app:latest # 设置重启策略 docker run -d --restart=unless-stopped my-app # 使用健康检查 docker run -d \ --health-cmd="curl -f http://localhost/health || exit 1" \ --health-interval=30s \ --health-timeout=5s \ --health-retries=3 \ my-app
7.3 日志管理
# 限制日志文件大小 docker run -d \ --log-driver json-file \ --log-opt max-size=10m \ --log-opt max-file=3 \ my-app # 使用 syslog 驱动 docker run -d \ --log-driver syslog \ --log-opt syslog-address=tcp://192.168.0.42:514 \ my-app
八、常见问题与解决方案
8.1 容器无法访问宿主机服务
在 Linux 上,容器可以通过 host.docker.internal 访问宿主机(需要添加 --add-host 参数):
docker run -d --add-host=host.docker.internal:host-gateway my-app
8.2 权限问题
在容器中挂载的目录可能遇到权限问题,可以通过设置正确的用户 ID 解决:
# 在 Dockerfile 中设置用户 RUN useradd -u 1000 -m myuser USER myuser
8.3 时区设置
# 方法1:挂载时区文件 docker run -v /etc/localtime:/etc/localtime:ro my-app # 方法2:设置环境变量 docker run -e TZ=Asia/Shanghai my-app
总结
Docker 容器化技术已经彻底改变了软件开发和部署的方式。通过本文的学习,你应该掌握了:
- Docker 核心概念:镜像、容器、仓库的关系和区别
- 基础操作:镜像拉取、容器运行、日志查看等日常命令
- Dockerfile 编写:如何编写高效、可维护的镜像构建脚本
- 数据持久化:数据卷的使用和数据备份策略
- 网络配置:不同网络模式的适用场景
- Docker Compose:多容器应用的编排和管理
- 性能优化:镜像瘦身、资源限制、日志管理
- 实战部署:从零构建完整的容器化 Web 应用
Docker 的学习曲线相对平缓,但要真正用好它,需要在实践中不断积累经验。建议从简单的单容器应用开始,逐步过渡到复杂的多服务架构。掌握 Docker 后,你将能更高效地进行开发、测试和部署,为后续学习 Kubernetes 等容器编排工具打下坚实基础。
本文链接:https://www.kkkliao.cn/?id=919 转载需授权!
版权声明:本文由廖万里的博客发布,如需转载请注明出处。



手机流量卡
免费领卡
号卡合伙人
产品服务
关于本站
