【Docker】Docker 常用命令和 Docker 镜像

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

启动和停止容器的操作

扫描二维码关注公众号,回复: 17169180 查看本文章
#启动容器
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 总结

img

  • attachAttach to a running container — 当前Shell下attach连接指定运行容器
  • buildBuild an image from a Dockerfile — 通过Dockerfile定制镜像
  • commitCreate a new image from a container’s changes — 提交当前容器为新的镜像
  • cpCopy files/folders from the containers filesystem to the host past — 从容器中拷贝指定文件或者目录到宿主机中
  • createCreate a new container — 创建一个新的容器,同run,但是不启动容器
  • diffInspect changes on a container’s filesystem — 查看 docker 容器的变化
  • eventsGet real time events from the server — 从 docker 服务获取容器实时事件
  • execRun a command in a running container — 在已存在的容器上运行命令
  • exportStream the contents of a container as a tar archive — 导出容器的内容流作为一个 tar 归档文件[对应 import]
  • historyShow the history of an image — 展示一个镜像形成历史
  • imagesList images — 列出本地系统当前镜像
  • infoDisplay system-wide information — 显示系统相关信息
  • inspect Return low-level information on Docker objects — 查看容器详细信息
  • killKill a runnning containers — kill 指定 docker 容器
  • loadLoad an image from a tar archive — 从一个 tar 包中加载一个镜像 [ 对应 save ]
  • loginLog in to a Docker registry — 注册或者登陆一个 docker 源服务器
  • logoutLog out from a Docker registry — 从当前 Docker Registry 退出
  • logsFetch the logs of a container — 输出当前容器日志信息
  • portList port mappings or a specific mapping for the container — 查看映射端口对应的容器内部源端口
  • pausePause all processes within one or more containers — 暂停容器
  • psList containers — 列出容器列表
  • pullPull an image or a repository from a registry — 从docker镜像源服务器拉取指定镜像或者库镜像
  • pushPush an image or a repository to a registry — 推送指定镜像或者库镜像至docker镜像源服务器
  • restartRestart one or more containers — 重启运行的容器
  • rmRemove one or more containers — 移除一个或者多个容器
  • rmiRemove one or more images — 移除一个或者多个镜像[无容器使用该镜像才可输出,否则需要输出相关容器才能可以继续或者 -f 强制删除]
  • runRun a command in a new container — 创建一个新的容器并运行一个命令
  • saveSave one or more images to a tar archive — 保存一个镜像为一个 tar 包[ 对应 load ]
  • searchSearch the Docker Hub for images — 在 DockerHub 中搜索镜像
  • startStart one or more stopped containers — 启动容器
  • stopStop one or more running containers — 停止容器
  • statsDisplay a live stream of container(s) resource usage statistics — 显示容器资源使用统计的实时流
  • tagTag an image into a repository — 给源中镜像打标签
  • topDisplay the running processes of a container — 查看容器中运行的进程信息
  • unpauseUnpause a pause container — 取消暂停容器
  • versionShow the Docker version information — 查看 Docker 版本号
  • waitBlock 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

img

端口暴露的概念

img

思考问题:我们每次改动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

img

思考问题:我们以后要部署项目,如果每次都要进入容器是不是十分麻烦?要是可以在容器外部提供一个映射路径,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"
}

img

#安装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

img

4 Docker 镜像

4.1 Docker 镜像是什么

  • Docker 镜像是什么?

镜像是一种轻量级,可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码,运行时需要的库,环境变量和配置文件等),这个打包好的运行环境就是 image 镜像文件。

只有通过这个镜像文件才能生成 Docker 容器实例(类似Java中 new 出来一个对象)

未来所有的应用,直接打包成 Docker 镜像,就可以直接跑起来。

如何得到镜像?

  1. 从远程仓库下载
  2. 朋友同学拷贝得到
  3. 自己制作镜像Dockerfile
  • 分层的镜像

在使用 pull 为例,在下载的过程中可以看到 docker 的镜像好像是在一层一层的在下载。

$ docker pull tomcat

img

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 等等。

总结:

  1. bootfs:系统启动的时候需要 bootloader 引导器加载内核 kernel,bootfs 就会卸载,将内存试用权给kernel。
  2. rootfs:Linux系统的标准目录和文件,类似于一个小型阉割版的虚拟机环境
  3. 系统由三个部分组成,bootfs + rootfs + 应用组成,其中 bootfs 非常大,但是在 Docker 中是公用的,所有镜像中不包含 bootfs ,镜像主要由 rootfs + 应用组成,所以比较小。

img

img

平时我们安装虚拟机的 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 分层理解

底层的镜像

我们可以去下载一个镜像,注岚观察下或的日志输出,可以看到是一层一层的在下载!

img

  • 为什么 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个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。

img

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下因中举了一个简单的例子,每个镜像.层包含3个文件,而境像包含了来白两个境像层的6个文件。

img

上图中的镜猕层银之前图中的路有区别,主要目的是使于展示文件。

下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。

img

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件,这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。Docker通过存储引擎(新版本采用快照机制》的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统.

Linux上可用的存储引擎有AUF5、Overlay2、Device Mapper、Btrfs 以及.zZFS。顾名思义,每种存储引擎都基于Linux 中对应的.文件系统或者块设备技术,并且每种存储引挛都有其独有的性能特点。

Docker在Windows上仪支持 windowstilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW[1]。

下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。

img

特点:

Docker 镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!

这一层就是我们通常说的容器层,容器之下的都叫镜像层!

重点理解

Docker 镜像层都是只读的,容器层是可写的。

当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称为“容器层”,“容器层”之下的都叫镜像层。

所有对容器的改动,无论添加、删除、还是修改文件都只会发生在容器中。只有容器层时可写的,容器层下面的所有镜像层都是只读的。

img

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 方式来提交镜像,获取一个镜像。类似于虚拟机的快照功能。

猜你喜欢

转载自blog.csdn.net/weixin_40274679/article/details/131736773