从零开始掌握容器化技术
目录
- 什么是 Docker?
- 核心概念
- 安装 Docker
- 基本命令
- Dockerfile 编写
- Docker Compose
- 数据持久化
- 网络管理
- 实战示例:部署 Node.js 应用
- 常见问题与技巧
- 总结
什么是 Docker?
Docker 是一个开源的容器化平台,让开发者可以将应用及其依赖打包到一个轻量级、可移植的容器中,从而实现"一次构建,到处运行"。
为什么使用 Docker?
| 传统部署 | Docker 容器化 |
|---|---|
| 环境配置繁琐 | 环境一致性保证 |
| 依赖冲突频繁 | 依赖隔离 |
| 扩容困难 | 秒级启停,弹性扩缩 |
| 资源利用率低 | 轻量高效,共享宿主内核 |
核心概念
镜像(Image)
镜像是一个只读的模板,包含运行应用所需的代码、运行时、库和配置。可以把它理解为一个"快照"或"安装包"。
镜像 = 操作系统层 + 运行时 + 应用代码 + 依赖
容器(Container)
容器是镜像的运行实例。一个镜像可以启动多个容器,每个容器相互隔离。
容器 = 镜像 + 可写层 + 运行进程
仓库(Registry)
仓库用于存储和分发镜像。最常用的是 Docker Hub,也可以搭建私有仓库。
Docker Hub = GitHub(但存放的是镜像,不是代码)
安装 Docker
macOS / Windows
从 Docker 官网 下载并安装 Docker Desktop,安装完成后即可使用。
⚠️ 注意授权:Docker Desktop 对个人、教育及小型企业(员工 < 250 人且年收入 < 1000 万美元)免费;超出此范围的商业用途需购买付费订阅。
Linux(Ubuntu 为例)
# 更新包索引
sudo apt-get update
# 安装依赖
sudo apt-get install -y ca-certificates curl gnupg
# 添加 Docker 官方 GPG 密钥
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 添加仓库
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装 Docker
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
# 验证安装
docker --version
验证安装
docker run hello-world
看到 Hello from Docker! 说明安装成功 🎉
基本命令
镜像操作
# 搜索镜像
docker search nginx
# 拉取镜像(不指定标签默认拉取 latest)
docker pull nginx
docker pull nginx:1.25
# 查看本地镜像
docker images
# 删除镜像
docker rmi nginx:latest
# 构建镜像
docker build -t my-app:1.0 .
容器操作
# 运行容器
docker run nginx
# 后台运行(-d: detach)
docker run -d nginx
# 指定名称 + 端口映射
docker run -d --name my-nginx -p 8080:80 nginx
# 交互模式进入容器
docker run -it ubuntu bash
# 查看运行中的容器
docker ps
# 查看所有容器(包括已停止)
docker ps -a
# 停止 / 启动 / 重启容器
docker stop my-nginx
docker start my-nginx
docker restart my-nginx
# 删除容器(需先停止)
docker rm my-nginx
docker rm -f my-nginx # 强制删除运行中的容器
# 进入运行中的容器
docker exec -it my-nginx bash
# 查看容器日志
docker logs my-nginx
docker logs -f my-nginx # 实时跟踪日志
# 查看容器详细信息
docker inspect my-nginx
系统清理
# 删除所有停止的容器
docker container prune
# 删除未使用的镜像
docker image prune
# 一键清理所有未使用资源
docker system prune -a
Dockerfile 编写
Dockerfile 是构建镜像的配置文件,每条指令对应镜像的一层。
常用指令
| 指令 | 说明 |
|---|---|
FROM | 指定基础镜像 |
WORKDIR | 设置工作目录 |
COPY | 复制文件到镜像 |
ADD | 复制文件(支持URL和解压tar) |
RUN | 构建时执行命令 |
ENV | 设置环境变量 |
EXPOSE | 声明容器监听端口 |
CMD | 容器启动时执行的默认命令 |
ENTRYPOINT | 容器启动入口点 |
示例:Python Flask 应用
# 1. 指定基础镜像
FROM python:3.11-slim
# 2. 设置工作目录
WORKDIR /app
# 3. 先复制依赖文件(利用构建缓存)
COPY requirements.txt .
# 4. 安装依赖
RUN pip install --no-cache-dir -r requirements.txt
# 5. 复制应用代码
COPY . .
# 6. 设置环境变量
ENV FLASK_APP=app.py
ENV FLASK_ENV=production
# 7. 暴露端口
EXPOSE 5000
# 8. 启动命令
CMD ["flask", "run", "--host=0.0.0.0"]
构建与运行
# 构建镜像
docker build -t flask-app:latest .
# 运行容器
docker run -d -p 5000:5000 --name flask-app flask-app:latest
.dockerignore 文件
类似 .gitignore,排除不需要打包的文件:
__pycache__/
*.pyc
.env
.git
node_modules/
*.log
Docker Compose
Docker Compose 用于定义和管理多容器应用,通过一个 YAML 文件描述所有服务。
安装
Docker Desktop 已内置 Compose;Linux 用户执行:
sudo apt-get install docker-compose-plugin
docker compose version
docker-compose.yml 示例
以下是一个包含 Web 应用、数据库和缓存的典型配置:
version: '3.8'
services:
# Web 应用
web:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:password@db:5432/mydb
- REDIS_URL=redis://redis:6379
depends_on:
- db
- redis
volumes:
- ./app:/app
restart: unless-stopped
# PostgreSQL 数据库
db:
image: postgres:15
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
# Redis 缓存
redis:
image: redis:7-alpine
ports:
- "6379:6379"
# 数据卷
volumes:
postgres_data:
Compose 常用命令
# 启动所有服务(后台)
docker compose up -d
# 查看服务状态
docker compose ps
# 查看日志
docker compose logs -f web
# 停止服务
docker compose stop
# 停止并删除容器
docker compose down
# 停止并删除容器、镜像、数据卷
docker compose down --volumes --rmi all
# 重新构建镜像
docker compose build
# 进入某个服务的容器
docker compose exec web bash
数据持久化
容器删除后,容器内的数据会一起消失。Docker 提供三种数据持久化方式:
1. Volume(推荐)
由 Docker 管理,存储在宿主机的 /var/lib/docker/volumes/ 目录。
# 创建 volume
docker volume create mydata
# 使用 volume
docker run -d -v mydata:/app/data nginx
# 查看所有 volume
docker volume ls
# 删除 volume
docker volume rm mydata
2. Bind Mount(绑定挂载)
将宿主机目录直接挂载到容器,适合开发阶段实时同步代码。
# 将当前目录挂载到容器的 /app
docker run -d -v $(pwd):/app -p 3000:3000 node-app
3. tmpfs Mount
数据存储在宿主机内存中,容器停止后消失,适合存储敏感临时数据。
docker run -d --tmpfs /tmp nginx
网络管理
Docker 网络类型
| 类型 | 说明 |
|---|---|
bridge | 默认网络,容器间可通过容器名互通 |
host | 共享宿主机网络,性能最好 |
none | 无网络,完全隔离 |
overlay | 跨主机容器通信(Swarm 集群) |
自定义网络
# 创建自定义网络
docker network create my-network
# 在指定网络中运行容器
docker run -d --network my-network --name app my-app
docker run -d --network my-network --name db postgres
# 此时 app 容器可以直接用 "db" 作为主机名访问数据库
# 查看网络
docker network ls
docker network inspect my-network
# 删除网络
docker network rm my-network
实战示例:部署 Node.js 应用
项目结构
my-node-app/
├── src/
│ └── index.js
├── package.json
├── Dockerfile
├── .dockerignore
└── docker-compose.yml
src/index.js
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.json({ message: 'Hello from Docker!', env: process.env.NODE_ENV });
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Dockerfile
FROM node:20-alpine
WORKDIR /app
# 先复制 package 文件,充分利用缓存
COPY package*.json ./
RUN npm ci --only=production
COPY src/ ./src/
ENV NODE_ENV=production
EXPOSE 3000
# 使用非 root 用户运行(安全最佳实践)
USER node
CMD ["node", "src/index.js"]
docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
NODE_ENV: production
restart: unless-stopped
部署步骤
# 1. 构建并启动
docker compose up -d --build
# 2. 验证运行
curl http://localhost:3000
# 3. 查看日志
docker compose logs -f app
常见问题与技巧
减小镜像体积
# ✅ 使用 alpine 版本
FROM node:20-alpine # ~50MB vs node:20 ~1GB
# ✅ 合并 RUN 命令,减少层数
RUN apt-get update && \
apt-get install -y curl && \
rm -rf /var/lib/apt/lists/*
# ✅ 多阶段构建(适合编译型语言)
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o server .
FROM alpine:latest # 最终镜像只包含可执行文件
COPY --from=builder /app/server .
CMD ["./server"]
常用快捷操作
# 删除所有停止的容器
docker rm $(docker ps -aq -f status=exited)
# 删除所有 <none> 镜像(悬空镜像)
docker rmi $(docker images -f "dangling=true" -q)
# 查看容器资源使用情况
docker stats
# 从容器复制文件到宿主机
docker cp my-container:/app/logs ./logs
# 将容器保存为镜像
docker commit my-container my-snapshot:v1
安全建议
- 不要以 root 用户运行:在 Dockerfile 中添加
USER node(或其他非root用户) - 不要在镜像中硬编码密码:使用环境变量或 Docker Secrets
- 定期更新基础镜像:及时获取安全补丁
- 使用
.dockerignore:避免将.env、密钥等敏感文件打包进镜像 - 扫描镜像漏洞:使用
docker scout或 Trivy 等工具
总结
| 场景 | 命令/工具 |
|---|---|
| 运行单个容器 | docker run |
| 构建自定义镜像 | Dockerfile + docker build |
| 管理多容器应用 | docker-compose.yml + docker compose up |
| 数据持久化 | Volume / Bind Mount |
| 容器间通信 | 自定义网络 |
掌握这些核心知识,你已经具备在生产环境中使用 Docker 的基础能力。下一步可以探索 Kubernetes(容器编排)和 CI/CD 集成,进一步提升你的云原生技术栈!
Happy Dockerizing! 🐳