本文主要是介绍熬夜干Docker,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 1. docker概述
- 2. docker安装
- 2.1 docker基本组成
- 2.2 docker安装
- 2.3 docker卸载
- 2.3 阿里云镜像加速
- 3. docker命令
- 3.1 帮助命令
- 3.2 镜像命令
- 3.3 容器命令
- 3.4 其他常用命令
- 3.5 小总结
- 3.6 小练习
- 3.6.1 docker部署nignx
- 3.6.2 docker部署tomcat
- 3.6.3 docker部署es+kibana
- 3.7 docker 可视化
- 4. docker镜像
- 4.1 镜像原理之联合文件系统
- 4.2 镜像原理之分层理解
- 4.3 commit镜像
- 4.4 容器数据卷使用
- 4.5 实战演练
- 4.5.1 MySQL同步数据
- 4.6 匿名挂载和具名挂载
- 5. 容器数据卷
- 6. dockerFile
- 7. docker网络原理
- 8. IDEA整合Docker
- 9. Docker Compose
- 10. DI\CD Jenkins
1. docker概述
官方网站:https//:www.docker.com/
文档地址:https://docs.docker.com/
仓库地址:https://hub.docker.com/
每一项技术的出现,都是因为之前的技术出现了问题。
遇到问题:
一款产品:开发-上线,两套环境(测试、生产),应用环境、应用配置,现在出现了如下的问题:
- 版本更新,导致服务不可用,环境配置十分的麻烦,每一个机器都要部署环境(集群Redis、ES、Hadoop…),费时费力。
- 服务器配置一个应用的环境(Redis、Mysql、jdk、es、hadoop),配置麻烦。
解决问题:
- 使用了 Docker之后,我们部署应用就和搭积木一样 项目打包为一个镜像,扩展服务器A,服务器B…更简单的系统运维 在容器化之后,我们的开发,测试环境都是高度一致的, 更高效的资源利用(docker是go语言开发的开源项目)
虚拟机技术对比docker容器技术:
虚拟机技术:
- 传统虚拟机,虚拟出硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件,占用资源十分多,启动很慢。
docker容器技术:
-
容器化技术不是模拟一个完整的操作系统,容器内的应用直接运行在宿主机的内核,容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了,每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响。
-
Docker是内核级别的虚拟化,可以在一个物理机上可以运行很多的容器实例!服务器的性能可以被压榨到极致。
2. docker安装
2.1 docker基本组成
docker的基本组成:
-
镜像(image): docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像-->run-->容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。
-
容器(container): docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的。
-
仓库(repository): 仓库就是存放镜像的地方,仓库分为公有仓库和私有仓库(类似于github)。默认仓库Docker Hub是国外的,可以修改成国内的。
docker基本操作流程:
- docker启动之后,有客户端和服务端,客户端使用docker命令进行访问。
- docker run 运行一个容器,真正的运行是在docker的服务上去运行,是一个docker的守护进程。
- docker守护进程要运行,要通过镜像来运行,运行镜像来生成对应的容器。
- 这些镜像可能来自我们的远程仓库。
2.2 docker安装
前提条件:uname -r
查看Linux内核版本,必须是3.10以上
(1)移除旧的镜像
yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine
(2) 安装需要的包
yum install -y yum-utils
(3) 设置docker镜像仓库( 推荐使用阿里云 )
yum-config-manager \ --add-repo \http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
更新软件包索引
yum makecache fast
(4) 安装docker相关的内容 – docker-ce 社区版 docker-ee 企业版
yum install docker-ce docker-ce-cli containerd.io -y
(5) 启动docker
systemctl start docker
systemctl enable docker
systemctl status docker
(6) 使用docker version 看是否安装成功
(7)通过运行hello-world镜像验证 Docker 是否正确安装。
(8)查看下载的hello-world镜像
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 6 months ago 13.3kB
2.3 docker卸载
1. 卸载依赖yum remove docker-ce docker-ce-cli containerd.io2. 删除资源rm -rf /var/lib/docder (docker的默认工作路径)rm -rf /var/lib/containerd
2.3 阿里云镜像加速
(1) 登录阿里云找到容器服务
(2)找到镜像加速地址
(3)配置使用:
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{"registry-mirrors": ["https://yws0gs4h.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
2.4 docker执行原理
docker run hello-world 执行的流程图
docker底层工作原理:
docker是一个Client- Server结构的系统,docker的守护进程运行在主机上。通过客户端访问。
dockerServer接收到docker-client的指令,就会执行这个命令。
3. docker命令
3.1 帮助命令
docker version # 显示docker
docker info # 显示docker的系统信息
docker 命令 --help # 帮助命令
帮助文档的地址:https://docs.docker.com/engine/reference/commandline/cp/
3.2 镜像命令
docker images
查看所有本地的主机上的镜像
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 6 months ago 13.3kB# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的id
GREATED 镜像的创建时间
SIZE 镜像的大小# 可选项-a,--all # 列出所有镜像-q,--quiet # 只显示镜像的id
docker search
搜索镜像(在镜像库中搜索镜像)
[root@docker ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11404 [OK]
mariadb MariaDB Server is a high performing open sou… 4329 [OK] ## 可选项,通过搜索来过滤
--filter=STARS=300 # 搜索出来的镜像就是STARS大于3000的[root@docker ~]# docker search mysql --filter=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11404 [OK]
mariadb MariaDB Server is a high performing open sou… 4329 [OK] [root@docker ~]# docker search mysql --filter=STARS=6000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11404 [OK]
docker pull
下载镜像
# 下载镜像 docker pull 镜像名[:tag]
[root@docker ~]# docker pull mysql
Using default tag: latest #如果不写tag,默认就是latest
latest: Pulling from library/mysql
a330b6cecb98: Pull complete # 分层下载,docker image的核心,联合文件系统
9c8f656c32b8: Pull complete
88e473c3f553: Pull complete
062463ea5d2f: Pull complete
daf7e3bdf4b6: Pull complete
1839c0b7aac9: Pull complete
cf0a0cfee6d0: Pull complete
1b42041bb11e: Pull complete
10459d86c7e6: Pull complete
b7199599d5f9: Pull complete
1d6f51e17d45: Pull complete
50e0789bacad: Pull complete
Digest: sha256:99e0989e7e3797cfbdb8d51a19d32c8d286dd8862794d01a547651a896bcf00c
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实地址# 等价于它
docker pull mysql
docker pull docker.io/library/mysql:latest# 指定版本下载
[root@docker ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
a330b6cecb98: Already exists
9c8f656c32b8: Already exists
88e473c3f553: Already exists
062463ea5d2f: Already exists
daf7e3bdf4b6: Already exists
1839c0b7aac9: Already exists
cf0a0cfee6d0: Already exists
fae7a809788c: Pull complete
dae5a82a61f0: Pull complete
7063da9569eb: Pull complete
51a9a9b4ef36: Pull complete
Digest: sha256:d9b934cdf6826629f8d02ea01f28b2c4ddb1ae27c32664b14867324b3e5e1291
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
docker rmi
删除镜像
[root@docker ~]# docker rmi -f 镜像id #删除指定的容器
[root@docker ~]# docker rmi -f 容器id 容器id # 删除多个容器
[root@docker ~]# docker rmi -f $(docker images -aq) # 删除全部的容器
3.3 容器命令
说明:我们有个镜像才可以创建镜像,Linux,下载一个centos来测试学习
docker pull
拉取镜像
docker pull centos
docker run
新建容器并启动
docker run [可选参数] image
# 参数说明
--name="Name" # 容器名字 tomcat01 tomcat02,用来区分容器
-d # 后台方式运行
-it # 使用交互方式运行,进入容器查看内容
-p # 指定容器的端口 -p 8080:8080 -p ip:主机端口:容器端口-p 主机端口:容器端口(常用)-p 容器端口
-P # 随机指定端口# 测试,启动并进入容器
[root@docker ~]# docker run -it centos /bin/bash
[root@4c218a662979 /]# ls # 查看容器内的centos,基础版本,很多命令都是不完善的!
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr# 从主机中退回主机
[root@4c218a662979 /]# exit
exit
[root@docker ~]# ls
anaconda-ks.cfg
docker ps
列出所有的运行的容器
# docker ps 命令# 列出当前正在运行的容器
-a # 列出当前正在运行的容器+带出历史运行过的容器
-n=? # 显示最近创建的容器
-q # 只显示容器的编号[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4c218a662979 centos "/bin/bash" 9 minutes ago Exited (0) 7 minutes ago gifted_chatterjee
35d6cbb3d074 hello-world "/hello" 11 hours ago Exited (0) 11 hours ago elated_gates
exit
退出容器
exit # 直接容器停止并推出
ctrl + P + Q # 容器不停止推出
docker rm
删除容器
docker rm 容器id # 删除指定的容器,不能删除正在运行的容器,如果强制删除rm -rf
docker rm -f $(docker ps -aq) # 删除所有的容器
docker ps -a -q | xargs docker rm # 删除所有的容器
docker start stop
启动和停止容器的操作
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止当前的容器
3.4 其他常用命令
后台启动容器
# 命令 docker run -d 镜像名
[root@docker ~]# docker run -d centos
# docker ps 发现centos停止了
# 常见的坑:docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
# nginxm, 容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了。
查看日志
docker logs -f -t --tail 容器,没有日志
# 自己编写一段shell脚本
[root@docker ~]# docker run -d centos /bin/sh -c "while true; do echo dongkun ;sleep 1;done" [root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e5cd26cb3c77 centos "/bin/sh -c 'while t…" 14 seconds ago Up 13 seconds confident_nobel# 显示日志
-tf # 显示日志
--tail number # 要显示日志条数
[root@docker ~]# docker logs -tf --tail 10 e5cd26cb3c77
docker top
查看容器中进程信息ps
# 命令docker top 容器id
[root@docker ~]# docker top e5cd26cb3c77
docker inspect
查看镜像的元数据
# 命令
docker inspect 容器id# 测试
[root@docker ~]# docker inspect e5cd26cb3c77
[{"Id": "e5cd26cb3c77f556dd57e2addb1ac859e5d14be6aece1349cad9d89bed817a31","Created": "2021-09-12T15:32:14.034129802Z","Path": "/bin/sh","Args": ["-c","while true;do echo dongkun;sleep 1;done"],"State": {
docker exec
进入当前正在运行的容器
# 我们通常容器都是使用后台方式进行的,需要进入容器,修改一些配置
# 方式一
docker exec -it 容器id bash
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e5cd26cb3c77 centos "/bin/sh -c 'while t…" 15 minutes ago Up 10 seconds confident_nobel[root@docker ~]# docker exec -it e5cd26cb3c77 /bin/bash
[root@e5cd26cb3c77 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 15:47 ? 00:00:00 /bin/sh -c while true;do echo dongkun;sleep 1;done
root 151 0 0 15:49 pts/0 00:00:00 /bin/bash
root 291 1 0 15:52 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
root 292 151 0 15:52 pts/0 00:00:00 ps -ef# 方式二
docker attach 容器id
# 测试
[root@docker ~]# docker attach e5cd26cb3c77
dongkun
dongkun
正在执行当前的代码# docker exec # 进入容器后开启一个新的终端,可以在在里面操作(常用)
# docker exec # 进入容器正在执行的终端,不会启动新的进程
docker cp
从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的主机路径
# 查看当前主机目录下
[root@docker ~]# ls /home/
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
40875467988c centos "/bin/bash" 2 hours ago Up About a minute practical_robinson# 进入docker容器内部
[root@docker ~]# docker attach 40875467988c
[root@40875467988c /]# cd /home
[root@40875467988c home]# ls# 在容器内容新建一个文件
[root@40875467988c home]# touch hello.java
[root@40875467988c home]# ls
hello.java# 这里docker容器是启动的还是停止的都不影响,因为只要里面的数据
# 将文件拷贝出来到主机上
[root@docker ~]# docker cp 40875467988c:/home/hello.java /home
[root@docker ~]# ls /home/
hello.java
# 拷贝是一个手动过程,我们可以使用 -v 数据卷技术,可以实现同步的功能,类似于挂载
3.5 小总结
attach Attach to a running container # 当前shell下,attach 连接指定运行镜像
build build an image from a Dockerfile # 通过dockerfile 定制镜像
commit Create a new image from a container changes # 提交当前容器为新的镜像
cp Copy files/folders from the containers filesystem to the host path # 从容器中拷贝指定文件或者目录到宿主机中
create Create a new container # 创建一个新的容器,同run,但不启动容器
diff Inspect changes on a container's filesystem # 查看docker容器变化
events Get real time events from the server # 从docker服务器获取容器实时事件
exec Run a command in an existingcontainer # 在已存在的容器上运行命令
export Stream the containers of a container as a tar archive # 导出容器的内容流作为一个tar归档文件【对一个import】
history Show the history of an image # 展示一个镜像形成历史
images List images # 列出系统当前镜像
import Create a new filesystem image from the contents of a tar tarball # 从tar 包中的内容创建一个新的文件系统镜像[对应export]
info Display system-wide information # 显示系统相关信息
inspect Return low-level information on a container # 查看容器信息
kill kill a running container # kill 指定docker容器
load load an image from a tar archive # 从一个tar包中加载一个镜像【对应 save】
login Register or login to the docker registry server # 注册或者登录一个docker源服务器
logout Log out from a Docker registry server # 从当前 docker registry 退出
logs Fetch the logs of a container # 输出当前容器日志信息
port Lookup the public-facing port which is NAT-ed to PRIVATE_PORT # 查看映射端口对应的容器内部源端口
pause Pause all processes within a container # 暂停容器
ps List containers # 列出容器列表
pull Push an image or a repository to the docker registory server # 从docker镜像源服务器拉取指定镜像或者库镜像
push Push an image or a repository to the docker registry server # 推送指定镜像或者库镜像至docker源服务器
restart Restart a running container # 重启运行的容器
rm remove one or more containers # 移除一个或者多个容器
rmi remove one or more images # 一处一个或多个镜像【无容器使用,该镜像才可删除,否则需删除相关容器才可以继续或 -f 强制删除】
run Run a command in a new container # 创建一个新的容器并运行一个命令
save Save an image to a tar archive # 保存一个镜像为一个tar包【对应load】
search Search for an image on the Docer Hub # 在docker hub中搜索镜像
start Start a stopped containers # 启动容器
stop Stop a running containers # 停止容器
tag Tag an image into a repository # 给源中镜像打标签
top Lookup the running into a repository # 查看容器中运行的进程信息
unpause Unpause a paused container # 取消暂停容器
version Show the docker version information # 查看docker版本号
wait Block until a container stops,then print its exit code # 截取容器停止时的退出状态值
3.6 小练习
3.6.1 docker部署nignx
重点: 暴露端口的必要性
# 1. 搜索镜像 search 可以去docker hub上去搜索,可以看到帮助文档# 2. 下载镜像 pull,并且运行容器
# 下载镜像,可以到docker hub上查看可以下载的版本
[root@docker ~]# docker pull nginx
Using default tag: latest# 查看你存在的镜像
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest ad4c705f24d3 3 days ago 133MB
centos latest 300e315adb2f 9 months ago 209MB# 运行镜像,并启动容器,如果本地不存在镜像,则会到远程仓库拉取
# -d 后台运行
# --name 给容器命名
# -p 宿主机端口:容器内部端口
[root@docker ~]# docker run -d --name nginx01 -p 3344:80 nginx
30c15589279e884c8ffdb76a9b6958dae98b7ce033853ad77ea86aabcefae162# 查看正在运行的容器
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
30c15589279e nginx "/docker-entrypoint.…" 3 minutes ago Up 3 minutes 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01# 进入容器内
[root@docker ~]# docker exec -it nginx01 /bin/bash
root@30c15589279e:/# ls
bin docker-entrypoint.d home media proc sbin tmp
boot docker-entrypoint.sh lib mnt root srv usr
dev etc lib64 opt run sys var# 3. 进行测试(也可以在浏览器中进行访问)
[root@docker ~]# curl localhost:3344
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
暴露端口的原理:
3.6.2 docker部署tomcat
重点: 官方测试,以及进入容器查看的重要性(从而引出数据卷)
# 官方的使用 (容器运行完之后删除,但是镜像没有删除)
docker run -it --rm tomcat:9.0
# 之前的启动都是后台,停止容器之后,容器还是可以查到 docker run -it --rm,一般用来测试,用完就删除# 1. 下载在启动
[root@docker ~]# docker pull tomcat # 2. 启动运行
[root@docker ~]# docker run -d -p 3355:8080 --name tomcat01 tomcat# 3. 测试访问(这是还不能访问,因为容器内/usr/local/tomcat/webapps里没有项目)
# 解决: 进入容器内把webapps.dist下的文件拷贝到webapps中
[root@docker ~]# curl localhost:3355# 4. 进入容器(执行下面的操作后,可以成功的访问tomcat)
[root@docker ~]# docker exec -it tomcat01 /bin/bash
root@797ff351e2b6:/usr/local/tomcat# cp -r webapps.dist/* webapps# 发现问题:默认是最小的镜像,所有不必要的都剔除掉,保证最小运行的环境
小提示:
如果这里使用数据卷的话,修改文件就不用在进入容器中,直接在宿主机上操作即可。
3.6.3 docker部署es+kibana
重点: 如何看容器当前的存活状态,如何进行修改
# es暴露的端口很多
# es 十分的耗内存
# es 的数据一般需要放置到安全目录!挂载
# --net somenetwork 网络配置
(1) 启动 elasticsearchdocker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2(2) 使用docker stats 查看es内存使用情况
(3) 因为es消耗内存非常大1.xG,增加内存的限制,修改配置文件 -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(4) 使用 docker stats 进行查看程序占用内存的大小(内存占用空间明显变小)
(5)测试es是否正常运行
[root@docker ~]# curl localhost:9200
{"name" : "3d340731321f","cluster_name" : "docker-cluster","cluster_uuid" : "YqQMzTw3Qy-bZmVzymrQ3A","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"
}
3.7 docker 可视化
(1) portainer(docker图形化揭秘那管理工具,提供一个后台面板供我们操作)docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer(2) Rancher(CI/CD用)
进行测试访问:http://10.0.0.100:8088
4. docker镜像
镜像: 镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包含代码、运行时、库、环境变量和配置文件。
所有的应用,直接打包docker镜像,就可以直接跑起来!
如何得到镜像:
- 从远程仓库下载
- 朋友拷贝给你
- 自己制作一个镜像DockerFile
4.1 镜像原理之联合文件系统
docker pull 下载镜像的时候,下面进行分层下载,这个就是使用了联合文件系统
UnionFS(联合文件系统)
UnionFS(联合文件系统): Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同的目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行集成,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性: 一次同时加载多个文件系统,但从外面看来,只能看到一个文件系统,联合加载会把各层的文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
bootfs(boot file system)主要包含bootloader和kernel,bootloader主要引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载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会有差别,因此不同的发行版可以共用bootfs。
虚拟机时分钟级别,容器是秒级!
4.2 镜像原理之分层理解
分层的镜像
我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载!
思考: 为什么Docker镜像要采用这种分层的结构那?
最大的好处,我觉得莫过于是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的镜像服务了,而且镜像的每一层都可以被共享。
查看镜像分层的方式可以通过docker image inspect命令!
[root@docker ~]# docker image inspect redis:latest"RootFS": {"Type": "layers","Layers": ["sha256:d000633a56813933cb0ac5ee3246cf7a4c0205db6290018a169d7cb096581046","sha256:bdad86443e47c5665683ac41c1f24f28479d830d7e3cc47d0a337ee5166c7714","sha256:6a7992ac480029d82b7dbb757d16fe5d023aa283ed32b52267cd1fe9e6b73c49","sha256:be43d2475cf809c0f2ec31950e849d0f888f3121970fd99196a11a903f8c3820","sha256:be5818ef2907adfe19be14bf66647b5fb5a2029143f9297f8ce1ff1fd1d35753","sha256:c54e0c16ea22fa873c12f6a7f3fb4e021bb58d67c292156a6ce6e08637458b7c"]},"Metadata": {"LastTagTime": "0001-01-01T00:00:00Z"}
理解:
所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于Ubuntu Linux 16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就是创建第三个镜像层。
该镜像当前已经包含3个镜像曾,如下图所示(这只是一个用于演示的很简单的例子)。
在添加额外的镜像层的同时,镜像始终保持是当前镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了两个镜像层的6个文件。
上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux上可用的存储引擎有AUFS、Overlay、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker在Windows上仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和Cow。
下图展示了与系统相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。
特点:
- Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!
- 这一层就是我们通常说的容器层,容器之下的都叫镜像层!
4.3 commit镜像
docker commit 提交容器成为一个新的副本# 命令和git原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
实战测试
# 1. 启动一个默认的tomcat
[root@docker ~]# docker run it -p 8080:8080 tomcat# 2. 发现这个默认的tomcat是没有webapps应用的,镜像的原因,官方的镜像默认webapps下面是没有文件的!
[root@docker ~]# docker exec -it 6044d5b039ec /bin/bashroot@6044d5b039ec:/usr/local/tomcat# ls
BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist
CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work# 3. 自己拷贝进去基本的文件
root@6044d5b039ec:/usr/local/tomcat# cp -r webapps.dist/* webapps/
root@6044d5b039ec:/usr/local/tomcat# exit
浏览器进行范文:
http://10.0.0.100:8080# 4. 将我们操作过的容器通过commit提交为一个镜像!我们以后就使用我们修改过的镜像即可,这就是我们自己的一个修改的镜像
docker commit -a="dongkun" -m="add webapps app" 6044d5b039ec tomcat02:1.0如果你想要保存当前容器的状态,就可以通过commit来提交,获得一个镜像,就好比VM的快照。
学习方法:理解概念,但是一定要实践,最后实践和理论一次搞定这个只
4.4 容器数据卷使用
(1)容器数据卷介绍
- docker的理念:将应用和环境打包成一个镜像!
- 如果数据都在容器中,那么我们容器删除,数据就会丢失,那么我们容器删除,数据就会丢失!
需求:数据可以持久化。 MySQL,容器删了,删库跑路!(非常危险)。 需求:MySQL数据可以存储在本地 - 容器之间可以有一个数据共享的技术,Docker容器中产生的数据,同步到本地!这就是数据卷技术! 目录的挂载,将我们容器内的目录,挂载到宿主机上面去。
总结: 容器的持久化和同步操作!容器间也是可以数据共享的!
(2)使用数据卷
# 方式一:直接使用命令来挂载 -v
docker run -it 主机目录:容器内目录# 测试
[root@docker home]# docker run -it -v /home/test:/home centos /bin/bash# 启动起来时候我们可以通过 docker inspect 容器id
[root@docker home]# docker inspect ab99d62ae662"Mounts": [{"Type": "bind","Source": "/home/test", # 宿主机的目录"Destination": "/home", # 容器内的目录"Mode": "","RW": true,"Propagation": "rprivate"}],
(3)测试文件的同步
容器创建文件,宿主机同步了容器的文件
(4)继续测试文件的同步
Exit退出容器后,然后容器就停止了,然后在/home/test/hehe.txt文件中输入内容,然后在启动centos容器,看一下容器内/home/hehe.txt的内容是否和宿主机的一致。结果是一致的。
优点: 我们以后修改只需要在本地修改即可,容器内会自动同步。
总结: 1. 停止容器 2. 宿主机上修改文件 3. 启动容器 4.容器内的数据依旧是同步的
小提示: docker attach ab99d62ae662
该命令是进入正在启动的容器内
4.5 实战演练
4.5.1 MySQL同步数据
(1)安装mysql
# 获取镜像
[root@docker home]# docker pull mysql:5.7# 运行容器,需要做数据挂载!# 安装启动mysql,需要配置密码的,这是要注意点
# 官方测试:$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag# 启动容器
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
--name 容器名字
[root@docker home]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
(2)sqlyog进行测试
mysql启动成功之后,我们在本地使用sqlyog来测试一下。
sqlyog 连接到服务器的3310 — 3310和容器内的3306映射,这个时候我们就可以连接上了!
在本地测试创建一个数据库,查看一下我们映射的路径是否ok!
(3) 测试删除容器数据卷是否保留
假设我们将容器删除
发现,我们挂载到本地的数据卷依旧没有丢失,这就是实现了容器数据持久化功能!
小提示: 在生成容器的时候,也挂载了配置文件,但是宿主机中的路径没有配置文件,是因为容器内没有生成那个配置文件。
4.6 匿名挂载和具名挂载
(1)匿名挂载
# 下载镜像,启动容器, -v匿名挂载
[root@docker ~]# docker run -d -p --name nginx01 -v /etc/nginx nginx# 查看所有volume的情况
[root@docker ~]# docker volume ls
DRIVER VOLUME NAME
local 8e0b46f72f554c25c0b6841f6ae8da9f9d4c9b0f2adb941605733c61459ca6a8
这里发现,这种就是匿名挂载,我们在-v只写了容器的路径,没有写容器外的路径!
(2)具名挂载
# 启动容器,-v 具名挂载
[root@docker ~]# docker run -d -p --name nginx02 -v juming-nginx:/etc/nginx nginx
c09388afd8850316504d7f107cc78b5377218ea80e63261109c2a53834b11dc6# 查看所有volume的情况
[root@docker ~]# docker volume ls
DRIVER VOLUME NAME
local juming-nginx# 通过-v 卷名:容器内路径
# 查看一下这个卷
(3)查看卷名的详细信息
所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxx/_data
我们通过具名挂载可以方便的找到我们的一个卷,大多是使用的具名挂载
(4) 判断匿名挂载还是具名挂载
# 如何确定是具名挂载还是匿名挂载,还是指定路径挂载!
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载
小拓展:
# 通过-v 容器内路径:ro rw 改变读写全新啊
ro readonly # 只读
rw readwrite # 只读可写# 一旦这个设置了容器权限,容器对我们挂载出来的内容就有限定了!
docker run -d -p --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -p --name nginx02 -v juming-nginx:/etc/nginx:rw nginx# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作!
5. 容器数据卷
6. dockerFile
7. docker网络原理
8. IDEA整合Docker
9. Docker Compose
10. DI\CD Jenkins
即使再小的帆也能远航
这篇关于熬夜干Docker的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!