Docker
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 或 Windows 操作系统的机器上。本教程将帮助你掌握 Docker 的基本概念和使用方法。
Docker 简介
什么是 Docker?
Docker 是一个开源平台,它使用容器技术来简化应用的部署和管理。Docker 容器将软件及其依赖项打包成标准化单元,确保应用程序在任何环境中都能以相同的方式运行。
Docker 的主要组件
- Docker 引擎:用于构建和运行容器的核心软件
- Docker 镜像:容器的只读模板,包含运行应用所需的一切
- Docker 容器:镜像的运行实例,可以启动、停止、移动或删除
- Docker 注册表:存储和分发 Docker 镜像的仓库,如 Docker Hub
- Dockerfile:用于自动构建 Docker 镜像的脚本文件
Docker 与虚拟机的区别
特性 | Docker 容器 | 虚拟机 |
---|---|---|
启动时间 | 秒级 | 分钟级 |
占用磁盘空间 | MB 级 | GB 级 |
性能 | 接近原生 | 有一定损耗 |
隔离级别 | 进程级隔离 | 完全隔离 |
操作系统 | 共享主机内核 | 独立操作系统 |
安装 Docker
Windows 安装
- 下载并安装 Docker Desktop for Windows
- 启动 Docker Desktop
- 验证安装:打开命令提示符或 PowerShell,运行
docker --version
macOS 安装
- 下载并安装 Docker Desktop for Mac
- 启动 Docker Desktop
- 验证安装:打开终端,运行
docker --version
Linux 安装 (Ubuntu)
bash
# 更新包索引
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 引擎
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
# 验证安装
sudo docker run hello-world
Docker 基本概念
镜像 (Images)
Docker 镜像是一个只读模板,包含创建 Docker 容器的指令。镜像可以包含一个完整的操作系统、应用程序和所有依赖项。
bash
# 列出本地镜像
docker images
# 拉取镜像
docker pull ubuntu:20.04
# 搜索镜像
docker search nginx
# 删除镜像
docker rmi image_id
容器 (Containers)
容器是镜像的运行实例,可以被启动、停止、删除。每个容器都是相互隔离的。
bash
# 运行容器
docker run -it ubuntu:20.04 bash
# 列出运行中的容器
docker ps
# 列出所有容器(包括已停止的)
docker ps -a
# 启动/停止容器
docker start container_id
docker stop container_id
# 删除容器
docker rm container_id
数据卷 (Volumes)
数据卷是 Docker 容器中数据持久化的机制,它们独立于容器的生命周期。
bash
# 创建数据卷
docker volume create my_volume
# 列出数据卷
docker volume ls
# 在容器中使用数据卷
docker run -v my_volume:/app nginx
# 使用主机目录作为数据卷
docker run -v /host/path:/container/path nginx
网络 (Networks)
Docker 网络允许容器之间以及容器与外部世界通信。
bash
# 创建网络
docker network create my_network
# 列出网络
docker network ls
# 在指定网络中运行容器
docker run --network=my_network nginx
# 将容器连接到网络
docker network connect my_network container_id
Docker 基本操作
运行容器
bash
# 基本运行
docker run nginx
# 后台运行
docker run -d nginx
# 指定名称
docker run --name my_nginx nginx
# 映射端口
docker run -p 8080:80 nginx
# 交互式终端
docker run -it ubuntu bash
# 环境变量
docker run -e MYSQL_ROOT_PASSWORD=password mysql
管理容器
bash
# 查看容器日志
docker logs container_id
# 在运行中的容器中执行命令
docker exec -it container_id bash
# 查看容器详细信息
docker inspect container_id
# 查看容器资源使用情况
docker stats
# 复制文件到容器
docker cp file.txt container_id:/path
# 从容器复制文件
docker cp container_id:/path/file.txt .
构建镜像
使用 Dockerfile
Dockerfile 是一个文本文件,包含构建 Docker 镜像的所有命令。
dockerfile
# 基础镜像
FROM node:14
# 设置工作目录
WORKDIR /app
# 复制依赖文件
COPY package*.json ./
# 安装依赖
RUN npm install
# 复制源代码
COPY . .
# 暴露端口
EXPOSE 3000
# 启动命令
CMD ["npm", "start"]
构建镜像:
bash
docker build -t my-app:1.0 .
常用 Dockerfile 指令
- FROM:指定基础镜像
- WORKDIR:设置工作目录
- COPY/ADD:复制文件到镜像
- RUN:执行命令并创建新层
- ENV:设置环境变量
- EXPOSE:声明容器监听的端口
- VOLUME:创建挂载点
- CMD:容器启动命令
- ENTRYPOINT:容器入口点
镜像管理
bash
# 为镜像添加标签
docker tag image_id username/repository:tag
# 推送镜像到 Docker Hub
docker push username/repository:tag
# 保存镜像到文件
docker save -o image.tar image_name
# 从文件加载镜像
docker load -i image.tar
# 查看镜像历史
docker history image_name
Docker Compose
Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。
安装 Docker Compose
bash
# Linux
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Windows 和 macOS
# Docker Desktop 已包含 Docker Compose
docker-compose.yml 文件
yaml
version: '3'
services:
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
depends_on:
- db
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: example
MYSQL_DATABASE: app
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
基本命令
bash
# 启动服务
docker-compose up
# 后台启动
docker-compose up -d
# 停止服务
docker-compose down
# 查看服务状态
docker-compose ps
# 查看服务日志
docker-compose logs
# 执行命令
docker-compose exec web bash
Docker 实战示例
部署 Web 应用
Node.js 应用
dockerfile
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
bash
docker build -t my-node-app .
docker run -p 3000:3000 my-node-app
使用 Docker Compose 部署 MEAN 栈
yaml
version: '3'
services:
frontend:
build: ./frontend
ports:
- "80:80"
depends_on:
- backend
backend:
build: ./backend
ports:
- "3000:3000"
environment:
- MONGODB_URI=mongodb://db:27017/myapp
depends_on:
- db
db:
image: mongo:4.4
volumes:
- mongo_data:/data/db
volumes:
mongo_data:
数据库容器
MySQL
bash
docker run -d \
--name mysql \
-e MYSQL_ROOT_PASSWORD=my-secret-pw \
-e MYSQL_DATABASE=mydb \
-v mysql_data:/var/lib/mysql \
-p 3306:3306 \
mysql:5.7
PostgreSQL
bash
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=my-secret-pw \
-e POSTGRES_DB=mydb \
-v postgres_data:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:13
MongoDB
bash
docker run -d \
--name mongodb \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=password \
-v mongo_data:/data/db \
-p 27017:27017 \
mongo:4.4
Docker 最佳实践
镜像优化
- 使用官方镜像:优先使用官方维护的镜像
- 使用特定标签:避免使用
latest
标签 - 多阶段构建:减小最终镜像大小
dockerfile
# 构建阶段
FROM node:14 AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
- 最小化层数:合并 RUN 命令减少层数
- 清理不必要的文件:删除缓存和临时文件
安全最佳实践
- 使用非 root 用户:
dockerfile
FROM node:14
RUN groupadd -r appuser && useradd -r -g appuser appuser
WORKDIR /app
COPY --chown=appuser:appuser . .
USER appuser
CMD ["node", "app.js"]
- 扫描镜像漏洞:使用 Docker Scout、Trivy 等工具
- 使用内容信任:签名和验证镜像
- 限制容器资源:设置内存和 CPU 限制
- 使用只读文件系统:
docker run --read-only ...
容器编排
对于生产环境,考虑使用容器编排平台:
- Kubernetes:大规模容器编排平台
- Docker Swarm:Docker 原生集群管理工具
- Amazon ECS:AWS 的容器编排服务
- Azure Container Instances:Azure 的容器服务
监控和日志
- 集中式日志管理:使用 ELK 栈或 Prometheus + Grafana
- 健康检查:实现容器健康检查
- 资源监控:监控容器 CPU、内存使用情况
Docker 常见问题解答
容器无法访问网络
检查以下几点:
- DNS 配置是否正确
- 网络模式是否适合您的用例
- 防火墙规则是否阻止了连接
容器启动后立即退出
容器需要在前台运行一个进程,如果主进程退出,容器也会退出。解决方法:
- 确保 CMD 或 ENTRYPOINT 指令正确
- 检查应用程序是否正确运行
- 使用
docker logs
查看错误信息
数据持久化问题
使用数据卷或绑定挂载来持久化数据:
- 数据卷:
docker run -v my_volume:/app/data ...
- 绑定挂载:
docker run -v /host/path:/container/path ...
容器间通信
容器可以通过以下方式通信:
- 使用用户定义的网络:
docker network create my_network
- 使用 Docker Compose 定义服务
- 使用容器名称作为主机名
Docker 占用磁盘空间过大
清理未使用的资源:
bash
# 删除所有停止的容器
docker container prune
# 删除未使用的镜像
docker image prune
# 删除未使用的数据卷
docker volume prune
# 删除所有未使用的对象
docker system prune
相关资源
本文档将持续更新,如有问题请通过 GitHub Issues 反馈。