Docker 是一个开源的应用容器引擎,使用go语言实现,它诞生于2013年,最早是dotCloud公司内部的一个项目,后来加入了Linux基金会,并采用Apache 2.0协议进行管理,代码托管在GitHub上。 Docker提供了一种轻量级操作系统虚拟化解决方案。它基于Linux容器(LXC)技术,在LXC之上,Docker进行了进一步的封装,让用户无需处理容器管理,使得操作变得更加简单。 它允许开发者将他们的应用程序和依赖包打包到一个可移植的镜像中,应用程序运行在容器中,每个容器都有自己独立的沙箱环境,相互之间没有任何接口。这意味着容器之间的应用程序不会相互干扰,提供了更高的安全性和隔离性。
Docker 是容器技术的一种体现,而容器技术的根本是为了抹平软件运行的环境差异。
Docker通过build命令将应用程序和其依赖构建成镜像文件,镜像是只读的,这意味着构建完成后,镜像不会再发生任何变化。如此,基于该镜像启动的容器环境必然一致。同理,跑在这个容器中的应用程序所处环境也一致。
通过这种容器化技术,开发者可以更加方便地部署和管理应用程序,提高开发效率和应用的可移植性。容器是完全使用沙箱机制,相互之间不会有任何接口。
它有几个特性
Docker 在许多场景下都能提供价值,特别是在需要快速部署、一致性环境、资源隔离和持续集成部署等方面具有明显优势。
新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统,避免引导。docker是利用宿主机的操作系统,省略了这个复杂的过程,它和vm的差异主要体现在
优势
docker 属于操作系统层面的虚拟化技术。隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。容器本质是一个受限制的进程,它没办法像直接运行在主机上的进程那样获取主机上的进程、环境变量、网络等信息。 虚拟化技术指的是通过隐藏特定计算平台的实际物理特性,为用户提供抽象、统一、模拟的计算环境。这种计算环境,也被称为虚拟机**。** Docker 是对Linux容器的一种封装,具有高性能,低开销,接口简单易用等特点。真正使其超过其他同类产品,迅速占领市场,成为目前最流行的Linux容器技术解决方案的根本是Docker引入了镜像功能。 与系统级别的虚拟机不同,容器技术的虚拟其实是进程级别的。虚拟机是通过在宿主机上启动一个虚拟机监视器 HyperVisor 来管理控制虚拟机的,最经典的 HyperVisor 就是 VirtualBox。与容器相比,虚拟机包含了整个客户操作系统,这也是二者性能差异的主要成因。
Docker是一个Client-Server结构的系统,包括客户端和服务端,Docker守护进程运行在主机上, 然后通过Socket连接从客户端访问Docker守护进程。
关系图
Docker的核心组件,负责整个容器化流程的管理和执行。它包括三个主要部分:Docker守护进程(Docker Daemon)、Docker客户端(Docker Client)和 Docker API。
镜像是一个完整的文件系统,它包含了容器运行时所需要的所有依赖项:代码、运行时、库、环境变量和配置文件等。镜像是容器的基础,每个容器启动时都会基于一个镜像来创建。镜像可以基于另一个镜像构建,这种镜像的继承和定制过程称为镜像的层叠和分层构建。 Docker 镜像包含以下几个重要组成部分:
镜像定义:可以通过Dockerfile定义,其中包含了构建镜像所需的指令和配置信息。 获取方式:可以从Docker Hub等镜像仓库获取,也可以通过本地构建。
镜像和容器的关系就好像类和实例的关系。容器是镜像的一个运行时实例。每个容器都基于一个镜像创建,类似于类的实例化过程。容器可以独立运行,并且可以根据需要启动、停止或删除。可以理解为容器 = 容器层(可写)+ 镜像(只读)。 容器是在隔离的环境中运行的进程,具有自己的文件系统、网络空间和进程空间。
写时复制 写时复制(Copy-on-Write,CoW)技术在容器化技术中起到了关键作用,特别是在提高磁盘利用率和确保容器间隔离性方面有显著的优势。 原理:当容器启动时,Docker 使用写时复制机制。如果容器需要修改镜像中的文件,Docker 并不会直接修改镜像的源文件。相反,它会将需要修改的文件从镜像的只读层复制到容器的可读写层中。这样,容器在修改文件时实际上是在自己的独立文件系统层上进行操作,而不会影响到其他容器或原始镜像。 它的优势在于
生命周期 每一个容器完整生命周期都具有创建,运行,停止,暂停,删除这五个状态。
仓库可看成一个代码控制中心,可以用来存储和分发 Docker 镜像的地方。最常用的是Docker Hub,它是一个公共的镜像仓库,包含了大量的官方和社区维护的镜像。除了公共仓库,还可以搭建私有的Docker仓库,用于存储和分享自定义的镜像。
Docker Hub 是最广泛使用的公共镜像仓库,由 Docker 官方维护。Docker Hub 包含大量的官方镜像(由 Docker 官方团队维护)和社区镜像(由开源社区或个人开发者维护)。用户可以在 Docker Hub 上搜索、下载、发布和分享 Docker 镜像。它还提供自动构建、镜像扫描等功能。
Docker 网络允许容器之间进行通信,也能通过端口映射将容器的端口映射到主机上,实现与外部网络的连接。Docker 提供了多种网络驱动程序,以适应不同的需求和使用场景。 常见的 Docker 网络驱动程序如下
除此之外,Docker提供了网络命名空间的隔离机制,使得每个容器拥有独立的网络栈。守护进程为每个容器分配一个唯一的IP地址,并为容器设置网络接口和网络路由规则。
Docker卷是用于在容器中持久化存储数据的一种机制。通过挂载卷到容器的特定路径上,可以实现容器内数据的共享和存储。 Docker卷可以是主机上的目录,也可以使用Docker卷插件提供的其他存储后端。当使用主机上的目录作为卷时,容器中的数据会直接存储在主机上的相应路径下。这样的话,即使容器被删除或重新创建,数据仍然可以被保留下来。 另一种方式是使用Docker卷插件提供的其他存储后端,例如网络存储或云存储。这些存储后端可以提供更高级的功能,如备份、快照、复制等。使用这种方式,卷中的数据可以被持久化存储在一个独立于主机的存储系统中,从而实现跨多个容器的数据共享和持久化。 总之,Docker卷是一种非常有用的功能,可以帮助我们在容器中方便地进行数据的共享和持久化存储,无论是使用主机上的目录还是其他存储后端。通过数据卷(Volume)和绑定挂载(Bind Mount)我们实现了数据的持久化和共享。
要实现一个完整的容器,我们需要容器提供隔离机制、资源分配、网络通信等能力。docker 需要依赖以下三项关键的Linux技术:Namespace、Cgroups 和UnionFS(联合文件系统)。让我们逐一解释它们的作用:
Namespace 是 Linux 内核用来隔离内核资源的一种方式。提供了一种机制,可以将系统资源隔离给特定的进程组。通过使用命名空间,不同的容器可以拥有各自独立的系统视图,包括进程ID、网络接口、用户ID、文件名、网络访问和进程间通信等,使得进程只能访问与自身相关的那部分资源,其他资源不可见。 主要涉及以下六种命名空间:
Cgroups 是控制组群,control groups 的缩写,供了一种可以限制、记录和隔离进程组所使用的系统资源(如CPU、内存、磁盘I/O等)的机制。通过Cgroups,管理员可以控制每个容器的资源使用,防止某个容器消耗过多资源影响其他容器。Cgroups 通常用来限制容器的 CPU 和内存等资源的使用。质上来说,cgroups 是内核附加在程序上的一系列钩子(hook),通过程序运行时对资源的调度触发相应的钩子以达到资源追踪和限制的目的。 主要控制项:
联合文件系统是一种分层、轻量级并且高性能的文件系统,它允许将多个文件系统叠加在一起形成一个单一的虚拟文件系统。它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。 在Docker 的世界中,联合文件系统为容器提供构建层,使得容器可以实现写时复制以及镜像的分层构建和存储。 镜像本身是只读的,在运行某个容器的时候,会在镜像外层附加一个可读写层,这也是基于联合文件系统实现的。 它的主要特点包括:
下图中每一行命令都会生成一个镜像层,当不同的镜像之间有相同的镜像层时,便可以实现不同的镜像之间共享镜像层的效果。(比如基于base镜像扩展的镜像)
bashdocker pull 仓库地址/命名空间/镜像名称:标签
选项参数:
通过 docker pull 拉取镜像并不是必须的,在 docker run 时,如果本地不存在指定镜像,Docker会自动拉取。
bash# 截图对应命令
docker run -d --name mysql_8.3.0 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root mysql:latest
# 完整命令
docker run [选项参数] 仓库地址/命名空间/镜像名称:标签 [命令行] [命令行参数]
选项参数:
镜像推拉命令
bash# 从 Docker Hub 拉取镜像
docker pull nginx
# 将本地镜像推送到 Docker Hub
docker tag my-app:latest myusername/my-app:latest
docker push myusername/my-app:latest
# 启动一个本地的 Docker Registry 容器
docker run -d -p 5000:5000 --name registry registry:2
# 将本地镜像推送到私有 Registry
docker tag my-app:latest localhost:5000/my-app:latest
docker push localhost:5000/my-app:latest
# 从私有 Registry 拉取镜像
docker pull localhost:5000/my-app:latest
docker其它常见命令
bash# 列出所有容器
docker ps -a
# 列出所有镜像
docker image ls
docker images
# 启动容器
docker start 容器名称/容器ID
# 停止容器
docker stop 容器名称/容器ID
# 强制停止容器
docker kill 容器名称/容器ID
# 重启容器
docker restart 容器名称/容器ID
# 删除容器
docker rm 容器名称/容器ID
# 删除镜像
docker rmi 容器名称/容器ID
想要通过 Docker 将项目部署到服务器上或是分发项目供他人使用,就需要将项目构建为镜像,通过 Dockerfile 构建镜像是一种常见的做法。Dockerfile 是一个文本文件,其中包含了一系列的命令和参数,用于定义在构建镜像时的操作步骤。通过编写 Dockerfile,你可以指定所需的基础镜像、设置环境变量、运行命令、添加文件等操作,最终将这些步骤打包成一个镜像,方便部署到服务器上或者分发给他人使用。
Dockerfile常用指令:
bash# 使用基础镜像
FROM python:3.9-slim
# 设置工作目录
WORKDIR /app
# 复制项目文件到工作目录
COPY . .
# 安装依赖
RUN pip install -r requirements.txt
# 暴露端口
EXPOSE 8000
# 启动应用
CMD ["python", "app.py"]
写好 Dockerfile 后,就可以通过该文件构建镜像了。
bashdocker build -t 仓库地址/命名空间/镜像名:标签 . docker build -t 仓库地址/命名空间/镜像名:标签 -f /path/myDockerfile .
选项参数:
每次发布更改内容都需要打包镜像后上传到生产环境再部署很麻烦,将镜像推送到私有仓库,并在生产环境直接从仓库中拉取镜像更加高效。
bash# 登录仓库
docker login 仓库地址
docker tag myapp:latest myusername/myapp:latest
# 推送镜像 仓库地址/命名空间/镜像名:标签
docker push myusername/myapp:latest
当项目依赖的服务较多时,每个容器都要单独配置运行,指定网络。使用Docker Compose,可以通过一个YAML文件定义服务,并同时运行它们。使用 Docker Compose 可以大大简化管理和部署多个服务的过程。Docker Compose 允许你通过一个 YAML 文件定义所有相关的服务、网络、卷等配置,并通过一个命令同时启动这些服务。 Docker Compose 将所管理的容器分为三层:工程(Project)、服务(Service)、容器(Container)。
在要部署项目的目录创建一个 docker-compose.yml 文件:
bashversion: '3'
services:
web:
image: myusername/myapp:latest
ports:
- "8000:8000"
depends_on:
- db
environment:
- DATABASE_HOST=db
- DATABASE_PORT=5432
networks:
- mynetwork
db:
image: postgres:13
environment:
POSTGRES_USER: exampleuser
POSTGRES_PASSWORD: examplepass
POSTGRES_DB: exampledb
volumes:
- db-data:/var/lib/postgresql/data
networks:
- mynetwork
volumes:
db-data:
networks:
mynetwork:
在 docker-compose.yml 文件所在的目录执行
bashdocker compose up -d
docker compose up 根据 docker-compose.yml 文件内容启动、创建、连接服务。 -d 参数表示以后台方式运行。 -f 如果文件名称不是 docker-compose.yml ,可以通过 -f 命令指定,使用方法与 构建镜像 章节一致。 每次更改了 docker-compose.yml 文件,都需要重新运行 docker-compose up -d 命令以应用更改。
本文作者:sora
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!