3 Docker的常用命令
3.1 帮助命令
docker version #显示Docker的版本信息
docker info #显示Docker的系统信息,包括镜像和容器的数量
docker [ command ] --help #万能命令
帮助文档的地址:https://docs.docker.com/engine/reference/commandline/docker/
3.2 镜像命令
3.2.1 docker images
查看所有本地的本机上的镜像
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 11 months ago 13.3kB
#解释
REPOSITORY 镜像的仓库源
TAG 镜像的表情
IMAGE ID 镜像的ID号
CREATED 镜像的创建时间
SIZE 镜像的大小
名称,速记 | 默认 | 描述 |
---|---|---|
–all,-a | 显示所有图像(默认隐藏中间图像) | |
–digests | 显示摘要 | |
–filter,-f | 基于所提供条件的滤波器输出 | |
–format | 使用 Go 模板打印漂亮的图像 | |
–no-trunc | 不截断输出 | |
–quiet,-q | 仅显示图像 ID |
3.2.2 docker search
搜索镜像
$ docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 13053 [OK]
mariadb MariaDB Server is a high performing open sou… 4995 [OK]
#可选项,通过收藏进行过滤
--filte=STARS=3000 #搜索出来的镜像就是 STARS 大于3000的镜像
$ docker search --filter=STARS=3000 mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 13053 [OK]
mariadb MariaDB Server is a high performing open sou… 4995 [OK]
3.2.3 docker pull
下载镜像
#下载镜像 docker pull 镜像名[:tag]
$ docker pull mysql
Using default tag: latest #如果不写Tag,默认就是 latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete #分层下载,docker image的核心,联合文件系统
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
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 #真实的地址
$ docker pull mysql
#等价于
$ docker pull docker.io/library/mysql:latest
#指定镜像版本下载
$ docker pull mysql:5.7
5.7: 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.7
docker.io/library/mysql:5.7
#查看镜像
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 c20987f18b13 8 months ago 448MB
mysql latest 3218b38490ce 8 months ago 516MB
hello-world latest feb5d9fea6a5 11 months ago 13.3kB
3.2.4 docker rmi
删除镜像
#删除指定的镜像
docker rmi <Image_ID>
#删除多个镜像
docker rmi <Image_ID> <Image_ID> <Image_ID> <Image_ID>
#删除全部的镜像
docker rmi -f $(docker images -aq)
3.3 容器命令
说明:我们有了镜像才可以创建容器,Linux,下载一个CentOS 7.9.2009 镜像来测试学习
$ docker pull centos:7.9.2009
新建容器并启动
$ docker run [可选参数] image
#参数说明
--name="Name" 容器名字 tomcat01 tomcat02,用来区分容器
-d 后台运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口
容器端口
-P 随机分配端口
#测试
$ docker run -it --name centos-node01 centos:7.9.2009 /bin/bash
#查看容器内的CentOS,基础环境,很多命令是不完善的
[root@094cce7271cd /]# ls
anaconda-post.log bin dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
#从容器中退回主机
[root@094cce7271cd /]# exit
exit
列出所有运行的容器
#docker ps 命令
#默认是列出当前正在运行的容器
-a #列出当前正在运行的容器+带出历史运行过的容器
-n=? #显示最近创建的容器
-q #只显示容器的编号
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
094cce7271cd centos:7.9.2009 "/bin/bash" 2 minutes ago Up 2 minutes centos-node01
495be2b73cf1 feb5d9fea6a5 "/hello" 24 hours ago Exited (0) 24 hours ago thirsty_faraday
退出容器
exit #直接容器停止并退出
Ctrl+P+Q #容器不停止退出
删除容器
#删除指定的容器,不能删除正在运行的容器,如果要强制删除 docker rm -f
docker rm 容器ID
#删除所有的容器
docker rm -f $(docker ps -aq)
docker ps -aq | xargs docker rm -f
启动和停止容器的操作
#启动容器
docker start 容器ID
#重启容器
docker restart 容器ID
#停止当前正在运行容器
docker stop 容器ID
#强制停止当前容器
docker kill 容器ID
3.4 常用其他命令
后台启动容器
#命令 docker run -d 镜像名!
docker run -d centos:7.9.2009
#问题 docker ps ,发现 centos:7.9.2009 停止了
#常见的坑,docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
#nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了。
#测试
docker run -d -it --name centos-node02 centos:7.9.2009 /bin/bash
查看日志
$ docker logs -f -t --tail [指定条目数] 容器
#显示日志
-tf :显示日志(-f动态显示,-t时间戳显示)
--tail :要显示日志的条目数
#启动容器时指定相应的命令
$ docker run -itd \
--name centos-node03 \
--restart=always \
centos:7.9.2009 /bin/bash -c "while true;do echo hello,world;done;sleep 1"
$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
707f6716e19c centos:7.9.2009 "/bin/bash -c 'while…" 38 seconds ago Up 37 seconds centos-node03
$ docker logs -f -t --tail 10 centos-node03
查看容器中进程信息
#命令 docker top 容器ID
$ docker top centos-node03
UID PID PPID C STIME TTY TIME CMD
root 15876 15855 82 22:37 ? 00:03:18 /bin/bash -c while true;do echo hello,world;done;sleep 1
查看容器的元数据
#命令
docker inspect 容器ID
#测试
$ docker inspect centos-node03
[
{
"Id": "707f6716e19ceea875cdd61dc2969b3542aed5523ffa78bb8f65c460050d08ed",
"Created": "2022-08-23T14:37:13.462762788Z",
"Path": "/bin/bash",
"Args": [
"-c",
"while true;do echo hello,world;done;sleep 1"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 15876,
"ExitCode": 0,
"Error": "",
"StartedAt": "2022-08-23T14:37:13.81511042Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:eeb6ee3f44bd0b5103bb561b4c16bcb82328cfe5809ab675bb17ab3a16c517c9",
"ResolvConfPath": "/var/lib/docker/containers/707f6716e19ceea875cdd61dc2969b3542aed5523ffa78bb8f65c460050d08ed/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/707f6716e19ceea875cdd61dc2969b3542aed5523ffa78bb8f65c460050d08ed/hostname",
"HostsPath": "/var/lib/docker/containers/707f6716e19ceea875cdd61dc2969b3542aed5523ffa78bb8f65c460050d08ed/hosts",
"LogPath": "/var/lib/docker/containers/707f6716e19ceea875cdd61dc2969b3542aed5523ffa78bb8f65c460050d08ed/707f6716e19ceea875cdd61dc2969b3542aed5523ffa78bb8f65c460050d08ed-json.log",
"Name": "/centos-node03",
"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": "always",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"CgroupnsMode": "host",
"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/72f30a5ccf50446ae62fd2722e318bea1a2dabc9eef978a37d60a7739350f8d8-init/diff:/var/lib/docker/overlay2/a37fa3541021205d4cc6fe5a51d6bda9a627c860fe9e0d6b23b317fd03e02dd8/diff",
"MergedDir": "/var/lib/docker/overlay2/72f30a5ccf50446ae62fd2722e318bea1a2dabc9eef978a37d60a7739350f8d8/merged",
"UpperDir": "/var/lib/docker/overlay2/72f30a5ccf50446ae62fd2722e318bea1a2dabc9eef978a37d60a7739350f8d8/diff",
"WorkDir": "/var/lib/docker/overlay2/72f30a5ccf50446ae62fd2722e318bea1a2dabc9eef978a37d60a7739350f8d8/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "707f6716e19c",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": true,
"OpenStdin": true,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/bash",
"-c",
"while true;do echo hello,world;done;sleep 1"
],
"Image": "centos:7.9.2009",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20201113",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS",
"org.opencontainers.image.created": "2020-11-13 00:00:00+00:00",
"org.opencontainers.image.licenses": "GPL-2.0-only",
"org.opencontainers.image.title": "CentOS Base Image",
"org.opencontainers.image.vendor": "CentOS"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "7e286039cc7562f9fe6b6174ef9dae698a6dc049414cfc56d666ca471689a78d",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
},
"SandboxKey": "/var/run/docker/netns/7e286039cc75",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "4b0a08726af85c28a4a6181d335491dd61c0e0b5530248f6be9adfc8ed9f6f41",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.4",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:04",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "ab0a6a7d99f1b549817749b69872806ed8989be4f03d330498f0f6becdd2b010",
"EndpointID": "4b0a08726af85c28a4a6181d335491dd61c0e0b5530248f6be9adfc8ed9f6f41",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.4",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:04",
"DriverOpts": null
}
}
}
}
]
进入当前正在运行的容器
#通常容器都是使用后台方式运行的,需要进入容器,修改一些配置
#命令
docker attach 容器ID
docker exec -it 容器ID bashShell
#测试
$ docker exec -it centos-node03 /bin/bash
[root@707f6716e19c /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 85 14:37 pts/0 00:09:17 /bin/bash -c while true;do echo hello,world;done;sleep 1
root 7 0 0 14:47 pts/1 00:00:00 /bin/bash
root 21 7 0 14:48 pts/1 00:00:00 ps -ef
[root@707f6716e19c /]# exit
exit
#测试
$ docker attach centos-node03
hello,world
hello,world
hello,world
#正在执行当前的代码
#docker exec #进入容器后开启一个新的终端,可以在里面操作(常用)
#docker attach #进入容器正在执行的终端,不会启动新的进程
从容器内拷贝文件到主机上
docker cp 容器ID:容器内路径 宿主机路径
#宿主机创建一个文件
$ echo "hello,docker" > host.txt
#将宿主机的文件传到容器内
$ docker cp host.txt centos-node03:/tmp
$ docker exec -it centos-node03 cat /tmp/host.txt #容器内有该文件
hello,docker
#容器内创建文件
$ docker exec -it centos-node03 /bin/bash
[root@707f6716e19c /]# cd /tmp/
[root@707f6716e19c tmp]# echo "hello,dockerhost" > docker.txt
[root@707f6716e19c tmp]# exit
#容器内的文件传到宿主机中
$ docker cp centos-node03:/tmp/docker.txt /tmp
$ cat /tmp/docker.txt
hello,dockerhost
#拷贝是一个手动过程,未来我们使用 -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’s changes — 提交当前容器为新的镜像cp
Copy files/folders from the containers filesystem to the host past — 从容器中拷贝指定文件或者目录到宿主机中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 a running container — 在已存在的容器上运行命令export
Stream the contents of a container as a tar archive — 导出容器的内容流作为一个 tar 归档文件[对应 import]history
Show the history of an image — 展示一个镜像形成历史images
List images — 列出本地系统当前镜像info
Display system-wide information — 显示系统相关信息inspect
Return low-level information on Docker objects — 查看容器详细信息kill
Kill a runnning containers — kill 指定 docker 容器load
Load an image from a tar archive — 从一个 tar 包中加载一个镜像 [ 对应 save ]login
Log in to a Docker registry — 注册或者登陆一个 docker 源服务器logout
Log out from a Docker registry — 从当前 Docker Registry 退出logs
Fetch the logs of a container — 输出当前容器日志信息port
List port mappings or a specific mapping for the container — 查看映射端口对应的容器内部源端口pause
Pause all processes within one or more containers — 暂停容器ps
List containers — 列出容器列表pull
Pull an image or a repository from a registry — 从docker镜像源服务器拉取指定镜像或者库镜像push
Push an image or a repository to a registry — 推送指定镜像或者库镜像至docker镜像源服务器restart
Restart one or more containers — 重启运行的容器rm
Remove one or more containers — 移除一个或者多个容器rmi
Remove one or more images — 移除一个或者多个镜像[无容器使用该镜像才可输出,否则需要输出相关容器才能可以继续或者 -f 强制删除]run
Run a command in a new container — 创建一个新的容器并运行一个命令save
Save one or more images to a tar archive — 保存一个镜像为一个 tar 包[ 对应 load ]search
Search the Docker Hub for images — 在 DockerHub 中搜索镜像start
Start one or more stopped containers — 启动容器stop
Stop one or more running containers — 停止容器stats
Display a live stream of container(s) resource usage statistics — 显示容器资源使用统计的实时流tag
Tag an image into a repository — 给源中镜像打标签top
Display the running processes of a container — 查看容器中运行的进程信息unpause
Unpause a pause container — 取消暂停容器version
Show the Docker version information — 查看 Docker 版本号wait
Block until one or more containers stop, then print their exit codes — 截取容器停止时的退出状态值
docker 的命令十分多,以上是最常用的容器和镜像的命令。
3.6 作业练习
3.6.1 部署Nginx
#1.搜索nginx镜像 docker search 建议去dockerhub搜索,可以看到帮助文档
#2.下载镜像 docker pull
$ docker pull nginx:1.23.1-alpine
$ docker images nginx:1.23.1-alpine
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx 1.23.1-alpine 804f9cebfdc5 13 days ago 23.5MB
#3.启动容器
#-d 后台运行
#--name 给容器命名
#-p 宿主机端口:容器内部端口
$ docker run -itd --name nginx01 -p 3344:80 --restart=always nginx:1.23.1-alpine
$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d0edd598caa1 nginx:1.23.1-alpine "/docker-entrypoint.…" 6 minutes ago Up 6 minutes 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01
$ curl localhost:3344
$ docker port nginx01
80/tcp -> 0.0.0.0:3344
80/tcp -> :::3344
端口暴露的概念
思考问题:我们每次改动Nginx配置,都需要进入容器内部?十分的麻烦,要是可以在容器外部提供一个映射路径,达到在容器修改文件名,容器内部就可以自动修改?
解决方法:-v 数据卷
3.6.2 部署 Tomcat
#官方的使用
$ docker run -it --rm tomcat:9.0
#之前的启动都是后台,停止了容器之后,容器还可以 docker ps 查到
#docker run -it --rm 一般用来测试,用完就删除容器
#下载在启动
$ docker pull tomcat:9.0
$ docker run -it -p 3355:8080 --name tomcat01 -d tomcat:9.0
#测试访问没有问题
#进入容器
$ docker exec -it tomcat01 /bin/bash
root@2cf8573ed4e2:/usr/local/tomcat# cp -av webapps.dist/* webapps/
root@2cf8573ed4e2:/usr/local/tomcat# exit
exit
#发现问题:
#1.Linux命令少了
#2.webapps目录下没有web文件。镜像的原因,默认是最小的镜像,所有不必要的都剔除掉。
#保证最小可运行的环境
$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2cf8573ed4e2 tomcat:9.0 "catalina.sh run" 4 minutes ago Up 4 minutes 0.0.0.0:3355->8080/tcp, :::3355->8080/tcp tomcat01
$ docker port tomcat01
8080/tcp -> 0.0.0.0:3355
8080/tcp -> :::3355
思考问题:我们以后要部署项目,如果每次都要进入容器是不是十分麻烦?要是可以在容器外部提供一个映射路径,webapps,我们在外部放置项目,就自动同步到内部就好了!
3.6.3 部署 ES+Kibana
#ES暴露的端口很多
#ES十分的消耗内存
#ES的数据一般需要放置到安全目录!挂载
$ docker network create somenetwork
#启动 elasticsearch 容器
$ docker run -d --name elasticsearch \
--net somenetwork \
-p 9200:9200 \
-p 9300:9300 \
-e "discovery.type=single-node" elasticsearch:7.17.5
#启动了 elasticsearch容器后,docker stats 查看CPU状态
$ docker stats --no-stream elasticsearch
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
90e93d93b0b0 elasticsearch 1.41% 1.226GiB / 3.682GiB 33.28% 2.38kB / 0B 0B / 1.02MB 45
#测试ES是否成功了,增加内存的设置
$ curl localhost:9200
{
"name" : "90e93d93b0b0",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "W4bf0m9_TU2e5TxRgifsqg",
"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"
}
#设置容器的内存限制,修改配置文件-e环境配置修改
$ docker run -d --name elasticsearch \
--net somenetwork \
-p 9200:9200 \
-p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms256m -Xmx512m" elasticsearch:7.17.5
#再次查看 docker stats 容器资源状态
$ docker stats --no-stream elasticsearch
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
c4479d160c62 elasticsearch 1.52% 364.6MiB / 3.682GiB 9.67% 656B / 0B 0B / 849kB 46
$ curl localhost:9200
{
"name" : "c4479d160c62",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "xj_fi6P2Tc2DldYqSCz2dw",
"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"
}
#安装Kibana
$ mkdir -p /mydata/elasticsearch/kibana/config/
$ cat > /mydata/elasticsearch/kibana/config/kibana.yml <<EOF
#
# ** THIS IS AN AUTO-GENERATED FILE **
#
# Default Kibana configuration for docker target
server.host: "0.0.0.0"
server.shutdownTimeout: "5s"
elasticsearch.hosts: [ "http://10.0.0.101:9200" ]
monitoring.ui.container.elasticsearch.enabled: true
EOF
$ docker run -d \
--name kibana \
--net somenetwork \
-v /mydata/elasticsearch/kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml \
-p 5601:5601 kibana:7.17.5
$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aa2b70cdab6f kibana:7.17.5 "/bin/tini -- /usr/l…" 2 minutes ago Up 2 minutes 0.0.0.0:5601->5601/tcp, :::5601->5601/tcp kibana#安装Kibana
$ mkdir -p /mydata/elasticsearch/kibana/config/
$ cat > /mydata/elasticsearch/kibana/config/kibana.yml <<EOF
#
# ** THIS IS AN AUTO-GENERATED FILE **
#
# Default Kibana configuration for docker target
server.host: "0.0.0.0"
server.shutdownTimeout: "5s"
elasticsearch.hosts: [ "http://10.0.0.101:9200" ]
monitoring.ui.container.elasticsearch.enabled: true
EOF
$ docker run -d \
--name kibana \
--net somenetwork \
-v /mydata/elasticsearch/kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml \
-p 5601:5601 kibana:7.17.5
$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aa2b70cdab6f kibana:7.17.5 "/bin/tini -- /usr/l…" 2 minutes ago Up 2 minutes 0.0.0.0:5601->5601/tcp, :::5601->5601/tcp kibana
4 Docker 镜像
4.1 Docker 镜像是什么
- Docker 镜像是什么?
镜像是一种轻量级,可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码,运行时需要的库,环境变量和配置文件等),这个打包好的运行环境就是 image 镜像文件。
只有通过这个镜像文件才能生成 Docker 容器实例(类似Java中 new 出来一个对象)
未来所有的应用,直接打包成 Docker 镜像,就可以直接跑起来。
如何得到镜像?
- 从远程仓库下载
- 朋友同学拷贝得到
- 自己制作镜像Dockerfile
- 分层的镜像
在使用 pull 为例,在下载的过程中可以看到 docker 的镜像好像是在一层一层的在下载。
$ docker pull tomcat
4.2 Docker 镜像加载原理
- UnionFS(联合文件系统)
UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层一层的叠加
,同时可以将不同目录挂载到同一个虚拟文件系统下(Unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承
,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但是从外面看起来,只能看到一个文件系统,联合加载会把各种文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
联合文件系统:分层,轻量,并且能够聚合的一种镜像基础。
- Docker 镜像加载原理
Docker 镜像加载原理:
Docker 的镜像实际上是由一层一层的文件系统组成
的,这种层级的文件系统UnionFS。
bootfs(boot file system)主要包含 bootloader(根加载) 和 kernel(Linux内核),bootloader 主要是引导加载 kernel,Linux 刚启动时会加载 bootfs文件系统(主要引导Linux内核),在Docker 镜像的最底层时引导文件系统 bootfs
。这一层与我们典型的Linux/Unix系统是一样的,包含 boot加载器和内核。当 boot 加载完成之后整个内核都在内存中,此时内存的使用权已由 bootfs 转交给内核,此时系统也会卸载 bootfs。
rootfs(root file system),在 bootfs 之上,包含的就是典型 Linux 系统中的 /dev,/proc,/bin,/etc等标准目录和文件。rootfs 就是各种不同的操作系统发行版
,比如 Ubuntu,CentOS 等等。
总结:
- bootfs:系统启动的时候需要 bootloader 引导器加载内核 kernel,bootfs 就会卸载,将内存试用权给kernel。
- rootfs:Linux系统的标准目录和文件,类似于一个小型阉割版的虚拟机环境
- 系统由三个部分组成,bootfs + rootfs + 应用组成,其中 bootfs 非常大,但是在 Docker 中是公用的,所有镜像中不包含 bootfs ,镜像主要由 rootfs + 应用组成,所以比较小。
平时我们安装虚拟机的 CentOS 都是好几个G,为什么 Docker 这里才 200M?
答案:对于一个精简的OS,rootfs 可以很小,只需要包括最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就行了。由此可见对于不同的 Linux 发行版,bootfs 基本上是一致的,rootfs 会有差别,因此不同的发行版可以共用 bootfs。
也是 虚拟机是分钟级的,容器是秒级的原因。容器只是运行命令和运行应用的环境,底层调用的是宿主机的内核。
~ docker images centos:centos7.9.2009
REPOSITORY TAG IMAGE ID CREATED SIZE
centos centos7.9.2009 eeb6ee3f44bd 11 months ago 204MB
4.3 分层理解
底层的镜像
我们可以去下载一个镜像,注岚观察下或的日志输出,可以看到是一层一层的在下载!
- 为什么 Docker 镜像要采用着这种分层结构呢?
Docker 镜像分层最大的一个好处就是共享资源,方便复制迁移,就是为了复用
。
比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
查看镜像分层的方式可以通过 docker image inspect 命令
~ docker image inspect redis
...省略部分输出...
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f",
"sha256:9b24afeb7c2f21e50a686ead025823cd2c6e9730c013ca77ad5f115c079b57cb",
"sha256:4b8e2801e0f956a4220c32e2c8b0a590e6f9bd2420ec65453685246b82766ea1",
"sha256:529cdb636f61e95ab91a62a51526a84fd7314d6aab0d414040796150b4522372",
"sha256:9975392591f2777d6bf4d9919ad1b2c9afa12f9a9b4d260f45025ec3cc9b18ed",
"sha256:8e5669d8329116b8444b9bbb1663dda568ede12d3dbcce950199b582f6e94952"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
理解:
所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于Ubuntu Linux 16.04创建一个新的镜像,这就是新镜像的第一层;如果在该境像中添加 Python包,就会需要在基础镜像层之上增加和修改和新的内容并提交 commit 创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下因中举了一个简单的例子,每个镜像.层包含3个文件,而境像包含了来白两个境像层的6个文件。
上图中的镜猕层银之前图中的路有区别,主要目的是使于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件,这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。Docker通过存储引擎(新版本采用快照机制》的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统.
Linux上可用的存储引擎有AUF5、Overlay2、Device Mapper、Btrfs 以及.zZFS。顾名思义,每种存储引擎都基于Linux 中对应的.文件系统或者块设备技术,并且每种存储引挛都有其独有的性能特点。
Docker在Windows上仪支持 windowstilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW[1]。
下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。
特点:
Docker 镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层!
重点理解
Docker 镜像层都是只读的,容器层是可写的。
当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称为“容器层”,“容器层”之下的都叫镜像层。
所有对容器的改动,无论添加、删除、还是修改文件都只会发生在容器中。只有容器层时可写的,容器层下面的所有镜像层都是只读的。
4.4 如何提交一个自己的镜像
4.4.1 commit 镜像
docker commit 提交容器成为一个新的版本
#命令和Git的原理类似
docker commit -m "提交的描述信息" -a "作者" 容器ID 目标镜像名:[TAG]
范例:
#启动一个默认的Tomcat
$ docker run -it -d -p 8080:8080 --name tomcat01 tomcat
#发现这个默认的Tomcat新版本是没有webapps应用,是由于镜像的原因:官方的新镜像默认Tomcat下的webapps目录下是没有文件的
$ docker exec -it tomcat01 /bin/bash
#将webapps.dist目录下的文件拷贝到webapps中
root@82b9be0838cd:/usr/local/tomcat# cp -av webapps.dist/ webapps
root@82b9be0838cd:/usr/local/tomcat# cd webapps
root@82b9be0838cd:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
root@82b9be0838cd:/usr/local/tomcat/webapps# exit
exit
$ curl localhost:8080
#将操作过的容器通过 commit 提交为一个镜像
$ docker commit \
-a "zhongzhiwei <[email protected]>" \
-m "拷贝webapps.dist目录下的内容到webapps" \
tomcat01 kube-tomcat:1.0
#查看提交的镜像
$ docker images kube-tomcat:1.0
REPOSITORY TAG IMAGE ID CREATED SIZE
kube-tomcat 1.0 0cf24bc18be1 4 seconds ago 684MB
$ docker history kube-tomcat:1.0
IMAGE CREATED CREATED BY SIZE COMMENT
0cf24bc18be1 3 minutes ago catalina.sh run 4.43MB 拷贝webapps.dist目录下的内容到webapps
fb5657adc892 8 months ago /bin/sh -c #(nop) CMD ["catalina.sh" "run"] 0B
<missing> 8 months ago /bin/sh -c #(nop) EXPOSE 8080 0B
<missing> 8 months ago /bin/sh -c set -eux; nativeLines="$(catalin… 0B
<missing> 8 months ago /bin/sh -c set -eux; savedAptMark="$(apt-m… 20.2MB
<missing> 8 months ago /bin/sh -c #(nop) ENV TOMCAT_SHA512=c2d2ad5… 0B
<missing> 8 months ago /bin/sh -c #(nop) ENV TOMCAT_VERSION=10.0.14 0B
<missing> 8 months ago /bin/sh -c #(nop) ENV TOMCAT_MAJOR=10 0B
<missing> 8 months ago /bin/sh -c #(nop) ENV GPG_KEYS=A9C5DF4D22E9… 0B
<missing> 8 months ago /bin/sh -c #(nop) ENV LD_LIBRARY_PATH=/usr/… 0B
<missing> 8 months ago /bin/sh -c #(nop) ENV TOMCAT_NATIVE_LIBDIR=… 0B
<missing> 8 months ago /bin/sh -c #(nop) WORKDIR /usr/local/tomcat 0B
<missing> 8 months ago /bin/sh -c mkdir -p "$CATALINA_HOME" 0B
<missing> 8 months ago /bin/sh -c #(nop) ENV PATH=/usr/local/tomca… 0B
<missing> 8 months ago /bin/sh -c #(nop) ENV CATALINA_HOME=/usr/lo… 0B
<missing> 8 months ago /bin/sh -c #(nop) CMD ["jshell"] 0B
<missing> 8 months ago /bin/sh -c set -eux; arch="$(dpkg --print-… 343MB
<missing> 8 months ago /bin/sh -c #(nop) ENV JAVA_VERSION=11.0.13 0B
<missing> 8 months ago /bin/sh -c #(nop) ENV LANG=C.UTF-8 0B
<missing> 8 months ago /bin/sh -c #(nop) ENV PATH=/usr/local/openj… 0B
<missing> 8 months ago /bin/sh -c {
echo '#/bin/sh'; echo 'echo "$J' 27B
<missing> 8 months ago /bin/sh -c #(nop) ENV JAVA_HOME=/usr/local/… 0B
<missing> 8 months ago /bin/sh -c set -eux; apt-get update; apt-g… 11.3MB
<missing> 8 months ago /bin/sh -c apt-get update && apt-get install… 152MB
<missing> 8 months ago /bin/sh -c set -ex; if ! command -v gpg > /… 18.9MB
<missing> 8 months ago /bin/sh -c set -eux; apt-get update; apt-g… 10.7MB
<missing> 8 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 8 months ago /bin/sh -c #(nop) ADD file:c03517c5ddbed4053… 124MB
#使用我们修改提交的新镜像,那么就会发现在 webapps 目录下有相应的文件
$ docker run -it -p 8085:8080 --name mytomcat01 -d kube-tomcat:1.0
$ docker exec -it mytomcat01 /bin/bash
root@6b8f51a773ee:/usr/local/tomcat# ls webapps
ROOT docs examples host-manager manager
root@6b8f51a773ee:/usr/local/tomcat# exit
exit
$ curl localhost:8085
学习方式说明:理解概念,可以比较模糊,但是一定要实践,最后实践和理论相结合。
如果想保存当前容器的状态,就可以通过 commit 方式来提交镜像,获取一个镜像。类似于虚拟机的快照功能。