Docker官网
容器变得越来越重要,尤其是在云环境中,许多企业甚至在考虑将容器替代 VM 作为其应用程序和工作负载的通用计算平台
systemctl status firewalld
systemctl stop firewalld
systemctl disable firewalld
较旧的 Docker 版本称为 docker 或 docker-engine ,如果已安装这些程序,请卸载它们以及相关的依赖项。
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
在新主机上首次安装 Docker Engine-Community 之前,需要设置 Docker 仓库,之后,您可以从仓库安装和更新 Docker。
yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
在新主机上首次安装 Docker Engine-Community 之前,需要设置 Docker 仓库,之后,您可以从仓库安装和更新 Docker,使用以下命令来设置稳定的仓库**(阿里云)**
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安装最新版本的 Docker Engine-Community 和 containerd
sudo yum install -y docker-ce docker-ce-cli containerd.io
如果提示您接受 GPG 密钥,请选是。
Docker 安装完默认未启动,并且已经创建好 docker 用户组,但该用户组下没有用户。
阿里云镜像获取地址:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors,登陆后,左侧菜单选中镜像加速器就可以看到你的专属地址了:
您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxxxx.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
service docker start
通过运行 hello-world 映像来验证是否正确安装了 Docker Engine-Community
docker run hello-world
运行该代码后首先会从仓库拉取
hello-world
镜像,然后运行该镜像,运行后会输出一个Hello from Docker!
使用docker时无法自动补全镜像名和其他参数,这样使用效率大大降低,下面是解决方法
yum install -y bash-completion
source /usr/share/bash-completion/completions/docker
source /usr/share/bash-completion/bash_completion
输入docker p
后docker会将可选项列出来
docker p
Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等),镜像不包含任何动态数据,其内容在构建之后也不会被改变。
Union FS
联合文件系统是(Union FS)是linux的存储技术,也是Docker镜像的存储方式, 它是分层的文件系统,将不同目录拉到同一个虚拟目录下,下图展示了Docker用Union FS 搭建的分层镜像:(比如最下层是操作系统的引导,上一层是Linux操作系统,再上一层是Tomcat,jdk,再上一层是应用代码)
这些层是只读的,加载完后这些文件会被看成是同一个目录,相当于只有一个文件系统。
我们可以通过docker info查看镜像的一些信息,可以看到存储驱动用的并不是Union FS 而是overlay2,overlay也是一个联合文件系统,所以上述主要介绍联合文件系统的概念,至于这些存储驱动的演变过程和优缺点
镜像构建时,会一层层构建,前一层是后一层的基础,每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。(比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除,在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像,因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉)
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体,容器可以被创建、启动、停止、删除、暂停等。
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间,因此容器可以拥有自己的root文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。
容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样,这种特性使得容器封装的应用比直接在宿主运行更加安全,也因为这种隔离的特性,很多人初学 Docker 时常常会混淆容器和虚拟机。
前面讲过镜像使用的是分层存储,容器也是如此,每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为容器存储层。
容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡,因此,任何保存于容器存储层的信息都会随容器删除而丢失。
镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本,我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像,如果不给出标签,将以latest作为默认标签。
以 Ubuntu 镜像为例,ubuntu是仓库的名字,其内包含有不同的版本标签,如,14.04,16.04,我们可以通过ubuntu:14.04,或者ubuntu:16.04来具体指定所需哪个版本的镜像,如果忽略了标签,比如ubuntu,那将视为ubuntu:latest
仓库名经常以三段式路径形式出现,比如heima.com/nginx-proxy:tag
,前者往往意味着 Docker Registry 多用户环境下的用户名,后者则往往是对应的软件名,但这并非绝对,取决于所使用的具体 Docker Registry 的软件或服务
# 查找镜像
docker search 镜像名称
# 下载镜像
docker pull 镜像名称
# 注意事项:
# 1.如果不写版本号默认拉取最新的版本好latest。
# 2.拉取的时候是多个层一起拉取的,这样可用让其他镜像复用分层
# 3.如果拉取的镜像不写仓库地址默认就是docker.io/library/
# 下载指定版本的镜像 https://hub.docker.com 找到Tags
docker pull mysql:5.7.40
# 查看镜像
docker images
查找指定镜像
# 通过镜像启动容器
docker run -d -p 3306:3306 -v /tmp/etc/mysql:/etc/mysql/mysql.conf.d/ -v /tmp/data/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name mysql mysql:5.7.40
# 参数解释:
# -d:是指容器后台运行,如果不加-d,当用户断开客户端时容器会结束运行
# -p:将容器的3306端口映射到主机的3306端口,用来暴漏端口的 (宿主机:容器)
# -v:这个命令是用来挂载目录的,将本地目录挂载到容器中,这样容器操作的就是本地目录 (宿主机:容器)
# -e:这个命令是配置环境参数的,这里MYSQL_ROOT_PASSWORD=root指的是用root用户运行mysql,可以登录Docker容器通过ENV命令查看
# --name:这个命令是配置Mysql的容器名称的,如果不配置,默认是随机生成的名字
# 查看容器运行状态
docker ps
# 查看全部容器
docker ps -a
# 停止容器
docker stop 容器ID
# 启动停止的容器
docker start 容器ID
# 重启容器
docker restart 容器ID
# 删除容器 对于运行中的容器可以加上-f参数强制删除
docker rm -f 容器ID
# 查看容器运行日志
docker logs -f mysql
# 登录容器
docker exec [options] container command [arg...]
# docker exec -it mysql /bin/bash
# 参数解释:
# 简写 名称 描述
# -d --detach 后台运行模式,在后台执行命令相关命令
# --detach-keys 覆盖容器后台运行的一些参数信息
# -e --env 设置环境变量
# -i --interactive 展示容器输入信息STDIN
# --privileged 为命令提供一些扩展权限
# -t --tty 命令行交互模式
# -u --user 设置用户名(format: [:])
# -w --workdir 指定容器内的目录
LXC是
Linux containers
的简称,Linux Container容器是一种内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源
完整的LXC能力在2008年合入Linux主线,所以容器的概念在2008年就基本定型了,并不是后面Docker造出来的,关于LXC的介绍很多,大体都会说“LXC是Linux内核提供的容器技术,能提供轻量级的虚拟化能力,能隔离进程和资源”,但总结起来,无外乎就两大知识点Cgroups(Linux Control Group)和Linux Namespace,搞清楚他俩,容器技术就基本掌握了。
Linux容器技术其实就是整合内核的功能,让其支持多个容器运行时资源相互隔离;我们知道内核的功能用户是无法直接操作的,必须得有一用户空间的软件,通过系统调用去操作内核功能;所以lxc就是用来操作Linux内核容器化的工具
Docker 引擎首次发布的时候,由两个核心组件构成:LXC 和 Docker daemon
Docker deamon 是一个单一的二进制文件,由 Docker Client 、Docker API、容器运行时、构建镜像等组成, LXC 由命名空间 Namespace 和 控制组 CGroup 等基础工具组成,由 Linux 内核的容器虚拟化技术提供
对 LXC 的依赖自始至终都是个问题
因此,Docker 公司开发了名为 Libcontainer 的自研工具,用于替代 LXC,Libcontainer 的目标是成为与平台无关的工具,可基于不同内核为 Docker 上层提供必要的容器交互功能,在 Docker 0.9 版本中,Libcontainer 取代 LXC 成为默认的执行驱动,也就是现在常说的Runc。
随着时间的推移,Docker daemon 的整体性带来了越来越多的问题,难于变更、运行越来越慢,这并非生态(或Docker公司)所期望的。
Docker 公司意识到了这些问题,开始努力着手拆解这个大而全的 Docker daemon 进程,并将其模块化,这项任务的目标是尽可能拆解出其中的功能特性,并用小而专的工具来实现它,这些小工具可以是可替换的,也可以被第三方拿去用于构建其他工具。
这一计划遵循了在 UNIX 中得以实践并验证过的一种软件哲学:小而专的工具可以组装为大型工具,这项拆解和重构 Docker 引擎的工作仍在进行中,不过,所有容器执行和容器运行时的代码已经完全从 daemon 中移除,并重构为小而专的工具。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MsUhoD0M-1679929771103)(Docker学习笔记.assets/docker265.png)]
这是一个管理和运行容器的守护进程,它推送和拉动镜像,管理存储和网络,并监督容器的运行
Containerd作为一个生产环境可用的OCI 实现,它利用了OCI 运行时和镜像格式,在对 Docker daemon 的功能进行拆解后,所有的容器执行逻辑被重构到一个新的名为 containerd的工具中
它是从 Docker 项目中分离出来,之后 containerd 被捐赠给云原生计算基金会(CNCF)为容器社区提供创建新容器解决方案的基础,所以 Docker 自己在内部使用 containerd,当你安装 Docker 时也会安装 containerd
containerd 通过其 CRI 插件实现了 Kubernetes 容器运行时接口(CRI),它可以管理容器的整个生命周期,包括从镜像的传输、存储到容器的执行、监控再到网络
containerd 在 Linux 和 Windows 中以 daemon 的方式运行,从 1.11 版本之后 Docker 就开始在 Linux 上使用它,Docker 引擎技术栈中,containerd 位于 daemon 和 runc 所在的 OCI 层之间。Kubernetes 也可以通过 cri-containerd 使用 containerd。
如前所述,containerd 最初被设计为轻量级的小型工具,仅用于容器的生命周期管理,然而,随着时间的推移,它被赋予了更多的功能,比如镜像管理。
shim是一个真实运行的容器的真实垫片载体,每启动一个容器都会起一个新的docker-shim的一个进程
shim是实现无daemon的容器(用于将运行中的容器与daemon解耦,以便进行daemon升级等操作)不可或缺的工具
containerd 指挥runc来创建新容器,事实上,每次创建容器时它都会fork一个新的runc实例,不过,一旦容器创建完毕,对应的runc进程就会退出,因此,即使运行上百个容器,也无须保持上百个运行中的runc实例。
一旦容器进程的父进程runc退出,相关联的containerd-shim 进程就会成为容器的父进程,作为容器的父进程,shim 的部分职责如下
这是低级别的容器运行时(实际创建和运行容器的东西),它包括 libcontainer,一个用于创建容器的基于 Go 的本地实现
runc是docker贡献给oci的容器运行时,也是目前使用比较多的容器运行时,docker目前的实现也是使用的runc,如前所述,runc 是 OCI 容器运行时规范的参考实现,Docker 公司参与了规范的制定以及 runc 的开发
去粗取精,会发现 runc 实质上是一个轻量级的、针对 Libcontainer 进行了包装的命令行交互工具(Libcontainer 取代了早期 Docker 架构中的 LXC)