Docker|简单入门
文章目录
- Docker简介
- Docker和虚拟机的联系和区别
- 基本原理和概念
- 镜像
- 容器
- 仓库
- Docker安装配置
- 容器化和Dockerfile
- 实践环节
- Docker Compose
Docker简介
- Docker是一个用于构建build、运行run、传送share应用程序的平台,可以把应用程序打包成一个个的集装箱,然后小鲸鱼就可以把它们运送到任何所需要的地方。
- Docker 是利用 Linux 内核的 Namespace + Cgroups 实现进程级隔离和资源限制,提供轻量级、快速可移植的容器技术,是现代云原生架构的基石之一。
- Docker 是一个开源的容器化平台,可以把应用程序和它的依赖打包在一个轻量级、可移植、自包含的容器中,保证跨环境一致运行。
- 一句话:“一次构建,到处运行”。
- Docker 解决了什么问题?
- 在传统部署中,常常遇到:
- 依赖冲突:不同应用需要不同版本的库,部署在同一机器容易打架。
- 环境不一致:开发、测试、生产环境配置不一致,导致“在我机器上能跑”。
- 复杂部署流程:要手动配置各种环境,效率低、容易出错。
- Docker 通过容器机制解决这些问题:
- 应用 + 环境打包成镜像 → 一次构建,任意运行
- 镜像不可变,版本可控,回滚方便
- 容器轻量、秒级启动、资源隔离
-
以一个前后端分离的网站,如果没有docker,那么我们要在本地先安装以下内容,才可以运行:
- 安装前端Node.js环境
- 安装各种npm依赖
- 安装Java运行时环境
- 安装SpringBoot微服务的各种第三方依赖包
- 安装MySQL数据库
- 安装配置Redis缓存
- 安装配置Nginx负载均衡
- 配置各种环境变量并启动脚本
-
而且这还只是开发环境,如果是要在测试环境也配一边就要再来一次,耗时耗力而且容易出错。
- 但是有了Docker我们就可以把他们打包成一个一个的集装箱,只要在开发环境中运行成功了,那么在测试环境中运行也是没有问题的。
- 核心概念
# Docker常用命令# 查看本地镜像
docker images# 拉取镜像
docker pull nginx# 启动容器
docker run -d -p 8080:80 nginx# 查看运行中的容器
docker ps# 停止容器
docker stop <container_id># 进入容器
docker exec -it <container_id> /bin/bash
Docker和虚拟机的联系和区别
- 联系
- 目的相同:容器和虚拟机都是用来实现隔离,让应用运行在相互隔离的环境中:
- 避免依赖冲突
- 保证环境一致性
- 提高资源利用率
- 都支持跨平台部署:容器镜像、虚拟机镜像都能实现 “一次打包,到处运行”。
- 都能通过编排工具管理(如 K8s 支持容器,VM 支持 OpenStack、vSphere 等)
- 目的相同:容器和虚拟机都是用来实现隔离,让应用运行在相互隔离的环境中:
- Docker 容器 ≠ 虚拟机,不需要 Hypervisor(虚拟化技术:将物理资源虚拟为多个逻辑资源的技术),不是完全模拟一个硬件环境
- Docker 容器 = 基于宿主机 Linux 内核的隔离进程,启动快,资源开销小
- 虚拟机一定程度上实现了资源的整合,可以将一台服务器的计算能力、存储能力、网络资源分配给多个逻辑服务器,实现多台服务器的功能
- 但是每台虚拟机都需要占用大量的资源,如CPU、内存、硬盘、网络等,而且启动速度很慢
- 最主要的是,大部份情况下,我们一台服务器上只需要运行一个主要对外提供服务的应用程序就行了,并不需要用到一个完整的操作系统所提供的所有功能,如下图所示
- 上面的例子来说其实我们所需要的只是一个web服务器,但是虚拟机却要启动一个完整的操作系统,包括操作系统内核,各种系统服务,各种工具,甚至图形界面等等,这些我们并不需要的服务会占用大量的资源,导致了资源的浪费和启动速度慢的问题
- 于是容器技术应运而生,但是要注意,Docker并不是容器!
- Docker只是容器的一种实现,是一个容器化的解决方案和平台;而容器是一种虚拟化技术,和虚拟机类似,也是一个独立的环境,可以在这个环境中运行应用程序,但是和虚拟机不同的是它并不需要运行一个完整的操作系统,而是使用宿主机的操作系统,所以启动速度非常快,通常只需要几秒钟,同时因为所需要的资源更少,所以可以在一台物理服务器上运行更多的容器,这样就可以更加充分地利用服务器的资源,减少资源的闲置和浪费。
# 虚拟机架构硬件
│
└── Hypervisor (KVM / VMware / Hyper-V)│├── Guest OS (Linux / Windows)│ └── App A├── Guest OS (Linux / Windows)│ └── App B
# 容器架构硬件
│
└── 宿主机 OS (Linux内核)│└── Docker Engine / containerd├── Container A (App + libs)├── Container B (App + libs)
- 容器不需要 Guest OS,进程直接运行在宿主机内核之上。
- 虚拟机需要完整 Guest OS,有更高隔离,但更重。
- 容器和虚拟机的主要联系是都实现了应用隔离,方便跨平台部署。区别在于虚拟机是通过 Hypervisor 提供系统级虚拟化,每个VM都有完整的操作系统,启动慢、资源占用大,隔离性强;而容器是基于宿主机内核,通过 Linux 的 Namespace 和 Cgroups 技术提供进程级隔离,启动快、资源占用小,非常适合微服务和大规模部署。容器与虚拟机是互补关系,通常混合使用,比如在公有云上用VM作为物理隔离基础,容器作为上层弹性计算单位。
- 虚拟机提供系统级隔离,容器提供进程级隔离;VM 启动慢资源重隔离强,容器启动快资源轻灵活高效,两者可以结合使用,满足不同场景需求。
基本原理和概念
- Docker 镜像是应用程序和依赖的静态打包模板,容器是镜像运行时的隔离进程,仓库用于存储和分发镜像。三者配合实现了应用的一键打包、快速部署和跨环境一致运行,是现代 DevOps 流水线的核心组件。
Dockerfile → docker build → 镜像 (Image) → docker push → 仓库 (Registry)↓docker run↓容器 (Container)
镜像
- 镜像是一个只读的模版,可以用来创建容器。
- 镜像和容器的关系,就好比Java中类和实例的关系一样,我们可以定义一个类中有哪些属性和方法,这个定义好的类就是模版,然后我们可以根据这个模版来创建多个实例,这些实例就是这个类的对象,对应到Docker中,镜像就是一个模版,容器就是这个模版的一个实例,可以有一个也可以有多个。
- 镜像是一个静态的模板,包含了应用程序和所有依赖、库、工具、配置等。
- 容器运行时会在镜像上加一个可写层(Writable Layer)
- 可以理解成容器的快照,容器运行时是基于镜像启动出来的。
- 特点:
- 分层结构,每一层是只读的
- 可复用,相同基础层不会重复存储
- 版本可控,便于回滚和管理
docker images # 查看本地镜像
docker pull nginx # 拉取远程镜像
docker build -t myapp:v1 . # 构建镜像
docker rmi <image_id> # 删除镜像
容器
- 容器是Docker的运行实例,提供了一个独立的可移植的环境。
- 镜像和容器的关系,就好比Java中类和实例的关系一样,我们可以定义一个类中有哪些属性和方法,这个定义好的类就是模版,然后我们可以根据这个模版来创建多个实例,这些实例就是这个类的对象,对应到Docker中,镜像就是一个模版,容器就是这个模版的一个实例,可以有一个也可以有多个。
- 容器是镜像的运行时实例,本质上是一个受限隔离的进程,它运行在宿主机内核之上。
- 容器 = 运行中受限隔离的进程 + 分层文件系统。
- 特点:
- 容器之间互相隔离,与宿主机隔离
- 轻量,共享宿主机内核(不像 VM 需要 Guest OS)
- 可以随时创建 / 启动 / 停止 / 删除
- 容器是临时的,可以随时销毁,也可以通过数据卷持久化数据
docker run -d -p 8080:80 nginx # 启动容器
docker ps # 查看运行中的容器
docker stop <container_id> # 停止容器
docker rm <container_id> # 删除容器
docker exec -it <container_id> /bin/bash # 进入容器
仓库
- 镜像如何分享给别人呢?这就涉及到Docker仓库的概念了。
- Docker仓库是用来存储Docker镜像的地方,最流行和最常用的仓库就是DockerHub,这是一个公共的Docker仓库,用来集中存储和管理Docker镜像,可以在这里下载各种镜像,也可以将镜像上传到仓库实现镜像的共享和复用。
- 仓库(Registry)是用来存放和分发镜像的服务器。1、公共仓库(Public):如 Docker Hub。2、私有仓库(Private):企业内部自建 Registry,保障镜像安全、加快拉取速度。
- 仓库(Registry)里可以有很多 仓库名(Repository),一个 Repository 中可以有多个 标签(Tag),每个标签对应一个镜像版本。
nginx:1.25.2
nginx:latest
mycompany/myapp:v1.0.0docker.io/nginx:latest # Docker Hub
registry.example.com/myapp:v1.0 # 私有仓库
docker login registry.example.com # 登录私有仓库
docker push myapp:v1 # 推送镜像
docker pull myapp:v1 # 拉取镜像
Docker安装配置
- 官网:https://www.docker.com/
- 安装完成之后记得启动Docker,Windows系统记得开启Hyper-V功能
- Docker使用Client-Server架构模式,Docker Client和Docker Daemon之间使用socket或者RESTful API进行通信,Docker Daemon就是服务端的守护进程,负责管理Docker的各种资源,Docker Client负责向Docker Daemon发送请求,Docker Daemon接收到请求之后进行处理,然后将结果返回给Docker Client,Docker Daemon是一个后台进程,用来接收并处理来自Docker客户端度请求,然后将结果返回给Docker客户端,所以我们在终端中输入各种Docker命令,实际上都是通过Docker客户端发送给Docker Daemon的,然后Docker Daemon进行处理再将结果返回给客户端,就可以在终端中看到执行结果了。
容器化和Dockerfile
- 容器化Containerization,顾名思义就是将应用程序打包成容器,然后在容器中执行应用程序的过程,主要有三步
- 创建一个Dockerfile,告诉Docker创建应用程序镜像所需要的步骤和配置
- 使用Dockerfile构建镜像
- 使用镜像创建和运行容器
- Dockerfile是一个文本文件,里面包含了一条一条的指令,用来告诉Docker如何来构建镜像,这个镜像包括了我们应用程序执行的所有命令,也就是刚刚提到的各种依赖,配置环境和运行应用程序所需要的所有内容:
- 精简版操作系统
- 应用程序的运行时环境
- 应用程序
- 第三方依赖库或者包
- 应用程序的配置文件和环境变量等
实践环节
-
写一个js脚本文件,输出"Hello World!"
-
没有Docker之前,我们在其他机器要运行代码,只能通过以下步骤:
- Step1: 安装操作系统
- Step2: 安装JavaScript运行环境(NodeJS)
- Step3: 复制应用程序、依赖包、配置文件
- Step4: 执行启动命令运行程序
-
有了Docker后我们可以把下面的步骤给写入Dockerfile里面,剩下的工作就交给Docker来自动完成
- 需要先指定一个基础镜像,镜像是按层次结构来构建的,每一层都是基于上一层的,所以要先指定一个基础镜像然后在这个镜像的基础上再添加我们的应用程序
- 比如可以在一个基础的linux镜像开始然后安装nodejs,也可以直接使用nodejs的镜像,
FROM node:14-alpine
- 然后需要把我们的应用程序复制到镜像中,可以使用copy命令来复制文件,
COPY source dest
,比如COPY index.js /index.js
- 接下来需要在镜像中运行应用程序,可以使用
CMD
命令来运行应用程序,CMD是个方括号,里面第一个参数表示可执行程序的名字,第二个参数表示可执行程序接收到的参数CMD [ "node", "/index,js" ]
,也可以不用方括号,如CMD node /index.js
- 回到终端使用
docker build -t 镜像名字 .
来构建镜像,后面加的一个点表示的是当前目录,也就是Dockerfile所在的目录 docker image ls
或者是docker images
,查看所有的镜像,latest表示最新版本docker run 镜像名字
,即可执行当前镜像文件
Docker Compose
- 用于定义和运行多容器Docker应用程序的工具
- 使用YAML文件来配置应用程序的服务
- 一条命令即可创建并启动所有服务
- 实际开发环境中这些服务是需要相互关联着才能工作的,Docker Compose解决的就是这个问题,通过一个单独的docker-compose.yaml的配置文件来将这一组互相关联的容器组合在一起,形成一个项目,然后使用一条命令就可以启动、停止或者重建这些服务,
docker compose up