Docker 完全教程
Docker 是一个开源的容器化平台,让你可以将应用及其依赖打包到一个轻量级、可移植的容器中,在任何环境中一致运行。
为什么选择 Docker?
- 一致性:开发、测试、生产环境完全一致
- 轻量级:比虚拟机更快、更小
- 可移植:一次构建,到处运行
- 隔离性:应用之间互不干扰
- 版本控制:镜像可以像代码一样管理
核心概念
镜像(Image)
镜像是一个只读的模板,包含运行应用所需的一切:代码、运行时、库、环境变量、配置文件。
容器(Container)
容器是镜像的运行实例,是一个独立的、可执行的软件包。
Dockerfile
Dockerfile 是一个文本文件,包含构建镜像的指令。
Docker Hub
Docker Hub 是官方的镜像仓库,类似于 GitHub。
安装 Docker
macOS
# 使用 Homebrew
brew install --cask docker
# 或下载 Docker Desktop
# https://www.docker.com/products/docker-desktopLinux (Ubuntu)
# 更新包索引
sudo apt-get update
# 安装依赖
sudo apt-get install \
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-worldWindows
下载并安装 Docker Desktop for Windows: https://www.docker.com/products/docker-desktop
基础命令
镜像操作
# 搜索镜像
docker search nginx
# 拉取镜像
docker pull nginx
docker pull nginx:1.21 # 指定版本
# 列出本地镜像
docker images
# 删除镜像
docker rmi nginx
docker rmi $(docker images -q) # 删除所有镜像
# 构建镜像
docker build -t myapp:1.0 .
# 标记镜像
docker tag myapp:1.0 username/myapp:1.0
# 推送镜像
docker push username/myapp:1.0容器操作
# 运行容器
docker run nginx
docker run -d nginx # 后台运行
docker run -d -p 8080:80 nginx # 端口映射
docker run -d -p 8080:80 --name my-nginx nginx # 指定名称
# 列出容器
docker ps # 运行中的容器
docker ps -a # 所有容器
# 停止容器
docker stop my-nginx
docker stop $(docker ps -q) # 停止所有容器
# 启动容器
docker start my-nginx
# 重启容器
docker restart my-nginx
# 删除容器
docker rm my-nginx
docker rm $(docker ps -aq) # 删除所有容器
# 查看容器日志
docker logs my-nginx
docker logs -f my-nginx # 实时查看
# 进入容器
docker exec -it my-nginx bash
# 查看容器详情
docker inspect my-nginx
# 查看容器资源使用
docker statsDockerfile
基本结构
# 基础镜像
FROM node:18-alpine
# 设置工作目录
WORKDIR /app
# 复制文件
COPY package*.json ./
# 安装依赖
RUN npm install
# 复制应用代码
COPY . .
# 暴露端口
EXPOSE 3000
# 启动命令
CMD ["npm", "start"]常用指令
# FROM:指定基础镜像
FROM ubuntu:22.04
# LABEL:添加元数据
LABEL maintainer="your@email.com"
LABEL version="1.0"
# ENV:设置环境变量
ENV NODE_ENV=production
ENV PORT=3000
# WORKDIR:设置工作目录
WORKDIR /app
# COPY:复制文件
COPY src/ /app/src/
COPY package.json .
# ADD:复制文件(支持 URL 和自动解压)
ADD https://example.com/file.tar.gz /tmp/
ADD archive.tar.gz /app/
# RUN:执行命令(构建时)
RUN apt-get update && apt-get install -y curl
RUN npm install
# CMD:容器启动命令(可被覆盖)
CMD ["node", "server.js"]
# ENTRYPOINT:容器入口点(不可被覆盖)
ENTRYPOINT ["docker-entrypoint.sh"]
# EXPOSE:声明端口
EXPOSE 3000 8080
# VOLUME:创建挂载点
VOLUME ["/data"]
# USER:指定运行用户
USER node
# ARG:构建参数
ARG VERSION=1.0
RUN echo "Building version $VERSION"多阶段构建
减小镜像大小,提高安全性。
# 构建阶段
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 运行阶段
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/server.js"]实战示例
Node.js 应用
Dockerfile:
FROM node:18-alpine
WORKDIR /app
# 复制依赖文件
COPY package*.json ./
# 安装依赖
RUN npm ci --only=production
# 复制应用代码
COPY . .
# 暴露端口
EXPOSE 3000
# 非 root 用户运行
USER node
# 启动应用
CMD ["node", "server.js"]构建和运行:
# 构建镜像
docker build -t my-node-app .
# 运行容器
docker run -d -p 3000:3000 --name node-app my-node-app
# 查看日志
docker logs -f node-appGo 应用
# 构建阶段
FROM golang:1.21 AS builder
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o server .
# 运行阶段
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/server .
EXPOSE 8080
CMD ["./server"]Python 应用
FROM python:3.11-slim
WORKDIR /app
# 安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用
COPY . .
EXPOSE 8000
CMD ["python", "app.py"]Docker Compose
Docker Compose 用于定义和运行多容器应用。
安装
# macOS/Windows:Docker Desktop 已包含
# Linux
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-composedocker-compose.yml
version: '3.8'
services:
# Web 应用
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://postgres:password@db:5432/mydb
depends_on:
- db
- redis
volumes:
- ./logs:/app/logs
networks:
- app-network
# 数据库
db:
image: postgres:15
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
- POSTGRES_DB=mydb
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- app-network
# Redis
redis:
image: redis:7-alpine
networks:
- app-network
# Nginx
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- web
networks:
- app-network
volumes:
postgres-data:
networks:
app-network:
driver: bridgeCompose 命令
# 启动服务
docker-compose up
docker-compose up -d # 后台运行
# 停止服务
docker-compose down
docker-compose down -v # 同时删除 volumes
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs
docker-compose logs -f web # 查看特定服务
# 执行命令
docker-compose exec web bash
# 重启服务
docker-compose restart
# 构建镜像
docker-compose build
docker-compose build --no-cache # 不使用缓存数据管理
Volume(卷)
# 创建 volume
docker volume create my-data
# 列出 volumes
docker volume ls
# 查看 volume 详情
docker volume inspect my-data
# 使用 volume
docker run -d -v my-data:/app/data nginx
# 删除 volume
docker volume rm my-data
docker volume prune # 删除未使用的 volumesBind Mount(绑定挂载)
# 挂载主机目录
docker run -d -v /host/path:/container/path nginx
# 只读挂载
docker run -d -v /host/path:/container/path:ro nginx网络
网络类型
- bridge:默认网络,容器间可通信
- host:使用主机网络
- none:无网络
- overlay:跨主机通信(Swarm)
网络命令
# 创建网络
docker network create my-network
# 列出网络
docker network ls
# 查看网络详情
docker network inspect my-network
# 连接容器到网络
docker network connect my-network my-container
# 断开连接
docker network disconnect my-network my-container
# 删除网络
docker network rm my-network容器间通信
# 创建网络
docker network create app-net
# 运行容器
docker run -d --name db --network app-net postgres
docker run -d --name web --network app-net -p 3000:3000 my-app
# web 容器可以通过 'db' 访问数据库
# 例如:postgresql://postgres:password@db:5432/mydb最佳实践
1. 使用 .dockerignore
node_modules
npm-debug.log
.git
.env
*.md
.DS_Store2. 最小化层数
# 不好
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y git
# 好
RUN apt-get update && \
apt-get install -y curl git && \
rm -rf /var/lib/apt/lists/*3. 利用缓存
# 先复制依赖文件
COPY package*.json ./
RUN npm install
# 再复制代码(代码变化不会重新安装依赖)
COPY . .4. 使用小镜像
# 不好
FROM node:18 # ~900MB
# 好
FROM node:18-alpine # ~170MB5. 非 root 用户
# 创建用户
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
# 切换用户
USER nodejs6. 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:3000/health || exit 17. 使用多阶段构建
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm run build
FROM node:18-alpine
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/server.js"]常见问题
清理资源
# 删除停止的容器
docker container prune
# 删除未使用的镜像
docker image prune
# 删除未使用的 volumes
docker volume prune
# 删除未使用的网络
docker network prune
# 清理所有未使用的资源
docker system prune -a查看资源使用
# 查看磁盘使用
docker system df
# 查看容器资源使用
docker stats调试容器
# 查看容器日志
docker logs -f container-name
# 进入容器
docker exec -it container-name sh
# 查看容器进程
docker top container-name
# 查看容器变化
docker diff container-name生产环境部署
使用 Docker Swarm
# 初始化 Swarm
docker swarm init
# 部署服务
docker stack deploy -c docker-compose.yml myapp
# 查看服务
docker service ls
# 扩展服务
docker service scale myapp_web=3使用 Kubernetes
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:1.0
ports:
- containerPort: 3000安全建议
- 使用官方镜像
- 定期更新镜像
- 扫描漏洞:
docker scan myapp:1.0 - 最小权限原则
- 不在镜像中存储敏感信息
- 使用 secrets 管理密码
常用工具
- Portainer:Docker 可视化管理
- Watchtower:自动更新容器
- Traefik:反向代理和负载均衡
- Docker Bench:安全检查工具
总结
Docker 是现代应用部署的标准工具。掌握 Docker 可以让你:
- 简化开发环境配置
- 确保环境一致性
- 快速部署和扩展应用
- 提高资源利用率
开始使用 Docker,让你的应用部署更加简单高效!
