一、Docker概述
1.1Docker为什么会出现?
1.1Docker为什么会出现?
【场景】:
一款产品:开发---->上线 两套环境! 应用环境,应用配置!
问题:因为环境问题,导致服务不可用。所以现在慢慢演变成了,开发即运维
环境配置是十分的麻烦的,每一个机器都要部署环境(集群Redis、ES、Hadoop…)!费时费力。
发布一个项目(jar+(Redis、MYSQL、JDK、ES)),项目能不能带着环境安装打包!Docker就是干这个事情的
java----apk----发布(应用商店)----张三使用apk----安装即可用!
java----jar(环境)----打包项目带上环境(镜像)----(Docker仓库:商店)----下载我们发布的镜像-----直接运行即可
Docker给以上的问题,提出了问题的解决方案!
Docker的思想就来自于集装箱,相互隔离!
JRE—多个应用(端口冲突)----原来都是交叉的!
隔离:Docker核心思想!打包装箱!每个箱子是相互隔离的。
Docker通过隔离机制,可以将服务器利用到极致!
1.2Docker的历史
2010年,几个搞IT的年轻人,就在美国成立了一家公司dotCloud, 做一些pass的云计算服务,基于 Linux Container 技术有关的容器化技术,什么是 PaaS 呢?PaaS 的全称是 Platform as a Service,也就是平台即服务,这个概念在2010年热的一塌糊涂,直到现在也没凉下来。
他们将将自己的容器化技术命名为Docker!Docker刚刚诞生的时候,没有引起行业的注意!dotCloud,就活不下去!开放源代码!2013年,Docker公司的创始人Solomon Hykes将Docker开源,越来越多的人发现了Docker的优点,就火了,Docker,每个月就会更新一个版本!
2014年4月9日,Docker1.0发布!Docker为什么这么火?十分的轻巧!在容器技术出来之前,我们都是使用虚拟机技术!
虚拟机:在windows中装一个Vmware,通过这个软件我们可以虚拟出来一台或者多台电脑!笨重!
虚拟机也是属于虚拟化技术,Docker容器技术,也是一种虚拟化技术!
vm: linux centos原生镜像(一个电脑) 隔离,需要开启多个虚拟机!
docker: 隔离,镜像(最核心的环境 4m jdk+mysql)这个镜像十分的小巧,运行镜像就可以了!小巧,启动非常快,几乎是秒级启动
到现在,所有开发人员都必须要会Docker!
聊聊Docker
Docker是基于Go语言开发的!开源项目!Docker官网
文档地址:https://docs.docker.com/ Docker的文档是超级详细的!
仓库地址:https://hub.docker.com/
1.3Docker能做什么
之前的虚拟机技术!
虚拟机技术缺点:
1、资源占用十分多
2、冗余步骤多
3、启动很慢!
容器化技术
容器化技术不是模拟的一个完成的操作系统
比较Docker和虚拟机技术的不同:
- 传统虚拟机,虚拟出一套硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
- 容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了
- 每个容器是互相隔离,每个容器内部都有一个属于自己的文件系统,互不影响。
DevOps(开发、运维)
应用更快速的交付和部署
传统:一堆帮助文档,安装程序
Docker:打包镜像发布测试,一键运行
更快捷的升级和扩缩容
使用了Docker之后,我们部署应用和搭积木一样!
项目打包为一个镜像,扩展服务器A!服务器B
更简单的系统运维
在容器化之后,我们的开发,测试环境都是高度一致的。
更高效的计算资源利用:
Docker是内核级别的虚拟化,可以在一个物理机上可以运行很多个实例!服务器的性能可以被压榨到极致。
二、Docker安装
2.1Docker的基本组成
镜像(image):
Docker镜像就好比是一个模板,可以通过模板来创建服务,tomcat镜像----> run ---->tomcat01容器(提供服务器),通过这个镜像可以创建多个容器(最终服务器运行或者项目运行就是在容器中的)。
容器(container):
Docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。启动,停止,删除,基本命令!
目前就可以把这个容器理解为一个简易的linux系统
仓库(repository):
仓库就是存放镜像的地方!
仓库分为公有仓库和私有仓库!
Docker Hub(默认是国外的)
阿里云。。。都有容器服务器(配置镜像加速!)
2.2安装Docker
环境准备
1、需要会一点点Linux的基础
2、CentOS 7
3、我们使用Xshell连接远程服务器进行操作!
环境查看
# 系统内核是3.0以上
[root@kikistudy /]# uname -r
4.18.0-147.5.1.el8_1.x86_64
#系统版本
[root@kikistudy /]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="8 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="8"
PLATFORM_ID="platform:el8"
PRETTY_NAME="CentOS Linux 8 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:8"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-8"
CENTOS_MANTISBT_PROJECT_VERSION="8"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="8"
安装
帮助文档:https://docs.docker.com/engine/install/centos/
#1.卸载旧的版本
[root@kikistudy /]# sudo yum remove docker \
> docker-client \
> docker-client-latest \
> docker-common \
> docker-latest \
> docker-latest-logrotate \
> docker-logrotate \
> docker-engine
#执行结果
[root@kikistudy /]# sudo yum remove docker \
> docker-client \
> docker-client-latest \
> docker-common \
> docker-latest \
> docker-latest-logrotate \
> docker-logrotate \
> docker-engine
Repository epel is listed more than once in the configuration
未找到匹配的参数: docker
未找到匹配的参数: docker-client
未找到匹配的参数: docker-client-latest
未找到匹配的参数: docker-common
未找到匹配的参数: docker-latest
未找到匹配的参数: docker-latest-logrotate
未找到匹配的参数: docker-logrotate
未找到匹配的参数: docker-engine
没有软件包需要移除。
依赖关系解决。
无需任何处理。
完毕!
#2.需要的安装包
[root@kikistudy /]# sudo yum install -y yum-utils
......
已安装:
yum-utils-4.0.17-5.el8.noarch elfutils-debuginfod-client-0.180-1.el8.x86_64
libmodulemd-2.9.4-2.el8.x86_64 libzstd-1.4.4-1.el8.x86_64
完毕!
#3.设置镜像的仓库
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo #默认是从国外下载的!速度极慢
#替换docker阿里云镜像地址
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#安装之前更新yum软件包索引
#清空缓存 linux8以下 linux8没有fast参数
yum makecache fast
#清空缓存 linux8以上
yum makecache
#4.安装最新版docker引擎 docker-ce 社区版 docker-ee企业版
yum install docker-ce docker-ce-cli containerd.io
【注意:】此时如果linux系统是8及其以上会报如下错误,参考博客
原因是:centos8默认使用podman代替docker,所以需要containerd.io.
手动安装:阿里镜像地址:https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/edge/Packages/
安装containerd.io
这里选择的containerd.io版本是比较低的
#4.1安装containerd.io
yum install -y https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/edge/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm
......
已安装:
container-selinux-2:2.144.0-1.module_el8.3.0+475+c50ce30b.noarch
containerd.io-1.2.6-3.3.el7.x86_64
完毕!
安装docker-ce docker-ce-cli
这里选择的 docker-ce-19.03.9-3.el7.x86_64.rpm,别的版本可能报错
#4.2安装docker-ce docker-ce-cli
yum install -y https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/edge/Packages/docker-ce-19.03.9-3.el7.x86_64.rpm
......
已安装:
docker-ce-3:19.03.9-3.el7.x86_64 docker-ce-cli-1:20.10.1-3.el7.x86_64
libcgroup-0.41-19.el8.x86_64
完毕!
#5.启动docker
[root@kikistudy /]# systemctl start docker
#6.查看是否启动成功
[root@kikistudy /]# docker version
Client: Docker Engine - Community
Version: 20.10.1
API version: 1.40
Go version: go1.13.15
Git commit: 831ebea
Built: Tue Dec 15 04:37:17 2020
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 19.03.9
API version: 1.40 (minimum version 1.12)
Go version: go1.13.10
Git commit: 9d988398e7
Built: Fri May 15 00:24:05 2020
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.2.6
GitCommit: 894b81a4b802e4eb2a91d1ce216b8817763c29fb
runc:
Version: 1.0.0-rc8
GitCommit: 425e105d5a03fabd737a126ad93d62a9eeede87f
docker-init:
Version: 0.18.0
GitCommit: fec3683
确定docker是否安装成功:
#7.启动hello-world程序
docker run hello-world
如果本地没有找到hello-world镜像,它会去docker官方去拉取library下的hello-world
#8、查看一下下载的这个hello-world镜像
[root@kikistudy ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 11 months ago 13.3kB
了解:卸载docker
# 1、卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
#2、删除资源
rm -rf /var/lib/docker
# /var/lib/docker docker的默认工作路径
2.3阿里云镜像加速
1、登录阿里云找到容器镜像服务
2、找到镜像加速地址
3、配置使用
#新建目录
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://jgk73kxa.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
2.4回顾hello-world流程
三、Docker底层原理
3.1Docker是怎么工作的?
Docker是一个Client-Server结构的系统,Docker的守护进程(类似windows的服务,运行在后台)运行在主机上。通过Socket从客户端访问!
DockerServer接收到Docker-Client的指令,就会执行这个命令!
3.2Docker为什么比虚拟机快
1、Docker有着比虚拟机更少的抽象层。
2、Docker利用的是宿主机的内核,vm需要Guest OS。
所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免一些引导操作。
虚拟机是加载Guest OS,分钟级别的,而Docker是利用宿主机的操作系统,忽略了这个复杂的过程,是秒级的!
之后学习完毕所有的命令,再回过头来看这段理论就会很清晰!
四、Docker常用命令
4.1帮助命令
#显示docker版本信息
docker version
#显示docker更加详细的信息
docker info
#万能命令
docker 命令 --help
帮助文档的地址:https://docs.docker.com/engine/reference/commandline/
4.2镜像命令
docker images 查看所有本地主机上的镜像
[root@kikistudy /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 11 months ago 13.3kB
#解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签,版本标签信息
IMAGE ID 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小
#可选项
[root@kikistudy /]# docker images --help
Usage: docker images [OPTIONS] [REPOSITORY[:TAG]]
List images
Options:
-a, --all #列出所有的镜像
-q, --quiet #只显示镜像的id
[root@kikistudy /]# docker images -aq #显示所有的镜像
docker search 搜索镜像
[root@kikistudy /]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10308 [OK]
mariadb MariaDB is a community-developed fork of MyS… 3819 [OK]
#可选项,通过收藏来过滤
[root@kikistudy /]# docker search --help
--filter=starts=3000 #搜索出来的镜像就是收藏量STARS大于3000的
[root@kikistudy /]# docker search mysql --filter=3000
docker pull 下载镜像
[root@kikistudy /]# docker pull --help
Usage: docker pull [OPTIONS] NAME[:TAG|@DIGEST]
Pull an image or a repository from a registry
Options:
-a, --all-tags Download all tagged images in the repository
--disable-content-trust Skip image verification (default true)
--platform string Set platform if server is multi-platform capable
-q, --quiet Suppress verbose output
#下载镜像 docker pull 镜像名[:tag]
[root@kikistudy /]# docker pull mysql #下载mysql镜像
Using default tag: latest
latest: Pulling from library/mysql #默认使用最新版,如果不写tag,默认就是latest
6ec7b7d162b2: Pull complete #分层下载,docker image的核心 联合文件系统
fedd960d3481: Pull complete
7ab947313861: Pull complete
64f92f19e638: Pull complete
3e80b17bff96: Pull complete
014e976799f9: Pull complete
59ae84fee1b3: Pull complete
ffe10de703ea: Pull complete
657af6d90c83: Pull complete
98bfb480322c: Pull complete
6aa3859c4789: Pull complete
1ed875d851ef: Pull complete
Digest: sha256:78800e6d3f1b230e35275145e657b82c3fb02a27b2d8e76aac2f5e90c1c30873 #签名 防伪标志
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #真实地址
#以下两个命令是等价的
docker pull mysql
docker pull docker.io/library/mysql:latest
#指定版本下载,且指定的版本一定要在官方镜像存在
[root@kikistudy /]# docker pull mysql:5.7
5.7: Pulling from library/mysql
6ec7b7d162b2: Already exists
fedd960d3481: Already exists
7ab947313861: Already exists
64f92f19e638: Already exists
3e80b17bff96: Already exists
014e976799f9: Already exists
59ae84fee1b3: Already exists
7d1da2a18e2e: Pull complete
301a28b700b9: Pull complete
529dc8dbeaf3: Pull complete
bc9d021dc13f: Pull complete
Digest: sha256:c3a567d3e3ad8b05dfce401ed08f0f6bf3f3b64cc17694979d5f2e5d78e10173
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
docker rmi 删除镜像
[root@kikistudy /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 f07dfa83b528 3 days ago 448MB
mysql latest a347a5928046 3 days ago 545MB
hello-world latest bf756fb1ae65 11 months ago 13.3kB
#删除镜像可以通过image id 也可以通过名称来删
[root@kikistudy /]# docker rmi -f f07dfa83b528 #删除指定id
Untagged: mysql:5.7
Untagged: mysql@sha256:c3a567d3e3ad8b05dfce401ed08f0f6bf3f3b64cc17694979d5f2e5d78e10173
Deleted: sha256:f07dfa83b5283f486f1fa1628cb8b4a18a4d071a486708acc5c06243ca7f592a
Deleted: sha256:1137660d239dd339c83697d1d5cc93542333aaf35c1fd90418f9c0d166c23487
Deleted: sha256:20c29fc0161bc3cc0addc48ab1aeb70f605a5529590fd32d01502d58d1c6dc10
Deleted: sha256:8615ae1ee613441540ee54a2c517eb0600a6c83667a79f7ca74acc9ffec4c9a4
Deleted: sha256:252efab3ecb7891820c5a340645044850d6edc7815c6588450d74b0a743424f4
#删除所有镜像 #docker images -aq 查出所有的镜像id
[root@kikistudy /]# docker rmi -f 镜像id #删除指定的容器
[root@kikistudy /]# docker rmi -f 镜像id 镜像id 镜像id 镜像id #删除多个容器
[root@kikistudy /]# docker rmi -f $(docker images -aq) #递归删除所有镜像,删除全部的容器
4.3容器命令
说明:我们有了镜像才可以创建容器,linux,下载一个centos镜像来测试学习
[root@kikistudy /]# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
7a0437f04f83: Pull complete
Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
Status: Downloaded newer image for centos:latest
docker.io/library/centos:latest
新建容器并启动
docker run [可选参数] image
# 参数说明
--name="Name" 容器名字 tomcat01 tomcat02 ,用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-i
-t
-P 大P,指定容器的端口 -p 8080:8080
-P ip:主机端口:容器端口
-P 主机端口:容器端口 主机端口映射到容器端口 (常用)
-P 容器端口
容器端口
-p 小p,随机指定端口
#测试 ,启动并进入容器
[root@kikistudy /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 300e315adb2f 2 weeks ago 209MB
[root@kikistudy /]# docker run -it centos /bin/bash
[root@f936082dfb33 /]# #这里的主机名就是镜像id
[root@f936082dfb33 /]# ls #查看容器内的centos,基础版本,很多命令都是不完善的!
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
#从容器中退回主机
[root@f936082dfb33 /]# exit #退出镜像
列出所有的运行的容器
#docker ps 命令
# 列出当前正在运行的容器
-a # 列出当前正在运行的容器+会顺带历史运行过的容器
-n=? # 显示最近创建的容器
-q # 只显示容器的编号
#查看当前运行的容器
[root@kikistudy /]# docker ps
#查看运行过的容器
[root@kikistudy /]# docker ps -a
[root@kikistudy /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@kikistudy /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f936082dfb33 centos "/bin/bash" 8 minutes ago Exited (0) 3 minutes ago peaceful_lalande
b1508cf1ba77 bf756fb1ae65 "/hello" 2 days ago Exited (0) 2 days ago condescending_easley
[root@kikistudy /]# docker ps -a -n=1 # 只显示一个
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f936082dfb33 centos "/bin/bash" 12 minutes ago Exited (0) 6 minutes ago peaceful_lalande
[root@kikistudy /]# docker ps -aq #只显示容器id
f936082dfb33
b1508cf1ba77
退出容器
exit #直接容器停止并且退出
ctrl + P + Q #容器不停止退出
删除容器
docker rm 容器id #删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm -f
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 #强制停止当前容器
4.4常用其他命令
后台启动容器
# 命令 docker run -d 镜像名!
[root@kikistudy /]# docker run -d centos
7763628b8689500f395b8074bd453be7cd28e494c10a0ba10b718c977635b908
# 问题docker ps,发现centos停止了
# 常见的坑,docker容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
查看日志
[root@kikistudy /]# docker logs --help
Usage: docker logs [OPTIONS] CONTAINER
Fetch the logs of a container
Options:
--details Show extra details provided to logs
-f, --follow Follow log output
--since string Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or
relative (e.g. 42m for 42 minutes)
-n, --tail string Number of lines to show from the end of the logs (default "all")
-t, --timestamps Show timestamps
--until string Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or
relative (e.g. 42m for 42 minutes)
# 条数 容器
[root@kikistudy /]# docker logs -f -t --tail 10 7763628b8689
docker logs -f -t --tail 容器,没有日志
# 自己编写一段shell脚本
"while true;do echo kikistudy;sleep 1;done"
[root@kikistudy /]# docker run -d centos /bin/sh -c "while true;do echo kikistudy;sleep 1;done"
# [root@kikistudy /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
837341c266f2 centos "/bin/sh -c 'while t…" 3 seconds ago Up 2 seconds lucid_cori
# 显示日志
-tf # 显示日志 f指的是format 带上时间
--tail number # 要显示的日志条数
[root@kikistudy /]# docker logs -tf --tail 10 837341c266f2 # 显示指定行数的日志
查看容器中的进程信息 ps
[root@kikistudy /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
837341c266f2 centos "/bin/sh -c 'while t…" 8 minutes ago Up 8 minutes lucid_cori
# 命令 docker top 容器id
[root@kikistudy /]# docker top 837341c266f2
UID PID PPID C STIME TTY TIME CMD
root 8624 8608 0 16:38 ? 00:00:00 /bin/sh -c while true;do echo kikistudy;sleep 1;done
root 23273 8624 0 16:46 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
查看镜像的元数据
[root@kikistudy /]# docker inspect --help
Usage: docker inspect [OPTIONS] NAME|ID [NAME|ID...]
Return low-level information on Docker objects
Options:
-f, --format string Format the output using the given Go template
-s, --size Display total file sizes if the type is container
--type string Return JSON for specified type
[root@kikistudy /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
837341c266f2 centos "/bin/sh -c 'while t…" 11 minutes ago Up 11 minutes lucid_cori
eb156c5c5180 centos "/bin/sh -C 'while t…" 11 minutes ago Exited (127) 11 minutes ago quizzical_torvalds
b4b359dd429f centos "/bin/sh -C 'while t…" 12 minutes ago Exited (127) 12 minutes ago hopeful_beaver
73c7438b972d centos "/bin/bash" 21 minutes ago Exited (0) 12 minutes ago romantic_swanson
7763628b8689 centos "/bin/bash" 31 minutes ago Exited (0) 31 minutes ago gracious_nightingale
c3f535e2a6dd centos "/bin/bash" 36 minutes ago Exited (0) 34 minutes ago flamboyant_sammet
# 命令 docker inspect 容器id
#测试
[root@kikistudy /]# docker inspect 837341c266f2
[
{
"Id": "837341c266f2c786a120184da915f60dba20cc82136c2413afca739defea38ad",
"Created": "2020-12-25T08:38:26.051525067Z",
"Path": "/bin/sh",
"Args": [
"-c",
"while true;do echo kikistudy;sleep 1;done"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 8624,
"ExitCode": 0,
"Error": "",
"StartedAt": "2020-12-25T08:38:26.863016384Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
"ResolvConfPath": "/var/lib/docker/containers/837341c266f2c786a120184da915f60dba20cc82136c2413afca739defea38ad/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/837341c266f2c786a120184da915f60dba20cc82136c2413afca739defea38ad/hostname",
"HostsPath": "/var/lib/docker/containers/837341c266f2c786a120184da915f60dba20cc82136c2413afca739defea38ad/hosts",
"LogPath": "/var/lib/docker/containers/837341c266f2c786a120184da915f60dba20cc82136c2413afca739defea38ad/837341c266f2c786a120184da915f60dba20cc82136c2413afca739defea38ad-json.log",
"Name": "/lucid_cori",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"Capabilities": null,
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/b8b73cc525527bde3da5116dd4d71c5768e6a4eaf1d6b486ff6ed945fdfcda6d-init/diff:/var/lib/docker/overlay2/a197712d50b7a67a39b70e7ddda9d1dd07a21af6693750747175b501bf7e7466/diff",
"MergedDir": "/var/lib/docker/overlay2/b8b73cc525527bde3da5116dd4d71c5768e6a4eaf1d6b486ff6ed945fdfcda6d/merged",
"UpperDir": "/var/lib/docker/overlay2/b8b73cc525527bde3da5116dd4d71c5768e6a4eaf1d6b486ff6ed945fdfcda6d/diff",
"WorkDir": "/var/lib/docker/overlay2/b8b73cc525527bde3da5116dd4d71c5768e6a4eaf1d6b486ff6ed945fdfcda6d/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "837341c266f2",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh",
"-c",
"while true;do echo kikistudy;sleep 1;done"
],
"Image": "centos",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20201204",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "249f760cb1686ee75bce8cd9d73f0aae967161c3a9edb63dba7440058c8afe39",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/249f760cb168",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "d36dbb55ccb4bab7414b8ed13b1d9c7f8a4b25aaa4bd9f8876c80f2d657c28c1",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "b17bb849524a9addbf0eebc6576046d7e26e1f2dd1f900da5a3b88bcc006e277",
"EndpointID": "d36dbb55ccb4bab7414b8ed13b1d9c7f8a4b25aaa4bd9f8876c80f2d657c28c1",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
[root@kikistudy /]#
进入当前正在运行的容器
# 我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置
# 命令
docker exec -it 容器id bashShell
# 测试
[root@kikistudy /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
837341c266f2 centos "/bin/sh -c 'while t…" 37 minutes ago Up 37 minutes lucid_cori
[root@kikistudy /]# docker exec -it 837341c266f2 /bin/bash
[root@837341c266f2 /]# ls
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
[root@837341c266f2 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 08:38 ? 00:00:01 /bin/sh -c while true;do echo kikistudy;slee
root 2309 0 0 09:16 pts/0 00:00:00 /bin/bash
root 2342 1 0 09:17 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=
root 2343 2309 0 09:17 pts/0 00:00:00 ps -ef
[root@837341c266f2 /]#
# 方式二
docker attach 容器id
# 测试
[root@kikistudy /]# docker attach 837341c266f2
正在执行当前的代码...
# 强制删除容器
[root@kikistudy /]# docker rm -f $(docker ps -aq)
837341c266f2
eb156c5c5180
b4b359dd429f
73c7438b972d
7763628b8689
c3f535e2a6dd
# 区别
# docker exec # 进入容器后开启新的终端,可以在里边操作【常用】
# docker attach # 进入容器正在执行的终端,不会启动新的进程
从容器拷贝文件到主机上
docker cp
注意:只要容器存在,它的数据就在,跟他运行不运行没有关系
docker cp 容器id:容器内路径 目的地主机路径
# 查看当前主机目录下文件
[root@kikistudy testdocker]# ls
kikitest.java
[root@kikistudy testdocker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
38176c71c7f6 centos "/bin/bash" 2 minutes ago Up 2 minutes serene_blackburn
# 进入docker容器内部
[root@kikistudy testdocker]# docker attach 38176c71c7f6
[root@38176c71c7f6 /]# cd /home
[root@38176c71c7f6 home]# ls
# 在容器中新建一个文件
[root@38176c71c7f6 home]# touch test.java
[root@38176c71c7f6 home]# ls
test.java
[root@38176c71c7f6 home]# exit
exit
[root@kikistudy testdocker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@kikistudy testdocker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
38176c71c7f6 centos "/bin/bash" 4 minutes ago Exited (0) 16 seconds ago serene_blackburn
# 将这个文件拷贝出来到主机上
[root@kikistudy testdocker]# docker cp 38176c71c7f6:/home/test.java /home/testdocker
[root@kikistudy testdocker]# ls
kikitest.java test.java
# 拷贝是一个手动过程,未来我们可以使用 -v 数据卷的技术,可以实现容器和主机打通(自动同步)
演示从容器拷贝文件到主机
学习方式:将所有docker命令敲一遍,加深印象。
4.5小结
基本命令:
Docker的命令是十分多的,上面我们学习的那些都是最常用的容器和镜像的命令,之后我们还会学习很多命令!
4.6作业练习之Nginx
Docker安装Nginx
1、搜索nginx
[root@kikistudy /]# docker search nginx
2、下载镜像,拉取
[root@kikistudy /]# docker pull nginx
3、查看镜像并启动nginx
[root@kikistudy /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest ae2feff98a0c 12 days ago 133MB
centos latest 300e315adb2f 2 weeks ago 209MB
# -d 后台运行
# --name 给容器命名
# -p 宿主机端口:容器内部端口 暴露端口
[root@kikistudy /]# docker run -d --name nginx01 -p 3344:80 nginx
833baba73a5a35b72eab69fcd74e66704d01278c2212bae60c460ba8aae03256
[root@kikistudy /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
833baba73a5a nginx "/docker-entrypoint.…" 8 seconds ago Up 6 seconds 0.0.0.0:3344->80/tcp nginx01
4、本机自测
[root@kikistudy /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
833baba73a5a nginx "/docker-entrypoint.…" 8 seconds ago Up 6 seconds 0.0.0.0:3344->80/tcp nginx01
[root@kikistudy /]# curl localhost:3344
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
端口暴露的概念:
进入正在运行的容器nginx
[root@kikistudy /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
833baba73a5a nginx "/docker-entrypoint.…" 16 minutes ago Up 16 minutes 0.0.0.0:3344->80/tcp nginx01
[root@kikistudy /]# docker exec -it nginx01 /bin/bash
root@833baba73a5a:/#
查找nginx的配置文件
root@833baba73a5a:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
[root@kikistudy /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
833baba73a5a nginx "/docker-entrypoint.…" 16 minutes ago Up 16 minutes 0.0.0.0:3344->80/tcp nginx01
# 进入容器
[root@kikistudy /]# docker exec -it nginx01 /bin/bash
root@833baba73a5a:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@833baba73a5a:/# cd /etc/nginx
root@833baba73a5a:/etc/nginx# ls
conf.d koi-utf mime.types nginx.conf uwsgi_params
fastcgi_params koi-win modules scgi_params win-utf
root@833baba73a5a:/etc/nginx#
思考问题我们每次改动nginx配置文件,都需要进入容器内部?十分的麻烦,我们要是可以在容器外部提供一个映射路径,达到在容器外部修改文件,容器内部可以自动修改? -v 数据卷的技术
4.7作业练习之Tomcat
作业:使用docker来装Tomcat
# 官方的使用
docker run -it --rm tomcat:9.0
# 我们之前的启动都是后台,停止了容器之后,容器还是可以查到
# docker run -it --rm docker官方这种方式是用完即删,自动删除,下载完之后运行,停止即删除
# 先下载再去启动
docker pull tomcat:9.0
[root@kikistudy /]# docker pull tomcat:9.0
9.0: Pulling from library/tomcat
Digest: sha256:57dae7dfb9b62a413cde65334c8a18893795cac70afc3be589c8336d8244655d
Status: Image is up to date for tomcat:9.0
docker.io/library/tomcat:9.0
[root@kikistudy /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat 9.0 feba8d001e3f 9 days ago 649MB
nginx latest ae2feff98a0c 12 days ago 133MB
centos latest 300e315adb2f 2 weeks ago 209MB
[root@kikistudy /]#
[root@kikistudy /]# docker run -d -p 3355:8080 --name tomcat01 tomcat
Unable to find image 'tomcat:latest' locally
latest: Pulling from library/tomcat
Digest: sha256:57dae7dfb9b62a413cde65334c8a18893795cac70afc3be589c8336d8244655d
Status: Downloaded newer image for tomcat:latest
7226eba3168001a9f4d8ebc6aa553e9c7f4afed2b974582c15c04d0186ff971e
[root@kikistudy /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat 9.0 feba8d001e3f 9 days ago 649MB
tomcat latest feba8d001e3f 9 days ago 649MB
nginx latest ae2feff98a0c 12 days ago 133MB
centos latest 300e315adb2f 2 weeks ago 209MB
[root@kikistudy /]# docker run -d -p 3355:8080 --name tomcat01 tomcat
docker: Error response from daemon: Conflict. The container name "/tomcat01" is already in use by container "7226eba3168001a9f4d8ebc6aa553e9c7f4afed2b974582c15c04d0186ff971e". You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'.
[root@kikistudy /]#
外网访问tomcat,发现浏览器提示未找到!
出现以上现象,其实并不是tomcat没有安装成功,而是从阿里云镜像下载的tomcat它是一个阉割版的,webapps文件夹下没有任何内容
[root@kikistudy /]# docker exec -it tomcat01 /bin/bash # 进入容器
# 发现问题:1、linux命令少了 2、它没有webapps。 原因:阿里云镜像的原因,默认是最小的镜像,使所有不必要的都剔除掉。
# 保证最小的可运行环境,那么如何解决呢?将webapps.dist下的文件拷贝到webapps下
root@7226eba31680:/usr/local/tomcat# ls
BUILDING.txt NOTICE RUNNING.txt lib temp work
CONTRIBUTING.md README.md bin logs webapps
LICENSE RELEASE-NOTES conf native-jni-lib webapps.dist
root@7226eba31680:/usr/local/tomcat# ls -al
total 128
drwxr-xr-x 1 root root 30 Dec 18 08:57 .
drwxr-xr-x 1 root root 20 Dec 18 08:52 ..
-rw-r--r-- 1 root root 18982 Dec 3 11:48 BUILDING.txt
-rw-r--r-- 1 root root 5409 Dec 3 11:48 CONTRIBUTING.md
-rw-r--r-- 1 root root 57092 Dec 3 11:48 LICENSE
-rw-r--r-- 1 root root 2333 Dec 3 11:48 NOTICE
-rw-r--r-- 1 root root 3257 Dec 3 11:48 README.md
-rw-r--r-- 1 root root 6898 Dec 3 11:48 RELEASE-NOTES
-rw-r--r-- 1 root root 16507 Dec 3 11:48 RUNNING.txt
drwxr-xr-x 2 root root 4096 Dec 18 08:58 bin
drwxr-xr-x 1 root root 40 Dec 28 07:52 conf
drwxr-xr-x 2 root root 4096 Dec 18 08:57 lib
drwxrwxrwx 1 root root 177 Dec 28 07:52 logs
drwxr-xr-x 2 root root 134 Dec 18 08:57 native-jni-lib
drwxrwxrwx 2 root root 30 Dec 18 08:57 temp
drwxr-xr-x 2 root root 6 Dec 18 08:57 webapps
drwxr-xr-x 7 root root 81 Dec 3 11:45 webapps.dist
drwxrwxrwx 2 root root 6 Dec 3 11:43 work
root@7226eba31680:/usr/local/tomcat# cd webapps
root@7226eba31680:/usr/local/tomcat/webapps# ls
root@7226eba31680:/usr/local/tomcat/webapps#
解决webapps下没有文件的问题
root@7226eba31680:/usr/local/tomcat# cd webapps
root@7226eba31680:/usr/local/tomcat/webapps# ls
root@7226eba31680:/usr/local/tomcat/webapps# cd ../
root@7226eba31680:/usr/local/tomcat# ls
BUILDING.txt NOTICE RUNNING.txt lib temp work
CONTRIBUTING.md README.md bin logs webapps
LICENSE RELEASE-NOTES conf native-jni-lib webapps.dist
root@7226eba31680:/usr/local/tomcat# cd webapps.dist
root@7226eba31680:/usr/local/tomcat/webapps.dist# ls
ROOT docs examples host-manager manager
root@7226eba31680:/usr/local/tomcat/webapps.dist# cd ../
root@7226eba31680:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@7226eba31680:/usr/local/tomcat# cd webapps
root@7226eba31680:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
root@7226eba31680:/usr/local/tomcat/webapps#
思考问题:我们以后要部署项目,如果每次都要进入容器是不是十分麻烦?我们要是可以在容器外部提供一个映射路径,达到在容器外部修改文件,容器内部可以自动修改?比如webapps,我们在外部放置项目,就自动同步到内部就好了!
4.8作业练习之es+kibana
作业:部署es + kibana
# es 暴露的端口很多
# es 十分的耗内存
# es 的数据一般需要放置到安全目录!挂载
# --net somenetwork ? docker网络配置
# 官方
$ docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:tag
# 下载启动 elasticsearch
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# 启动了 linux就卡住了 dokcer status 查看 cpu的状态
# es 是十分耗内存的,1核2G!
# 停止整个docker,一般不建议
# 查看 docker stats
# 测试一下es是否成功了
# 赶紧关闭,增加内存的限制
本机访问es
[root@kikistudy /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fd0a099d0603 elasticsearch:7.6.2 "/usr/local/bin/dock…" 6 minutes ago Up 6 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp elasticsearch
[root@kikistudy /]# curl localhost:9200
{
"name" : "fd0a099d0603",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "ZMNjd41XTn6DxPW1DNO9XA",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
[root@kikistudy /]#
# 赶紧关闭,增加内存的限制,修改配置文件 -e 环境配置修改
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
指定es内存,启动
[root@kikistudy /]# docker run -d --name elasticsearch03 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
dd2a598a01b17d9521ec3f77357900a57fdb6facc7c8d110f39ae743e603186f
[root@kikistudy /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dd2a598a01b1 elasticsearch:7.6.2 "/usr/local/bin/dock…" 5 seconds ago Up 3 seconds 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp elasticsearch03
[root@kikistudy /]#
此时再看内存占用情况,可见占用明显变少了
[root@kikistudy /]# curl localhost:9200
{
"name" : "dd2a598a01b1",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "WfUmZb6jQSKPQ1ByNE4Kmg",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
[root@kikistudy /]#
作业:使用Kibana连接es,思考如何才能连接过去?
4.8可视化
- portainer
docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock --privileged=true portainer/portainer
- Rancher(CI/CD再用)
什么是portainer?
Docker的图形化界面工具!提供一个后台面板供我们操作!
docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock --privileged=true portainer/portainer
测试:
[root@kikistudy /]# docker run -d -p 8088:9000 \--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
Unable to find image 'portainer/portainer:latest' locally
latest: Pulling from portainer/portainer
d1e017099d17: Pull complete
717377b83d5c: Pull complete
Digest: sha256:f8c2b0a9ca640edf508a8a0830cf1963a1e0d2fd9936a64104b3f658e120b868
Status: Downloaded newer image for portainer/portainer:latest
02b8c549f95346899cb4756611cf1e24f08ae8c612816e7fbe713de58ebca84c
访问测试地址:http://39.102.88.251:8088/
第一次访问可能比较久
设置登录密码后
进入之后的面板
五、Docker镜像讲解
5.1镜像是什么?
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
也就是所有应用直接打包docker镜像,就可以直接跑起来!
如何得到镜像:
- 从远程仓库下载
- 朋友拷贝给你
- 自己制作一个镜像DockerFile
5.2Docker镜像加载原理
1.UnionFS(联合文件系统)
我们测试下载镜像的时候看到的一层层的就是这个!
UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite serveral directions into a single virtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
2.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都是好几个G,为什么Docker这里才200M?
对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了,由此可见对于不同的linux发行版,bootfs基本上是一致的,rootfs会有差别,因此不同的发行版可以公用rootfs。
虚拟机是分钟级别的,容器是秒级的!
5.3分层理解
1.分层的镜像
我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的下载在下载!
[root@kikistudy /]# docker image inspect redis:latest
[
{
"Id": "sha256:ef47f3b6dc11e8f17fb39a6e46ecaf4efd47b3d374e92aeb9f2606896b751251",
"RepoTags": [
"redis:latest"
],
"RepoDigests": [
"redis@sha256:0f724af268d0d3f5fb1d6b33fc22127ba5cbca2d58523b286ed3122db0dc5381"
],
"Parent": "",
"Comment": "",
"Created": "2020-12-11T16:25:00.990749243Z",
"Container": "6da61e8ec8c774f324d488c6047bd913d6f379855b7abcb08be9f41acee6e3ab",
"ContainerConfig": {
"Hostname": "6da61e8ec8c7",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"6379/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",
"REDIS_VERSION=6.0.9",
"REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.0.9.tar.gz",
"REDIS_DOWNLOAD_SHA=dc2bdcf81c620e9f09cfd12e85d3bc631c897b2db7a55218fd8a65eaa37f86dd"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"redis-server\"]"
],
"Image": "sha256:d9311f71736ce563d01280a6cc23530a3f838f6f6c4c245b2b99919594b67b7b",
"Volumes": {
"/data": {}
},
"WorkingDir": "/data",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {}
},
"DockerVersion": "19.03.12",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"6379/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",
"REDIS_VERSION=6.0.9",
"REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.0.9.tar.gz",
"REDIS_DOWNLOAD_SHA=dc2bdcf81c620e9f09cfd12e85d3bc631c897b2db7a55218fd8a65eaa37f86dd"
],
"Cmd": [
"redis-server"
],
"Image": "sha256:d9311f71736ce563d01280a6cc23530a3f838f6f6c4c245b2b99919594b67b7b",
"Volumes": {
"/data": {}
},
"WorkingDir": "/data",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 104252176,
"VirtualSize": 104252176,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/1afb8f11b21df1c47935b00d87478f845f3ff808cca64e13a085f2c480ce8fc0/diff:/var/lib/docker/overlay2/7d10a2f6a2d8aa2eaedf676fb5ed6d09c85f76df2340360ae5f8f739bad9d347/diff:/var/lib/docker/overlay2/4f6aea52aa2b8f37e4e990dbd0b5cd3b81902d67a462c5955dcf2d06e12eaf06/diff:/var/lib/docker/overlay2/5afea4856c9912fe2deca56bdb1ef695b60b89ec5bdebaf2e2529b750198227c/diff:/var/lib/docker/overlay2/36c2a590814dfb5b1c5d48f56f8c890a6bc38c081b4c5ebb4e082041183088cd/diff",
"MergedDir": "/var/lib/docker/overlay2/f441ee5e64252bf4b63b9317cd795a30426067f9cf33e576c90124a4f15c340e/merged",
"UpperDir": "/var/lib/docker/overlay2/f441ee5e64252bf4b63b9317cd795a30426067f9cf33e576c90124a4f15c340e/diff",
"WorkDir": "/var/lib/docker/overlay2/f441ee5e64252bf4b63b9317cd795a30426067f9cf33e576c90124a4f15c340e/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:87c8a1d8f54f3aa4e05569e8919397b65056aa71cdf48b7f061432c98475eee9",
"sha256:25075874ce886bd3adb3b75298622e6297c3f893e169f18703019e4abc8f13f0",
"sha256:caafc8119413c94f1e4b888128e2f337505fb57e217931a9b3a2cd7968340a9e",
"sha256:e5d940a579ec4a80b6ec8571cb0fecf640dba14ccfd6de352977fd379a254053",
"sha256:2a1c28c532d20c3b8af8634d72a4d276a67ce5acb6d186ac937c13bd6493c972",
"sha256:1540b8226044ed5ce19cc0fec7fbfb36a00bb15f4e882d6affbd147a48249574"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
[root@kikistudy /]#
理解:
所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子:
例如基于Ubuntu Linux 16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层之上创建创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三层镜像。
该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图也举了一些简单的例子,每个镜像层包含3个文件,而镜像包含来自两个镜像层的6个文件。
上图的镜像层跟之前图中的略有区别,主要目的是便于展示文件。
下图展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。
这种情况下,上层镜像中的文件覆盖了底层镜像中的文件,这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
Docker通过存储引擎(新版本采用快照机制)的方式实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独特的性能特点。
Docker在Windows上仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层的CoW。
下图展示了与系统显示相同的三层镜像,所有镜像层堆叠并合并,对外界提供统一的视图。
特点:
Docker镜像都是只读的,当容器启动时,一个新的可写层加载到镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层!
如何提交一个自己的镜像
5.4commit镜像
docker commit 提交容器成为一个新的副本
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
实战测试tomcat
[root@kikistudy /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
02b8c549f953 portainer/portainer "/portainer" 24 hours ago Up 24 hours 0.0.0.0:8088->9000/tcp sweet_euler
dd2a598a01b1 elasticsearch:7.6.2 "/usr/local/bin/dock…" 2 days ago Up 2 days 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp elasticsearch03
# 1.自己启动一个默认的tomcat
[root@kikistudy /]# docker run -it -p 8080:8080 tomcat #启动tocat
# 进入容器
[root@kikistudy /]# docker exec -it 68fee2aa72b9 /bin/bash
root@68fee2aa72b9:/usr/local/tomcat# cp -r webapps.dist/* webapps #拷贝文件
# 2.发现这个默认的tomcat是没有webapps应用,镜像的原因,官方的默认webapps下面是没有文件的!
#3. 我们可以自己拷贝进去了基本的文件
#4. 将我们操作过的容器通过commit提交为一个镜像,我们以后就使用修改过的镜像就可以,这就是我们自己的一个修改过的镜像
# 提交镜像
[root@kikistudy /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
68fee2aa72b9 tomcat "catalina.sh run" 17 minutes ago Up 17 minutes 0.0.0.0:8080->8080/tcp lucid_dijkstra
[root@kikistudy /]# docker commit -a="kikistudy" -m="add webapps app" 68fee2aa72b9 tomcat02:1.0
sha256:611ae7d39b71cb0c3c24a79f8f5ac55393e3e4e84541f27c23859870b4c8c158
[root@kikistudy /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat02 1.0 611ae7d39b71 11 seconds ago 654MB
tomcat 9.0 feba8d001e3f 12 days ago 649MB
tomcat latest feba8d001e3f 12 days ago 649MB
nginx latest ae2feff98a0c 2 weeks ago 133MB
redis latest ef47f3b6dc11 2 weeks ago 104MB
centos latest 300e315adb2f 3 weeks ago 209MB
portainer/portainer latest 62771b0b9b09 5 months ago 79.1MB
elasticsearch 7.6.2 f29a1ee41030 9 months ago 791MB
[root@kikistudy /]#
学习方式说明:理解概念,但是一定要去实践,最后理论和实践相结合,一次搞定这个知识。
如果你想要保存当前容器的状态,就可以通过commit来提交,获得一个镜像。就好比我们以前学习虚拟机的时候,快照【存档】
到了这里,才算是Docker入门!