Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
Docker 官网:https://www.docker.com
DockerHub:https://hub.docker.com/
Docker 为什么会出现
- 项目开发、测试、生产环境的不同,导致环境配置十分繁琐
- 发布一个项目,项目需要与环境一并打包
- 在 Windows 下配置的应用环境( JDK, MySQL, Redis 等等),不能跨平台,无法与其他平台(例如 Linux)兼容
- …
Docker 为以上种种问题,给出了解决方案
Docker 能做什么
虚拟机
Docker
两者比较
传统虚拟机技术,虚拟一套硬件然后运行特定的操作系统,在此系统上运行与安装软件
Docker 容器内的应用直接运行在宿主机上,没有虚拟硬件和内核,更加轻便
每个容器间相互隔离,其内都有一个属于自身的文件系统,互不干扰
总之,Docker 具有许多优点:
- 更快速的交付和部署
- 更便捷的升级和扩展
- 更简单的运维
- 更高效的资源利用
Docker 基本概念
镜像(Image):
相当于一个 root 文件系统。
容器(Container):
通过镜像创建的一个或一组应用。
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是类,容器是对应的实例。
仓库(Repository):
存放镜像的地方,分为公开仓库和私有仓库。
DockerHub、阿里云等都有 Docker 仓库。
Read More:Docker架构
Docker 安装
https://docs.docker.com/get-docker/
https://www.runoob.com/docker/centos-docker-install.html
注意:docker-ce 是社区版,ee 是企业版
配置阿里云镜像加速
https://help.aliyun.com/document_detail/60750.html
Docker 运行流程
Docker 运行原理
Docker 工作方式
Docker 是一种 Client-Server 结构的系统,Docker 守护进程 (Docker Daemon) 运行在主机上,通过 Socket 从客户端访问
DockerServer 收到 DockerClient 的指令,就会执行该指令
Docker 为什么比虚拟机快
Docker 拥有比虚拟机更少的抽象层
Docker 利用的是宿主机的内核,虚拟机需要 GuestOS
GuestOS:VM(虚拟机)系统(OS)
HostOS:物理机系统(OS)
新建容器时,Docker 不需要重新加载一个操作系统内核,省去了引导过程
Docker 常用命令
https://docs.docker.com/reference/
帮助命令
# docker 版本信息
docker version
# docker 系统信息,包括镜像和容器的数量
docker info
# docker 帮助信息
docker 命令 --help
镜像命令
docker images
查看所有本地主机上的镜像
[root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcat latest c662ee449a7e 8 days ago 680MB nginx latest f8f4ffc8092c 9 days ago 133MB mysql latest 2fe463762680 9 days ago 514MB hello-world latest feb5d9fea6a5 13 days ago 13.3kB centos latest 5d0da3dc9764 3 weeks ago 231MB redis latest 02c7f2054405 4 weeks ago 105MB rabbitmq management 3e83da0dc938 5 weeks ago 253MB portainer/portainer latest 580c0e4e98b0 6 months ago 79.1MB elasticsearch 7.9.2 caa7a21ca06e 12 months ago 763MB # 解释 REPOSITORY 镜像的仓库源 TAG 镜像的标签 IMAGE ID 镜像的id CREATED 镜像的创建时间 SIZE 镜像的大小 # 可选项 -a, --all # 列出所有镜像 -q, --quiet # 只显示镜像的id
docker search
搜索镜像
[root@localhost ~]# docker search mysql NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 11511 [OK] mariadb MariaDB Server is a high performing open sou… 4368 [OK] mysql/mysql-server Optimized MySQL Server Docker images. Create… 850 [OK] centos/mysql-57-centos7 MySQL 5.7 SQL database server 91 mysql/mysql-cluster Experimental MySQL Cluster Docker images. Cr… 88 centurylink/mysql Image containing mysql. Optimized to be link… 59 [OK] # 可选项 --filter=STARS=3000 # 筛选STARS大于3000的镜像
docker pull
下载镜像
docker rmi
删除镜像
docker rmi -f 镜像id # 删除指定镜像 docker rmi -f 镜像id,镜像id,镜像id # 删除多个镜像 docker rmi -f ${docker images -aq} # 删除全部镜像
容器命令
新建容器并启动
docker run [可选参数] image
# 参数说明
--name="xxxx" 容器名字,tomcat01,tomcat02,tomcat114514,用于区分容器
-d 后台方式运行
-it 交互方式运行
-p 指定容器端口
-p 主机端口:容器端口(常用)
-p 主机ip:主机端口:容器端口
-p 容器端口
# 测试,启动并进入容器
[root@localhost ~]# docker run -it centos /bin/bash
[root@3726acf7506d /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
# 退出容器,返回主机
[root@3726acf7506d /]# exit
exit
[root@localhost ~]# ls
anaconda-ks.cfg initial-setup-ks.cfg
列出所有运行的容器
docker ps #列出当前正在运行的容器
# 可选参数
-a # 列出所有容器,包括正在运行和历史运行的容器
-n=? # 限制显示的容器个数
-q # 只显示容器编号
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
673143eb13f9 portainer/portainer "/portainer" 7 hours ago Up 24 minutes 0.0.0.0:8088->9000/tcp, :::8088->9000/tcp youthful_sutherland
edaaf8cdd660 rabbitmq:management "docker-entrypoint.s…" 2 weeks ago Up 24 minutes 4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, :::5672->5672/tcp, 15671/tcp, 15691-15692/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp, :::15672->15672/tcp rabbit
20e0d6112f64 redis "docker-entrypoint.s…" 2 weeks ago Up 24 minutes 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp redis
73569253a92c 0716d6ebcc1a "docker-entrypoint.s…" 2 weeks ago Up 24 minutes 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql
退出容器
exit # 停止容器并退出
ctrl + p + q # 不停止容器并退出
删除容器
docker rm 容器id # 删除指定容器
docker rm -f ${docker ps -aq} # 删除所有容器
docker ps -a -q|xargs docker rm # 删除所有容器
启动和停止容器的相关操作
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止容器
留坑:
docker run -d xxxx
使用该命令后台启动容器,过一会发现容器自动停止
Docker 容器后台运行,必须要有一个前台进程
其他命令
日志命令
docker logs
# 可选参数
-tf # 显示日志
--tail num # 要显示的日志条数
查看容器进程信息
docker top 容器id
查看镜像元数据
docker inspect 容器id
进入当前正在运行的容器
方式一
# 容器通常是后台运行的方式,有时候需要进入容器,修改一些配置
docker exec -it 容器id [bash或shell]
方式二
docker attach 容器id
区别
docker exec
进入容器后开启一个新的终端
docker attach
进入容器正在执行的终端,不会启动新进程
从容器拷贝文件到主机
docker cp 容器id:容器内路径 目的主机路径
命令总结
Docker 可视化面板
可视化面板工具日常很少使用,仅供测试
portainer
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
Rancher
Docker 镜像加载原理
UnionFS (联合文件系统)
UnionFS 是一种分层、轻量并且高性能的文件系统,它支持对文件系统的修改作为一次提交,进行一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。
UnionFS 是 Docker 镜像的基础,镜像可以通过分层进行继承,基于基础镜像,可以制作具体的各种镜像。
特性:
一次同时加载多个文件系统,从外界看,只有一个文件系统,联合加载会把各层系统文件叠加起来,最终的系统文件会包含所有底层文件和目录。
加载原理
Docker 镜像实际上由一层一层的文件系统组成,即 UnionFS。
bootfs (boot file system) 主要包含 bootloader 和 kernel,bootloader 主要引导加载 kernel,Linux 刚启动时会加载 bootfs,Docker 镜像的最底层就是 bootfs。这一层与典型的 Linux/Unix 系统是一样的,包含 boot 加载器和内核。当boot加载完成后,整个内核存在于内存中,此时内存的使用权已由 bootfs 转交给内核,系统会自动卸载 bootfs。
rootfs (root file system) 在 bootfs 之上,包含典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件,rootfs 就是各种不同操作系统的发行版,如 Ubuntu,CentOS 等。
平时安装的 CentOS 都是按 GB 计算,为什么 Docker 才几百 MB?
[root@localhost ~]# docker images centos
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 5d0da3dc9764 3 weeks ago 231MB
对于一个精简版 OS,rootfs 很小,只包含最基础的命令、工具和程序库,底层直接用的是 Host 的 Kernel,本身只提供 rootfs。
由此可见,对于不同的 Linux 发行版本,bootfs 基本是一致的,rootfs 会有所差别,即不同发行版可以共用 bootfs。
如何理解分层
观察 Docker 下载镜像的过程,可以看到一层一层的下载:
为什么 Docker 要采用分层的结构?
最大的好处是资源共享,例如,多个镜像由相同的 base 镜像构建,那么宿主机只需在磁盘上保留一份 base 镜像,内存中也只需加载一份 base 镜像,就可以为所有容器服务,镜像的每一层都可以进行共享。
docker image inspect xxxx
查看镜像分层信息
[root@localhost ~]# docker image inspect mysql:5.7
[
{
"Id": "sha256:9f35042c6a98363147ae456147643a3d14c484640f13f4ab207cf2c296839baf",
"RepoTags": [
"mysql:5.7"
],
"RepoDigests": [
"mysql@sha256:360c7488c2b5d112804a74cd272d1070d264eef4812d9a9cc6b8ed68c3546189"
],
"Parent": "",
"Comment": "",
"Created": "2021-09-28T08:18:07.951097511Z",
"Container": "3c0f8c1100d9abdbe629b2617727a637847c69e7a46fd142596b78e28087fb3f",
"ContainerConfig": {
"Hostname": "3c0f8c1100d9",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"3306/tcp": {},
"33060/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOSU_VERSION=1.12",
"MYSQL_MAJOR=5.7",
"MYSQL_VERSION=5.7.35-1debian10"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"mysqld\"]"
],
"Image": "sha256:9d2d1742b119869ea812b372c42f9187d3d08c53ca2af103cd93e2f415789f53",
"Volumes": {
"/var/lib/mysql": {}
},
"WorkingDir": "",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {}
},
"DockerVersion": "20.10.7",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"3306/tcp": {},
"33060/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOSU_VERSION=1.12",
"MYSQL_MAJOR=5.7",
"MYSQL_VERSION=5.7.35-1debian10"
],
"Cmd": [
"mysqld"
],
"Image": "sha256:9d2d1742b119869ea812b372c42f9187d3d08c53ca2af103cd93e2f415789f53",
"Volumes": {
"/var/lib/mysql": {}
},
"WorkingDir": "",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 448231647,
"VirtualSize": 448231647,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/ada332e1d9bf25db7e8f7cf83db2c4a3f8426eb7bdfe0be3664fb3ffb403a6a1/diff:/var/lib/docker/overlay2/2ec01820c2d54238f6ea0bccfe4824430554050bec04fa4a4777d077036428e3/diff:/var/lib/docker/overlay2/be77c514734d30c85acc52166dd3b6265785b1917fe36f98c726dc35941b310e/diff:/var/lib/docker/overlay2/191ed40243b6aea8b7cca5c4030d07be5b08880d62f4a62022f4d4097e27c366/diff:/var/lib/docker/overlay2/ad1625acde0a506677de7e116085d2cf2f3d7914970229be050a26f2fac8c425/diff:/var/lib/docker/overlay2/761fde36efc5dd18f45f028a74f5d552fe881cb082aa1977d8705cf339089f72/diff:/var/lib/docker/overlay2/331c558c501038e534ba76367e0f63663733d96da930496306997e37b7bd7b45/diff:/var/lib/docker/overlay2/f845ddda6d164fa72587002cdd7244f533d5e87d8d07fe32af9185a69573a43f/diff:/var/lib/docker/overlay2/2bb1bf94a07e00abcb648e69d9dfdba79d04919e6510503f0915197f39cbc05f/diff:/var/lib/docker/overlay2/8d06674bf384b552980456abebc1c9b28602cbf6119a919510575cb7e6870d95/diff",
"MergedDir": "/var/lib/docker/overlay2/56c6d33bf549a5de2cef76caee3a0b7d622b71ca150c97aec98fd65bc0daa20f/merged",
"UpperDir": "/var/lib/docker/overlay2/56c6d33bf549a5de2cef76caee3a0b7d622b71ca150c97aec98fd65bc0daa20f/diff",
"WorkDir": "/var/lib/docker/overlay2/56c6d33bf549a5de2cef76caee3a0b7d622b71ca150c97aec98fd65bc0daa20f/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:476baebdfbf7a68c50e979971fcd47d799d1b194bcf1f03c1c979e9262bcd364",
"sha256:f2f5bad82361770ad8ec94444e6e0499d79dddf8100f21ca24e9cddec85009d4",
"sha256:96fe563c6126ed009136798afd7d88f82205232e93d7df5873e57beecc450249",
"sha256:44bc6574c36fc508f365a3f9313bd129074115cd3fd247b7de741d2b88d455af",
"sha256:e333ff907af7d9103e9cb74f3ee450be324333a1b4db08fea9bb8c6f6bf1846d",
"sha256:4cffbf4e4fe3490ea3df6d9567dc2cef46c242be61673da9ec2e0cffc4994229",
"sha256:42417c6d26fccb39f58ad78542e033654b1b62ef4f768ff702596a8d4fe702b4",
"sha256:3622b32457db96d80047fe5fd536a7942d48f10e72d76a3827a0c124f86e8fac",
"sha256:9955f67940c9f8b2d3c51225fb646e5b704f83af9634ef5e7046e9d0374a9b44",
"sha256:b53fd933647793b71756e69426dc8e435e8e283560ba14539d9746dbeb9d8927",
"sha256:b2cd93f4f068d080f1d4759a651a6c39b817f8f4c8a02be538292c4674309410"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
所有的 Docker 镜像都源于一个基础镜像层,当进行修改或增加新内容时,就会在当前镜像层之上,创建新镜像层。
Docker 镜像都是只读的,当容器启动时,就将新一层(可写)加载到镜像之上。
这一层就是通常所说的容器层,容器层之下的都是镜像层。
容器数据卷
容器数据卷是什么
如果数据都存储在容器内部,一旦删除容器,数据就会丢失
另外,我们需要有一个容器间数据共享的技术,并将容器中产生的数据同步到本地
这就是卷技术,可以将容器内的目录,挂载到 Linux 本机上
数据卷使用
docker run -it -v 主机目录:容器目录
# 测试
[root@localhost home]# docker run -it -v /home/test:/home centos /bin/bash
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
850915c6c1e6 centos "/bin/bash" 4 minutes ago Up 4 minutes
# 查看容器信息,找到 Mounts ,即挂载属性
[root@localhost ~]# docker inspect 850915c6c1e6
具名挂载和匿名挂载
# 匿名挂载
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 具名挂载
docker run -d -P --name nginx02 -v named-nginx:/etc/nginx nginx
具名挂载的特点是:-v 卷名:容器内路径
通过具名挂载可以方便的找到卷
且大多数情况下使用具名挂载
# 区分具名、匿名、指定路径挂载
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径::容器内路径 # 指定路径挂载
# 通过 -v 容器内路径: ro rw 改变读写权限
# ro readonly 只读,即只能通过宿主机操作,容器内部无法操作
# rw readwrite 可读写
docker run -d -P --name nginx02 -v jumping-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v jumping-nginx:/etc/nginx:rw nginx
DockerFile
DockerFile 就是用来构建 Docker 镜像的文件,也就是命令脚本
通过这个脚本可以生成镜像
一个简单的演示
# 编写一个脚本文件 dockerfile01
FROM centos
VOLUME ["volume01","volume02"] #匿名挂载
CMD echo "eeeeeeeeeeend"
CMD /bin/bash
# 运行脚本
docker build -f dockerfile01 -t rayucan/centos:1.0 .
指令详解
https://www.runoob.com/docker/docker-dockerfile.html
构建步骤
- 编写一个 DockerFile 文件
docker build
构建成一个镜像docker run
运行镜像docker push
发布镜像
DockerHub CentOS 官方的 DockerFile
FROM scratch
ADD centos-7-x86_64-docker.tar.xz /
LABEL \
org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20201113" \
org.opencontainers.image.title="CentOS Base Image" \
org.opencontainers.image.vendor="CentOS" \
org.opencontainers.image.licenses="GPL-2.0-only" \
org.opencontainers.image.created="2020-11-13 00:00:00+00:00"
CMD ["/bin/bash"]
总结
DockerFile 是面向开发的,发布项目或发布镜像都需要编写 DockerFile,这个文件并不复杂。
DockerFile:构建文件,定义了一切步骤
DockerImages:通过 DockerFile 构建生成的镜像,即最终发布和运行的产品
DockerContainer:容器就是镜像运行起来提供的服务器
- Post link: http://example.com/2021/10/07/Docker/
- Copyright Notice: All articles in this blog are licensed under unless otherwise stated.