一、Docker 概述
Docker是一个开源的应用容器引擎,基于Go语言开发,并遵循Apache2.0协议开源。Docker允许开发者将应用以及依赖包打包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux、Windows或Mac机器上,也可以实现虚拟化。容器完全使用沙箱机制,相互之间不会有任何接口,更重要的是容器性能开销极低。
二、Docker与虚拟机的区别
Docker与虚拟机是两种不同的虚拟化技术,它们在架构、性能、资源使用和隔离级别等方面有显著区别。
架构差异
- 虚拟机(VM):
- 硬件级虚拟化:每个虚拟机包括完整的操作系统、应用程序以及相关的库和依赖。
- 隔离级别:每个虚拟机之间以及虚拟机与宿主机之间完全隔离,安全性高。
- Docker(容器):
- 操作系统级虚拟化:容器共享宿主机的操作系统内核,但每个容器运行在独立的用户空间中。容器包括应用程序及其依赖,但不需要完整的操作系统。Docker引擎运行在宿主机操作系统上,负责管理容器。
- 隔离级别:容器之间通过命名空间(Namespace)和控制组(cgroups)进行隔离,但共享内核,因此隔离级别比虚拟机低。
- 虚拟机(VM):
性能比较
- 虚拟机(VM):
- 启动速度较慢(分钟级),因为需要启动整个操作系统。
- 资源消耗较大,每个虚拟机都需要分配独立的资源(内存、CPU等),并且有额外的操作系统开销。
- 性能有损失,因为应用程序运行在虚拟硬件上,需要通过Hypervisor层。
- Docker(容器):
- 启动速度极快(秒级甚至毫秒级),因为容器直接运行在宿主机内核上,无需启动操作系统。
- 资源消耗小,多个容器共享宿主机内核,没有额外的操作系统开销。
- 性能接近原生,因为容器直接运行在宿主机上,没有虚拟硬件层。
- 虚拟机(VM):
资源使用效率
- 虚拟机(VM):
- 每个虚拟机都需要完整的操作系统,因此占用磁盘空间大(通常几GB到几十GB)。
- 内存占用也大,因为每个虚拟机都要运行操作系统进程。
- Docker(容器):
- 容器共享宿主机内核,只需要存储应用程序及其依赖,因此镜像体积小(通常几MB到几百MB)。
- 内存占用少,因为多个容器可以共享宿主机的操作系统内核。
- 虚拟机(VM):
隔离性和安全性
- 虚拟机(VM):
- 完全隔离,每个虚拟机有独立的操作系统和内核,一个虚拟机的崩溃不会影响其他虚拟机或宿主机。
- 安全性高,攻击者需要先突破虚拟机,然后再突破Hypervisor才能访问宿主机。
- Docker(容器):
- 隔离性相对较弱,虽然容器之间通过命名空间隔离,但共享内核,因此内核漏洞可能影响所有容器。
- 安全性较低,如果容器内的应用程序获得宿主机内核的访问权限,可能会影响其他容器和宿主机。
- 虚拟机(VM):
可移植性
- 虚拟机(VM):
- 虚拟机镜像通常较大,迁移和分发不如容器方便。
- 虚拟机可以在不同Hypervisor上运行,但可能需要调整配置。
- Docker(容器):
- 容器镜像轻量,易于分发和迁移,适合持续集成和持续部署(CI/CD)。
- 容器可以在任何安装Docker引擎的宿主机上运行,保证了环境一致性。
- 虚拟机(VM):
使用场景
- 虚拟机(VM):
- 适合运行不同操作系统的应用程序(例如在Linux服务器上运行Windows应用)。
- 需要完全隔离的环境,如多租户环境、安全要求高的场景。
- 遗留系统迁移,或者需要模拟完整硬件环境的情况。
- Docker(容器):
- 微服务架构,每个服务运行在独立的容器中,便于扩展和管理。
- DevOps实践,实现快速部署和弹性伸缩。
- 云原生应用,容器可以轻松在云环境中部署和迁移。
- 虚拟机(VM):
三、Docker 的核心优势
- 轻量级:共享主机内核,无需完整操作系统
- 可移植性:一次构建,到处运行
- 隔离性:进程、网络、文件系统隔离
- 快速部署:秒级启动和停止
- 版本控制:支持镜像版本管理
- 生态丰富:Docker Hub 提供海量镜像
四、Docker核心概念
4.1 镜像(Image)
4.1.1 定义
Docker 镜像是只读的模板,包含了运行应用程序所需的一切:
- 操作系统(精简版)
- 运行时环境
- 应用程序代码
- 依赖库
- 配置文件
- 环境变量
4.1.2 镜像的核心特性
只读性
# 镜像是不可变的docker pull ubuntu:20.04# 下载的镜像不能修改# 基于镜像创建容器时,会添加一个可写层+---------------------+|容器可写层|← 容器层(可修改) +---------------------+|镜像只读层|← 镜像层(不可变) +---------------------+分层存储(Layer)
# Dockerfile 示例FROM ubuntu:20.04# 第1层:基础镜像RUNapt-getupdate# 第2层:执行命令COPY app.py /app/# 第3层:添加文件RUN pipinstallflask# 第4层:安装依赖CMD["python","app.py"]# 第5层:启动命令分层优势:
- 共享存储:多个镜像共享相同的基础层
- 快速构建:只重新构建变化的层
- 节省空间:相同层只存储一次
镜像 myapp:v1 ├── Layer4: CMD["python","app.py"](2KB)├── Layer3: RUN pipinstallflask(15MB)├── Layer2: COPY app.py /app/(5KB)└── Layer1: FROM ubuntu:20.04(72MB)镜像 myapp:v2 ├── Layer5: COPY config.json /app/(3KB)← 新增 ├── Layer4: CMD["python","app.py"](2KB)← 共享 ├── Layer3: RUN pipinstallflask(15MB)← 共享 ├── Layer2: COPY app.py /app/(5KB)← 共享 └── Layer1: FROM ubuntu:20.04(72MB)← 共享
4.1.3 镜像的生命周期
# 1. 编写 Dockerfile# 2. 构建镜像docker build -t myapp:1.0.# 3. 查看本地镜像docker images# 4. 推送镜像到仓库docker push myregistry.com/myapp:1.0# 5. 拉取镜像docker pull myregistry.com/myapp:1.0# 6. 运行容器docker run myapp:1.0# 7. 删除镜像docker rmi myapp:1.04.1.4 镜像操作命令
基本操作
# 查看本地镜像docker images docker imagels# 搜索镜像docker search nginx# 拉取镜像docker pull ubuntu:20.04 docker pull nginx:alpine# 删除镜像docker rmi ubuntu:20.04 docker imagermnginx:alpine# 删除所有未使用镜像docker image prune -a镜像标签管理
# 添加标签docker tag ubuntu:20.04 myregistry.com/ubuntu:latest docker tag myapp:1.0 myapp:production# 查看镜像历史dockerhistoryubuntu:20.04# 导出镜像docker save ubuntu:20.04>ubuntu.tar# 导入镜像docker load<ubuntu.tar# 导出容器为镜像dockerexportcontainer_id>container.tar镜像构建与优化
# 构建镜像docker build -t myapp:1.0.docker build -t myapp:1.0 -f Dockerfile.prod.# 查看构建过程docker build --progress=plain.# 多阶段构建docker build -t myapp:multi-stage.# 构建参数docker build --build-argVERSION=1.0.
4.2 容器(Container)
4.2.1 定义
Docker 容器是镜像的运行实例,是一个轻量级、可执行的软件包,包含:
- 应用程序及其所有依赖项
- 独立的文件系统
- 网络配置
- 进程空间
- 资源限制
4.2.2 容器的核心特性
轻量级
# 与传统虚拟机对比+-----------------------------+|虚拟机:重量级隔离||+-----------------------+|||Guest OS||||+-----------------+|||||App|||||+-----------------+|||+-----------------------+|+-----------------------------+ 启动时间:分钟级|内存:GB级 +-----------------------------+|Docker容器:轻量级隔离||+-----------------------+|||App|||+-----------------------+|+-----------------------------+ 启动时间:秒级|内存:MB级隔离性
# Linux 内核特性实现隔离1. Namespaces:进程、网络、挂载点隔离2. Cgroups:CPU、内存、磁盘I/O限制3. UnionFS:分层文件系统# 查看容器命名空间ls-la /proc/<container-pid>/ns/
4.2.3 容器的生命周期
生命周期状态
创建(Created)→ 运行(Running)→ 暂停(Paused)↓ ↓ ↓ → 停止(Stopped)→ 删除(Deleted)状态转换命令
# 完整生命周期管理docker create --name mycont nginx:alpine# 创建docker start mycont# 启动docker pause mycont# 暂停docker unpause mycont# 恢复docker stop mycont# 停止(优雅停止)dockerkillmycont# 强制停止docker restart mycont# 重启dockerrmmycont# 删除
4.2.4 容器操作命令
基础操作
# 运行容器docker run -d --name web nginx:alpine# 运行并进入交互模式docker run -it --name ubuntu ubuntu:20.04bash# 查看运行中的容器dockerps# 查看所有容器(包括停止的)dockerps-a# 查看容器详情docker inspect web# 查看容器日志docker logs web docker logs -f web# 实时查看docker logs --tail100web# 最后100行容器控制
# 进入运行中的容器dockerexec-it webbashdockerexec-it webshdockerexec-it web /bin/bash# 在容器内执行命令(不进入)dockerexecwebls-la /usr/share/nginx/html dockerexecwebpsaux# 复制文件dockercpindex.html web:/usr/share/nginx/html/ dockercpweb:/var/log/nginx/access.log ./nginx.log# 重命名容器dockerrenameweb nginx-server资源监控
# 查看容器资源使用docker stats docker stats --no-stream# 单次查看docker stats web# 指定容器# 查看容器进程dockertopweb# 查看容器端口映射docker port web# 查看容器元数据docker inspect web|grep-A10"NetworkSettings"
4.2.5 容器运行参数详解
基础运行选项
# 完整的运行示例docker run -d\# 后台运行--name myapp\# 容器名称--hostname app-server\# 主机名--restart unless-stopped\# 重启策略-p8080:80\# 端口映射-p443:443\-v /data:/var/lib/app\# 数据卷挂载-eDATABASE_URL=postgres://...\# 环境变量--memory="512m"\# 内存限制--cpus="1.5"\# CPU限制--network my-network\# 网络myapp:latest# 镜像端口映射
# 基本端口映射docker run -p80:80 nginx# 绑定特定IPdocker run -p127.0.0.1:80:80 nginx# 随机端口docker run -p80nginx# 多端口映射docker run -p8080:80 -p8443:443 nginx# UDP端口docker run -p53:53/udp dns-server环境变量
# 单个环境变量docker run -eMY_VAR=value myapp# 多个环境变量docker run -eVAR1=value1 -eVAR2=value2 myapp# 从文件读取docker run --env-file .env myapp# 传递主机环境变量docker run -eHOMEmyapp资源限制
# CPU限制docker run --cpus=0.5myapp# 最多使用0.5个CPU核心docker run --cpuset-cpus="0,2"myapp# 绑定到特定CPU核心# 内存限制docker run --memory="512m"myapp# 内存限制512MBdocker run --memory-swap="1g"myapp# 交换分区限制docker run --memory-reservation="256m"myapp# 内存软限制# 磁盘I/O限制docker run --device-write-bps /dev/sda:10mb myapp重启策略
# 自动重启策略docker run --restart no# 不自动重启(默认)docker run --restart on-failure# 失败时重启docker run --restart on-failure:5# 最多重启5次docker run --restart always# 总是重启docker run --restart unless-stopped# 除非手动停止,否则重启
4.3 仓库(Repository)
4.3.1 定义
Docker 仓库是存储和分发 Docker 镜像的中心化服务,类似代码仓库(Git),但专门用于 Docker 镜像。
4.3.2 核心概念
镜像仓库生态系统: 仓库(Repository) → 注册中心(Registry) → 镜像标签(Tag) 仓库:存储特定镜像的所有版本(如 nginx, mysql) 注册中心:存放多个仓库的服务(如 Docker Hub) 标签:镜像的版本标识(如 :latest, :1.0, :alpine)4.3.3 仓库类型
- 公共仓库
# Docker Hub(官方)https://hub.docker.com/# 第三方公共仓库- Google Container Registry(GCR)- Amazon ECR Public Gallery - Azure Container Registry - GitHub Container Registry(GHCR)- Quay.io- 私有仓库
# 自建私有注册中心docker run -d -p5000:5000 --name registry registry:2# 云厂商托管- AWS ECR(Amazon Elastic Container Registry) - Google Cloud Container Registry - Azure Container Registry - 阿里云容器镜像服务 - 腾讯云容器镜像服务4.3.4 仓库操作命令
基本操作
# 搜索镜像docker search nginx docker search --filter=stars=1000nginx docker search --filter=is-official=true nginx# 拉取镜像docker pull nginx:alpine docker pull registry.example.com/myapp:latest# 推送镜像docker tag myapp:latest registry.example.com/myapp:latest docker push registry.example.com/myapp:latest# 查看镜像标签curlhttps://registry.hub.docker.com/v2/repositories/library/nginx/tags/认证管理
# 登录仓库docker login docker login registry.example.com docker login -u username -p password registry.example.com# 查看登录信息docker info|grep-A5"Registry"cat~/.docker/config.json# 登出dockerlogoutdockerlogoutregistry.example.com
4.3.5 企业级仓库解决方案
Nexus Repository Manager
# docker-compose.yml for Nexusversion:'3.8'services: nexus: image: sonatype/nexus3:latest container_name: nexus restart: unless-stopped ports: -"8081:8081"-"5000:5000"volumes: - ./nexus-data:/nexus-data environment: -INSTALL4J_ADD_VM_PARAMS=-Xms2g -Xmx2g -XX:MaxDirectMemorySize=2gHarbor(企业级 Registry)
# Harbor 特性- 基于角色的访问控制(RBAC)- LDAP/AD 集成 - 镜像漏洞扫描 - 镜像复制 - Webhook 通知 - 图形化管理界面# 快速部署curl-s https://raw.githubusercontent.com/goharbor/harbor/master/make/harbor.yml -o harbor.yml ./install.sh