Docker
虚拟化
虚拟化技术
我们可以把虚拟化技术作为计算机资源的一种管理技术,它掌控计算机中的CPU、存储、网络等各种实体资源,并将这些资源抽象化,通过统一的形式展现给应用程序。也就是说,运行在虚拟环境中的程序,对接和使用的是虚拟化程序提供的资源,它们并没有接触真实的环境。在迁移到其他机器的时候,只要通过虚拟化程序制造出完全一样的虚拟环境,就能让应用程序的运行与之前完全一致。
虚拟化技术将应用与真实的计算机资源分离,不但打破了应用程序与真实资源之间不可切割的障碍,也让资源跨物理或地域的配置和使用成为可能。通过虚拟化技术,可以更容易地完成应用程序对依赖资源的解耦,让应用程序轻松地运行在更多的环境之中。
虚拟机与容器
虚拟机(VM)是计算机系统的仿真。简而言之,它可以在一台计算机的硬件上运行看似多台单独的计算机。
操作系统(OS)及其应用程序共享单个主机服务器或主机服务器池的硬件资源。每个VM都需要自己的基础OS,并且硬件已虚拟化。系统管理程序或虚拟机监视器(Hypervisor)是创建和运行VM的软件。它位于硬件和虚拟机之间,是虚拟化服务器所必需的。
使用容器,可以像虚拟机(VM)一样虚拟化基础计算机,而无需虚拟化OS。
容器位于物理服务器及其主机操作系统(通常为Linux或Windows)的顶部。每个容器共享主机OS内核,通常也共享二进制文件和库。共享组件是只读的。共享操作系统资源(例如库)可以大大减少重现操作系统代码的需求,并且意味着服务器可以通过安装单个操作系统来运行多个工作负载。因此,容器非常轻便-它们只有几兆字节大小,只需几秒钟即可启动。与容器相比,VM运行需要几分钟,并且比等效容器大一个数量级。
Docker
Docker作为一款优秀的容器集成软件,和传统的容器虚拟化工具相比,有着非常多的改进与优化。
由于Docker的设计是为独立应用封装容器,所以我们可以很轻松地通过Docker容器组装需要的服务系统体系,整个过程省去了大量应用程序搭建和调试的时间。使用Docker时,用很小的修改就能代替我们之前所做的大量工作,节约了大量时间。
镜像
在Docker中,镜像是一个包含应用程序及相关依赖库的文件,在Docker容器启动的过程中,它以只读的方式被用于创建容器运行的基础环境。如果把容器理解为应用程序运行的虚拟环境,那么镜像就可以被看作这个环境的持久化副本。通过镜像,我们可以很容易地保存虚拟环境的运行状态,并可以很方便地镜像迁移及反复构造相同的运行环境。
镜像管理命令
获取镜像
docker cli 与git 相似 使用docker pull 命令就可以从网上的镜像库下载所需要的镜像。
下面以mysql镜像为例 使用docker pull mysql 就可以将该镜像拉去到本地了。
[root@VM-20-8-centos docker-test]# docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete d
ac563158d721: Pull complete
d2ba16033dad: Pull complete
688ba7d5c01a: Pull complete
00e060b6d11d: Pull complete
1c04857f594f: Pull complete
4d7cfa90e6ea: Pull complete
e0431212d27d: Pull complete
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest
可以看到 using default tag:latest 这一行,镜像名还包括了标签名,如果pull的时候不指定tag则默认是最新版本的镜像
同样我们也加上标签,拉取指定版本mysql
[root@VM-20-8-centos docker-test]# docker pull mysql:5
5: Pulling from library/mysql
72a69066d2fe: Already exists
93619dbc5b36: Already exists
99da31dd6142: Already exists
626033c43d70: Already exists
37d5d7efb64e: Already exists
ac563158d721: Already exists
d2ba16033dad: Already exists
0ceb82207cd7: Pull complete
37f2405cae96: Pull complete
e2482e017e53: Pull complete
70deed891d42: Pull complete
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5
docker.io/library/mysql:5
查看镜像
使用docker images 命令即可查看本地镜像
[root@VM-20-8-centos docker-test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
golang 1.17 276895edf967 4 months ago 941MB
golang latest 276895edf967 4 months ago 941MB
mysql 5 c20987f18b13 4 months ago 448MB
mysql latest 3218b38490ce 4 months ago 516MB
每个镜像都有一个独立的imageID,标识每个镜像
删除镜像
docker rmi IMAGEID 或 REPOSITORY:TAG 后面跟上镜像ID 或者镜像名:标签 指定镜像删除
[root@VM-20-8-centos docker-test]# docker rmi mysql:latest
Untagged: mysql:latest
Untagged: mysql@sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709
Deleted: sha256:3218b38490cec8d31976a40b92e09d61377359eab878db49f025e5d464367f3b
Deleted: sha256:aa81ca46575069829fe1b3c654d9e8feb43b4373932159fe2cad1ac13524a2f5
Deleted: sha256:0558823b9fbe967ea6d7174999be3cc9250b3423036370dc1a6888168cbd224d
Deleted: sha256:a46013db1d31231a0e1bac7eeda5ad4786dea0b1773927b45f92ea352a6d7ff9
Deleted: sha256:af161a47bb22852e9e3caf39f1dcd590b64bb8fae54315f9c2e7dc35b025e4e3
Deleted: sha256:feff1495e6982a7e91edc59b96ea74fd80e03674d92c7ec8a502b417268822ff
[root@VM-20-8-centos docker-test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5 c20987f18b13 4 months ago 448MB
docker的镜像是一个多层结构,镜像的每一层都是在原有层的基础上进行改动的。镜像的分层机制与Git的版本控制原理类似,每层镜像都可以被视为一个提交,并且拥有独立的ID,最顶层的ID就被视为镜像ID。
容器
在Docker中,容器是基于镜像运行的轻量级环境,是Docker封装和管理应用程序或微服务的“集装箱”。运行中的容器读取了镜像中基础的程序和依赖库的代码,并将修改保存在一个沙盒环境中,充分保障了应用程序运行的虚拟性和隔离性。
容器管理命令
创建容器
docker create IMAGEID 或 REPOSITORY:TAG 现在将刚刚拉取的mysql镜像构造成容器,构造成功后返回容器ID
[root@VM-20-8-centos docker-test]# docker create mysql:5
e9a9b932e468477a7d225f1acae1f39a8ed0f64f0a5d396f016b39070def3e55
查看容器
docker ps
[root@VM-20-8-centos docker-test]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@VM-20-8-centos docker-test]#
竟然空空如也,回顾一下ps 命令,ps命令是Process Status的缩写,用来列出当前运行的进程。很明显刚刚我们只是创建了容器,但容器并没有启动,docker ps 列出的是运行中的容器状态。想要查看刚刚创建的容器只要加上 -a (也可以写成 -all 顾名思义列出所有容器包括未启动的)参数就行了
[root@VM-20-8-centos docker-test]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e9a9b932e468 mysql:5 "docker-entrypoint.s…" About a minute ago Created elastic_kirch
下面是查看结果解析
可以看到为了方便显示,docker ps 命令显示结果都是截断的,(docker id和command 指令都显示不全)。需要完整查看 再加上 --no-trunc 参数。
[root@VM-20-8-centos docker-test]# docker ps -a --no-trunc
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e9a9b932e468477a7d225f1acae1f39a8ed0f64f0a5d396f016b39070def3e55 mysql:5 "docker-entrypoint.sh mysqld" 2 minutes ago Created elastic_kirch
运行容器
docker run IMAGEID 或 REPOSITORY:TAG docker run 让容器在创建完成后运行起来
Docker容器有以下两种运行态。
前台交互式:容器运行在前台,容器运行时直接连接到了程序中运行的程序上,当我们通过命令退出和关闭连接的程序时,就意味着容器停止了运行。在这种场景下,我们通常会通过附加的参数打开容器的伪终端和输入流,这样我们就可以和容器中的程序实现交互了。
虽然容器在前台运行,但我们只是连接到了容器中的应用程序,并没有形成与应用程序完整的交互,要与容器形成完整的交互,还需要使用-t和-i两个参数。在docker run命令中携带**-t或--tty参数,可以让Docker为这个容器分配一个伪终端,为实现交互提供基础。而带入-i或-- interactive**则打开了交互模式,这时候输入流会一直保持,以便于我们向容器中输入命令或数据。
一般容器启动后,docker会给这个容器随机命名,如果我们想要自己命名容器的话需要加上 --name 参数 后面跟的是容器名
[root@VM-20-8-centos docker-test]# docker run -it --name mymysql mysql:5
2022-05-13 06:39:59+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2022-05-13 06:39:59+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2022-05-13 06:39:59+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2022-05-13 06:39:59+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
You need to specify one of the following:
\- MYSQL_ROOT_PASSWORD
\- MYSQL_ALLOW_EMPTY_PASSWORD
\- MYSQL_RANDOM_ROOT_PASSWORD
第一次运行mysql容器时,需要指定密码,这里我们添加**-e**参数指定环境遍量就行了
MYSQL_ROOT_PASSWORD 代表root密码
[root@VM-20-8-centos docker-test]# docker run -it -e MYSQL_ROOT_PASSWORD="123456" --name mymysql mysql
由于携带 -it 参数,使用了交互模式,控制台上会打印一堆log
到最后 显示mysqld 准备好连接时,代表mysql服务器已经成功启动。但此时,mysql服务器进程一直占据终端,不得不重新开启一个控制台。
像这种情况,我们可以直接让其在后台运行。
后台守护式:容器运行在后台,运行的过程不会占用到当前输入指令的终端,也不会连接到容器内的应用程序上。因为我们无法连接到容器中的程序,所以处于这种运行态的容器必须通过指令来关闭。
后台运行 只需要加上**-d** 参数。
[root@VM-20-8-centos ~]# docker run -d -e MYSQL_ROOT_PASSWORD="123456" --name mymysql mysql
05e81fe9d6a45bfa64c473577aa1fdd8a4e9070912be432930f4cd10fc3cdbdd
[root@VM-20-8-centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
05e81fe9d6a4 mysql "docker-entrypoint.s…" 2 seconds ago Up 1 second 3306/tcp, 33060/tcp mymysql
可以看到后台启动了mysql 并且返回 容器ID。
连接到容器
docker attach
docker attach命令可以attach到一个已经运行的容器的stdin,然后进行命令执行的动作。但是需要注意的是,使用docker attach命令可以衔接到容器中运行的主进程上,并且衔接后就依附到了主进程之中,当我们退出程序时,也会导致容器一起停止。
docker attach 容器名 或者 容器ID
docker exec
那么有没有其他的办法来实现在容器中进行操作呢?Docker提供了docker exec命令来达成我们的需求。
docker exec命令可以让我们在容器中执行一条全新的指令,并开启新的进程。使用docker exec命令的方法很简单,给出容器名称或容器ID并提供需要执行的命令即可。进入容器后再用之前设置的密码成功连接数据库
mymysql 后 bash 命令,表示进入容器后自动执行bash命令。
数据卷
容器内的文件环境,虽然能够让程序随意操作其中的文件,但所有的读写都是在沙盒环境中进行的。当容器停止运行并被删除时,这个临时记录着文件修改的层就会被一同丢弃。
Docker提出了**数据卷(Data Volume)**的概念。简而言之,数据卷就是一个挂载在容器内文件系统中的文件或目录。在容器中,数据卷和其他的文件或目录看起来别无二致,但是因为数据卷是从外界挂载在容器中的,所以它可以脱离容器的生命周期而独立存在。正是由于数据卷的生命周期并不等同于容器的生命周期,在容器退出乃至删除之后,数据卷仍不会受到影响,会依然存在于Docker之中。所以,如果通过数据卷保存文件,那么这些文件就不会因为容器的终结而消失。
指定路径挂载
参数 -v src:dst src是宿主机的目录,dst 是容器内的目录。
先在 root目录下创建一个volume 目录,下面再创建file文件,随便写点内容进去。后面我们将使用volume目录作为宿主机挂载目录,挂载在docker的**/volume**目录下
挂载成功后可以看到,容器内挂载目录下内容与宿主机一致。
现在尝试修改内容
然后在另一个终端中查看宿主机下挂载的文件信息
具名挂载
[root@VM-20-8-centos ~]# docker run -d -e MYSQL_ROOT_PASSWORD=yes --name mymysql3 -v volume:/volume mysql:5
c3873912615bb191e41b74003d7507edad6582615f974fae7a8807af4766b63c
[root@VM-20-8-centos ~]# docker volume inspect volume #查看数据卷信息
[
{
"CreatedAt": "2022-05-12T17:43:20+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/volume/_data",
"Name": "volume",
"Options": null,
"Scope": "local"
}
]
如果 宿主机挂载 -v后的src 不是目录或者文件的话,将会创建一个数据卷并以该参数命名。通过 docker volume inspect 查看到该数据卷实际挂载点为 /var/lib/docker/volumes/volume/_data
[root@VM-20-8-centos ~]# docker volume ls #查看数据卷
DRIVER VOLUME NAME
local volume
[root@VM-20-8-centos ~]# docker volume rm volume #删除数据卷 注意需要先删除与其挂载的所有容器
volume
构建镜像(Dockerfile)
前面一直说的是将镜像pull到本地后的操作,那么镜像是怎么构建的呢?
Docker提供了一种通过配置文件创建镜像的方式――使用Dockerfile构建镜像。这种方式是将制作镜像的操作全部写入到一个文件中,而docker build命令可以读取这个文件中的所有操作,并根据这些配置创建相应的镜像。Dockerfile让创建镜像的过程变得更加独立和透明,也使整个过程可以轻松容易地往复执行,是构建镜像和进行容器迁移时一个非常优秀的辅助工具。