Docker 概述

Docker 是一个开源的应用容器引擎,Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

应用场景

  • 微服务架构:每个服务独立容器化,便于管理和扩展。
  • CI/CD 流水线:与 Jenkins/GitLab CI 集成,实现自动化构建和测试。
  • 开发环境标准化:新成员一键启动全套依赖服务
  • 云原生基础:Kubernetes 等编排工具基于 Docker 管理容器集群。

容器基本架构

2f8f9b1e4e857b300d1746ce5b18df4f

传统应用部署的痛点

  • 环境不一致:应用在开发环境运行正常,但在测试或生产环境出现问题
  • 依赖管理复杂:不同应用需要不同版本的运行时、库文件等
  • 资源利用率低:传统虚拟机需要完整的操作系统,占用大量资源
  • 部署复杂:需要手动配置环境、安装依赖,容易出错

容器化技术的解决方案

  • 环境标准化:将应用及其依赖打包在一起,确保在任何环境中都能一致运行
  • 轻量级:容器共享宿主机的操作系统内核,比虚拟机更轻量
  • 快速部署:容器可以在几秒内启动,大大提高了部署效率
  • 可移植性:一次构建,到处运行

核心概念

镜像 (Image)

定义:镜像是一个只读的模板,包含了运行应用所需的所有内容:代码、运行时、库文件、环境变量和配置文件。


  • 分层存储:镜像由多个层组成,每一层代表一次修改
  • 只读性:镜像本身是只读的,不能直接修改
  • 可复用:同一个镜像可以创建多个容器
  • 版本管理:通过标签(tag)进行版本管理

容器

容器是镜像的运行实例,是一个轻量级、可移植的执行环境,基于镜像创建,与其他容器隔离,共享主机操作系统内核,启动快(毫秒级)、资源占用低;虚拟机有独立内核,启动慢(分钟级)、资源开销大。
特点:

  • 隔离性:每个容器都有自己的文件系统、网络和进程空间
  • 临时性:容器可以被创建、启动、停止、删除
  • 可写层:容器在镜像基础上添加了一个可写层
  • 进程级:容器内通常运行一个主进程

仓库 (Repository)

仓库是存储和分发镜像的地方,可以包含一个镜像的多个版本。

分类:

  • 公共仓库:如 Docker Hub,任何人都可以使用
  • 私有仓库:企业内部搭建,用于存储私有镜像
  • 官方仓库:由软件官方维护的镜像仓库。

Dockerfile

文本文件,描述如何自动构建镜像(例如指定基础镜像、安装软件、复制文件等)。

Docker 架构

Docker 使用客户端-服务器 (C/S) 架构模式,使用远程 API 来管理和创建 Docker 容器。
Docker 容器通过 Docker 镜像来创建。

工作流程

  • 构建镜像:使用 Dockerfile 创建镜像。
  • 推送镜像到注册表:将镜像上传到 Docker Hub 或私有注册表中。
  • 拉取镜像:通过 docker pull 从注册表中拉取镜像。
  • 运行容器:使用镜像创建并启动容器。
  • 管理容器:使用 Docker 客户端命令管理正在运行的容器(例如查看日志、停止容器、查看资源使用情况等)。
  • 网络与存储:容器之间通过 Docker 网络连接,数据通过 Docker 卷或绑定挂载进行持久化。

Docker 客戶端

Docker 客户端是用户与 Docker 守护进程交互的命令行界面(CLI)。它是用户与 Docker 系统的主要交互方式,用户通过 Docker CLI 发出命令,这些命令被发送到 Docker 守护进程,由守护进程执行相应的操作。

Docker 守护进程(Docker Daemon)

Docker 守护进程(通常是 dockerd)是 Docker 架构的核心,负责管理容器生命周期、构建镜像、分发镜像等任务。守护进程通常以后台进程的方式运行,等待来自 Docker 客户端的 API 请求。

Docker 引擎 API

Docker 引擎 API 是 Docker 提供的 RESTful 接口,允许外部客户端与 Docker 守护进程进行通信。通过这个 API,用户可以执行各种操作,如启动容器、构建镜像、查看容器状态等。

Docker 容器

容器是 Docker 的执行环境,它是轻量级、独立且可执行的软件包。容器是从 Docker 镜像启动的,包含了运行某个应用程序所需的一切——从操作系统库到应用程序代码。容器在运行时与其他容器和宿主机共享操作系统内核,但容器之间的文件系统和进程是隔离的。

Docker 镜像

Docker 镜像是容器的只读模板。每个镜像都包含了应用程序运行所需的操作系统、运行时、库、环境变量和应用代码等。镜像是静态的,用户可以根据镜像启动容器。

Docker 仓库

Docker 仓库是用来存储 Docker 镜像的地方,最常用的公共仓库是 Docker Hub。

Docker Compose

Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。通过 Compose,用户可以使用一个 docker-compose.yml 配置文件定义多个容器(服务),并可以通过一个命令启动这些容器。Docker Compose 主要用于开发、测试和部署多容器的应用。

Docker Swarm

Docker Swarm 是 Docker 提供的集群管理和调度工具。它允许将多个 Docker 主机(节点)组织成一个集群,并通过 Swarm 集群管理工具来调度和管理容器。Swarm 可以实现容器的负载均衡、高可用性和自动扩展等功能。

Docker 网络

Docker 网络允许容器之间相互通信,并与外部世界进行连接。

Docker 卷

Docker 卷是一种数据持久化机制,允许数据在容器之间共享,并且独立于容器的生命周期。与容器文件系统不同,卷的内容不会随着容器的销毁而丢失,适用于数据库等需要持久存储的应用。

使用 Docker

安裝

Ubuntu 安裝

方式 1

1
2
3
4
5
6
7
8
# 下载并执行Docker官方安装脚本
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# 启动Docker服务
sudo systemctl start docker
sudo systemctl enable docker

方式 2

  1. 卸载旧版本
    sudo apt-get remove docker docker-engine docker.io containerd runc
  2. 更新索引包
1
sudo apt-get remove docker docker-engine docker.io containerd runc
  1. 安装 apt 依赖包
1
2
3
4
5
6
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
  1. 添加 Docker 的官方 GPG 密钥:
1
curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
  1. 设置稳定版仓库
1
2
3
4
5
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/ \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

docker 常用命令

镜像获取与查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 搜索镜像(Docker Hub)
docker search [关键词]

# 拉取镜像
docker pull [镜像名]:[标签]
# 示例:拉取Ubuntu 20.04镜像
docker pull ubuntu:20.04

# 查看本地镜像列表
docker images
#
docker image ls

# 查看镜像详情
docker inspect [镜像名]:[标签]

# 查看镜像构建历史
docker history [镜像名]:[标签]

镜像操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 为镜像打标签
docker tag [原镜像名:标签] [新镜像名:新标签]
# 示例:标记镜像用于推送至私有仓库
docker tag myapp:v1 registry.example.com/myapp:v1

# 推送镜像到仓库
docker push [镜像名:标签]

# 删除镜像
docker rmi [镜像名:标签]
#
docker image rm [镜像名:标签]

# 强制删除镜像(即使有容器依赖)
docker rmi -f [镜像名:标签]

镜像导入导出

1
2
3
4
5
6
7
8
9
10
11
12
13
# 导出镜像
docker save -o [文件名.tar] [镜像名:标签]
# 示例
docker save -o ubuntu_20_04.tar ubuntu:20.04

# 导入镜像
docker load -i [文件名.tar]

# 清理悬空镜像(无标签镜像)
docker image prune

# 清理所有未使用镜像
docker image prune -a

容器创建与启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 创建容器(不启动)
docker create -it [镜像名:标签]

# 创建并启动容器
docker run [选项] [镜像名:标签] [命令]
# 常用选项:
# -d: 后台运行
# -it: 交互式终端
# -p 宿主机端口:容器端口: 端口映射
# --name 容器名: 指定名称
# -v 卷名:容器路径: 挂载数据卷
# --rm: 容器退出后自动删除

# 示例:启动一个Nginx容器
docker run -d -p 80:80 --name mynginx nginx:1.23

容器状态管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 查看运行中的容器
docker ps

# 查看所有容器(包括停止的)
docker ps -a

# 启动容器
docker start [容器ID/名称]

# 停止容器
docker stop [容器ID/名称]

# 重启容器
docker restart [容器ID/名称]

# 强制终止容器
docker kill [容器ID/名称]

# 暂停容器
docker pause [容器ID/名称]

# 恢复容器
docker unpause [容器ID/名称]

容器交互与信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 进入运行中的容器
docker exec -it [容器ID/名称] /bin/bash

# 查看容器日志
docker logs [容器ID/名称]
# 实时查看日志
docker logs -f [容器ID/名称]
# 查看最后100行日志
docker logs --tail 100 [容器ID/名称]

# 查看容器内进程
docker top [容器ID/名称]

# 查看容器资源使用情况
docker stats [容器ID/名称]

# 查看容器详细信息
docker inspect [容器ID/名称]

# 查看容器端口映射
docker port [容器ID/名称]

容器文件操作

1
2
3
4
5
# 从容器复制文件到本地
docker cp [容器ID/名称]:[容器内路径] [本地路径]

# 从本地复制文件到容器
docker cp [本地路径] [容器ID/名称]:[容器内路径]

容器删除与清理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 删除容器
docker rm [容器ID/名称]

# 强制删除运行中的容器
docker rm -f [容器ID/名称]

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

# 批量操作示例
# 停止所有运行中的容器
docker stop $(docker ps -q)
# 删除所有容器
docker rm -f $(docker ps -aq)

容器与镜像转换

1
2
3
4
5
6
7
8
# 从容器创建镜像
docker commit [容器ID/名称] [新镜像名:标签]

# 导出容器快照
docker export -o [文件名.tar] [容器ID/名称]

# 从快照导入镜像
docker import [文件名.tar] [镜像名:标签]

网络命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 查看网络列表
docker network ls

# 创建自定义网络
docker network create --driver bridge [网络名]
# 示例
docker network create my-network

# 查看网络详情
docker network inspect [网络名]

# 将容器连接到网络
docker network connect [网络名] [容器名]

# 将容器从网络断开
docker network disconnect [网络名] [容器名]

# 删除网络
docker network rm [网络名]

# 清理未使用的网络
docker network prune

容器互联示例

1
2
3
4
5
6
# 创建两个容器并连接到同一网络
docker run -d --name app1 --network my-network myapp:v1
docker run -d --name app2 --network my-network myapp:v1

# 此时app1可以通过容器名ping通app2
docker exec app1 ping app2

数据卷命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 创建数据卷
docker volume create [卷名]
# 示例
docker volume create mysql-data

# 查看数据卷列表
docker volume ls

# 查看数据卷详情
docker volume inspect [卷名]

# 删除数据卷
docker volume rm [卷名]

# 清理未使用的数据卷
docker volume prune

# 运行容器时挂载数据卷
docker run -d -v [卷名]:[容器内路径] --name [容器名] [镜像名]
# 示例:MySQL数据持久化
docker run -d -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql mysql:8.0

docker run -d -v [主机目录]:[容器内路径] --name [容器名] [镜像名]
# 示例
docker run -d -v /home/user/app:/app --name myapp myapp:v1

配置 DNS

DNS(Domain Name System,域名系统)是互联网的一项核心基础服务,它的主要作用是将人类容易记忆的域名(如www.baidu.com)转换为计算机能够识别的 IP 地址(如 180.101.50.242),从而实现网络设备之间的通信。
DNS 就像一个 “网络通讯录”,负责在 “域名” 和 “IP 地址” 之间建立映射,让用户无需记住复杂的 IP,只需输入域名就能访问网站。


宿主机的 /etc/docker/daemon.json 文件中增加以下内容来设置全部容器的 DNS

1
2
3
{
"dns": ["114.114.114.114", "8.8.8.8"]
}

启动容器的 DNS 会自动配置为 114.114.114.114 和 8.8.8.8

如果只想在指定的容器设置 DNS,则可以使用以下命令:

1
docker run -it --rm -h host_ubuntu  --dns=114.114.114.114 --dns-search=test.com ubuntu

Docker 仓库管理

仓库(Repository)是集中存放镜像的地方

  • 注册 docker 账号
  • 登录docker login
  • 登出docker logout
  • 查询镜像docker search
  • 拉取镜像docker pull
  • 推送镜像docker push

Dockerfile

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

构建过程

  1. 新建 dockerfile 文件
  2. 添加配置文本
  3. 构建镜像
    docker build -t 镜像名称:镜像标签 .

指令介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 基础镜像
FROM node:16-alpine

# 设置工作目录
WORKDIR /app

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

# 安装依赖
RUN npm install --production

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 3000

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

Docker Compose

Compose 是用于定义和运行多容器 Docker 应用程序的工具。
通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务

使用步骤

  1. 使用 Dockerfile 定义应用程序的环境
  2. 使用 docker-compose.yml 定义构成应用程序的服务,
  3. 执行 docker-compose up 命令来启动并运行整个应用程序。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
version: "3"
services:
frontend:
image: nginx:1.23
ports:
- "80:80"
volumes:
- ./frontend:/usr/share/nginx/html
depends_on:
- backend

backend:
image: mynodeapp:v1
ports:
- "3000:3000"
depends_on:
- db
environment:
- DB_HOST=db
- DB_USER=root
- DB_PASS=123456

db:
image: mysql:8.0
volumes:
- mysql-data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=mydb

volumes:
mysql-data:

启动应用:docker-compose up -d