余白

Docker 介绍与使用

什么是 Docker

Docker 是一个开源的容器化平台,让你可以打包应用及其依赖到一个可移植的容器中,然后在任何支持 Docker 的环境中运行。

核心概念

概念说明
镜像(Image)应用程序的只读模板,包含运行应用所需的所有内容
容器(Container)镜像的运行实例,类似轻量级虚拟机
仓库(Registry)存储和分发镜像的地方,最常用的是 Docker Hub
Dockerfile定义镜像构建步骤的配置文件

容器 vs 虚拟机

特性Docker 容器虚拟机
启动速度秒级分钟级
资源占用很小(MB 级)较大(GB 级)
性能接近原生有一定损耗
隔离性进程级隔离完全隔离
操作系统共享宿主机内核独立操作系统

安装 Docker

Ubuntu/Debian

# 1. 卸载旧版本(如有)
sudo apt remove docker docker-engine docker.io containerd runc

# 2. 安装依赖
sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release

# 3. 添加 Docker GPG 密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 4. 添加 Docker 仓库
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

# 5. 安装 Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 6. 验证安装
sudo docker run hello-world

启动并设置开机自启

sudo systemctl start docker
sudo systemctl enable docker

非 Root 用户免 sudo

sudo usermod -aG docker $USER
# 重新登录生效,或执行
newgrp docker

macOS / Windows

下载 Docker Desktop 安装包进行安装。


基础命令

镜像操作

# 搜索镜像
docker search nginx

# 拉取镜像
docker pull nginx:latest

# 列出本地镜像
docker images
docker images -a        # 包含中间层

# 删除镜像
docker rmi nginx:latest

# 构建镜像(根据 Dockerfile)
docker build -t myapp:1.0 .

# 导出/导入镜像
docker save -o myapp.tar myapp:1.0
docker load -i myapp.tar

# 查看镜像详情
docker inspect nginx:latest

容器操作

# 运行容器(最常用)
docker run nginx                          # 后台运行
docker run -it nginx /bin/bash            # 交互式运行
docker run -d nginx                        # 后台守护式运行
docker run --name mynginx nginx            # 指定容器名称

# 常见选项
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

# 常用选项:
# -d              后台运行
# -it             交互式终端
# --name          容器名称
# -p 8080:80      端口映射(宿主机:容器)
# -v /host:/container    卷挂载
# -e KEY=VALUE    设置环境变量
# --network       指定网络
# --rm            容器停止后自动删除
# --restart       重启策略(no/on-failure/always/unless-stopped)

# 列出运行中的容器
docker ps

# 列出所有容器(包括已停止)
docker ps -a

# 启动/停止/重启容器
docker start mynginx
docker stop mynginx
docker restart mynginx

# 删除容器
docker rm mynginx
docker rm -f mynginx           # 强制删除(运行中也可删)

# 进入运行中的容器
docker exec -it mynginx /bin/bash
docker exec -it mynginx sh     # 很多容器没有 bash

# 查看容器日志
docker logs mynginx
docker logs -f mynginx          # 实时跟踪

# 查看容器进程
docker top mynginx

# 查看容器详细信息
docker inspect mynginx

进入容器的替代方法

# 如果容器已经在运行
docker attach mynginx

# 推荐方式(exec)
docker exec -it mynginx /bin/sh

进阶命令

Docker Compose

Docker Compose 用于定义和运行多容器应用。

安装(新版 Docker 已内置):

docker compose version

示例 docker-compose.yml:

version: '3.8'

services:
  web:
    image: nginx:latest
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html
    depends_on:
      - redis
    networks:
      - mynet

  redis:
    image: redis:alpine
    networks:
      - mynet

networks:
  mynet:

常用命令:

docker compose up -d           # 后台启动所有服务
docker compose up --build      # 构建并启动
docker compose down            # 停止并删除容器
docker compose down -v         # 删除容器和卷
docker compose ps              # 查看状态
docker compose logs -f         # 查看日志
docker compose restart         # 重启
docker compose exec web sh      # 在服务中执行命令
docker compose build           # 构建镜像
docker compose pull             # 拉取依赖镜像

清理资源

# 删除已停止的容器
docker container prune

# 删除未使用的镜像
docker image prune
docker image prune -a          # 删除所有未使用镜像

# 删除未使用的卷
docker volume prune

# 删除未使用的网络
docker network prune

# 一键清理所有未使用资源
docker system prune
docker system prune -a          # 清理更多(包括未使用的镜像)

查看资源使用

docker stats              # 实时显示资源使用
docker stats --no-stream  # 单次显示

实战示例

1. 运行一个 Web 服务

docker run -d \
    --name mynginx \
    -p 8080:80 \
    nginx:latest

# 访问 http://localhost:8080

2. 运行 MySQL 数据库

docker run -d \
    --name mysql \
    -p 3306:3306 \
    -e MYSQL_ROOT_PASSWORD=mysecretpassword \
    -e MYSQL_DATABASE=myapp \
    -v mysql_data:/var/lib/mysql \
    mysql:8.0

# 连接:mysql -h localhost -P 3306 -u root -p

3. 运行 Redis

docker run -d \
    --name redis \
    -p 6379:6379 \
    redis:alpine

# 使用 redis-cli 连接
docker exec -it redis redis-cli

4. 使用 Docker Compose 运行 LNMP

# docker-compose.yml
version: '3'
services:
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./html:/usr/share/nginx/html
    depends_on:
      - php
    networks:
      - app-net

  php:
    image: php:8.2-fpm
    volumes:
      - ./html:/var/www/html
    networks:
      - app-net

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: myapp
    volumes:
      - mysql_data:/var/lib/mysql
    networks:
      - app-net

volumes:
  mysql_data:

networks:
  app-net:
    driver: bridge

启动:

docker compose up -d

5. 构建自定义镜像

创建 Dockerfile:

# 基于官方镜像
FROM node:18-alpine

# 设置工作目录
WORKDIR /app

# 复制文件
COPY package*.json ./

# 安装依赖
RUN npm install --production

# 复制源代码
COPY . .

# 暴露端口
EXPOSE 3000

# 启动命令
CMD ["node", "server.js"]

构建并运行:

docker build -t myapp:1.0 .
docker run -d --name myapp -p 3000:3000 myapp:1.0

Dockerfile 常用指令

指令说明
FROM指定基础镜像
RUN执行命令
COPY复制文件
ADD复制文件(支持 URL 和解压)
WORKDIR设置工作目录
ENV设置环境变量
EXPOSE声明端口
CMD容器启动命令
ENTRYPOINT入口点
VOLUME定义卷
ARG构建参数

CMD vs ENTRYPOINT

# CMD:默认命令,可被 docker run 参数覆盖
CMD ["echo", "hello"]

# ENTRYPOINT:固定入口,参数附加在其后
ENTRYPOINT ["echo", "hello"]
# docker run image world  →  输出 "hello world"

数据管理

挂载宿主目录

docker run -v /host/path:/container/path nginx

使用 Docker 卷

# 创建卷
docker volume create mydata

# 使用卷
docker run -v mydata:/data nginx

# 查看卷
docker volume ls
docker volume inspect mydata

# 删除未使用卷
docker volume prune

数据备份

# 备份
docker run --rm -v mydata:/data -v $(pwd):/backup alpine tar czf /backup/backup.tar.gz /data

# 恢复
docker run --rm -v mydata:/data -v $(pwd):/backup alpine tar xzf /backup/backup.tar.gz -C /

网络配置

网络模式

模式说明
bridge默认模式,容器连接到 bridge 网络
host容器共享宿主机的网络命名空间
none禁用网络
overlay跨 Docker 守护进程通信
macvlan为容器分配 MAC 地址

创建自定义网络

docker network create mynet
docker network ls

# 容器加入网络
docker run --network=mynet nginx

# 连接已运行的容器到网络
docker network connect mynet mynginx

容器间通信

# docker-compose.yml 中自动创建网络
services:
  web:
    networks:
      - mynet
  db:
    networks:
      - mynet

networks:
  mynet:

Docker 镜像加速

中国镜像加速器

创建或编辑 /etc/docker/daemon.json:

{
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://docker.xuanyuan.me"
  ]
}

应用配置:

sudo systemctl daemon-reload
sudo systemctl restart docker

验证:

docker info | grep -A 10 "Registry Mirrors"

常用场景

1. 开发环境隔离

# 每个项目独立的开发环境
docker run -d --name project1-db -e MYSQL_ROOT_PASSWORD=secret mysql:8.0

2. 一键部署应用

docker compose up -d --build

3. 定时任务容器化

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "task.py"]

4. 临时测试环境

# 用完即删
docker run --rm -it python:3.11 python

常见问题

容器内中文乱码

docker run -e LANG=C.UTF-8 nginx

容器时间不同步

docker run -v /etc/localtime:/etc/localtime:ro nginx

查看容器 IP

docker inspect -f '{{.NetworkSettings.IPAddress}}' mynginx

容器无法访问外网

# 重启 Docker
sudo systemctl restart docker

# 检查 iptables
sudo iptables -L -n

Docker 太占空间

docker system prune -a      # 清理
docker volume prune        # 清理卷