2021-07-08

本文深入介绍了Docker的基础知识,包括Docker镜像的分层原理、容器的启动与管理、数据卷的使用以及网络配置。重点讨论了容器的数据持久化,通过数据卷实现多个容器间的数据共享,并演示了Dockerfile构建自定义镜像的过程。此外,还介绍了Docker网络的桥接模式和自定义网络,以及容器间的网络连通性。
摘要由CSDN通过智能技术生成

Docker概述

Docker为什么出现


一款产品: 开发–上线 两套环境! 应用环境,应用配置!

开发 — 运维。 问题:我在我的电脑上可以运行!版本更新,导致服务部可用! 对于运维来说,考验十分大

Docker的思想就来自于集装箱,看他现在的logo就一目了然,一个小鲸鱼上面装了很都货物

Docker的出现解决了项目部署的的问题。比如MySQL集群或者是Redis集群等,如果单独去部署这些东西很麻烦,但是通过Docker一键就可以安装了,就是因为Docker本身就写好了这些东西的配置。

Docker官网: https://www.docker.com/

文档地址: https://docs.docker.com/

仓库地址: https://hub.docker.com/

容器化技术,不是虚拟出一套完整的操作系统。每一个容器都是隔离的,每一个容器都会跟自己的项目进行打包形成一个镜像,而且它是直接运行在系统之上的。不像虚拟机,有很多得lib拓展。占用很大一部分资源。像虚拟机上如果一些拓展崩了的话,有可能会直接影响系统运行。但是容器就不会。因为它的隔离性。即使是其中的一项崩掉。也不会影响其他的项目运行。从而将自己的服务器资源最大化利用。这也是Docker最大的优势。

比较Docker与虚拟机技术的不同

  1. 传统虚拟机,虚拟出一套完整的操作系统,然后再这个系统上安装和运行软件
  2. 容器内法人应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有虚拟我们的硬件。
  3. 每个容器间是互相隔离的,每个容器内都有一个属于自己的文件系统,互不影响。

Docker的基本组成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O1ts1746-1625704465857)(/Users/minato/Library/Application Support/typora-user-images/image-20210525193756861.png)]

镜像(image):docker镜像就好比一个模板,可以通过这个模板来创建容器服务。镜像==》run==》镜像容易(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)

容器(container):Docker利用容器技术,独立运行一个或者一组应用。通过镜像来创建的。启动,停止,删除,基本命令,可以吧容器理解为一个建议的linux系统。

仓库(repository):仓库就是存放镜像的地方。仓库分为共有仓库和私有仓库。

Docker Hub

阿里云,华为云都有容器服务(配置镜像加速)。

Docker安装

  1. 卸载旧版本:
sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
  1. 安装基本环境:
# 需要的安装包
sudo yum install -y yum-utils

# 设置镜像的仓库
sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo # 默认是国外源,不用这个


sudo yum-config-manager \
    --add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 用阿里云的

更新yum软件包索引

yum makecac fask
  1. 安装docker相关的内容 docker-ce社区办(推荐) ee企业版
yum install docker-ce docker-ce-cli containerd.io
  1. 启动docker
systemctl start docker
# 利用docker version查看是否启动
  1. 测试 hellow world
docker run hello-world
  1. 查看下载的镜像
docker images
  1. 卸载 docker
# 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
# 删除docker资源目录
rm -rf /var/lib/docker

rm -rf /var/lib/containerd

阿里云镜像加速

  1. 登录阿里云 找到容器服务

  2. 找到镜像加速地址

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rXgNDoEB-1625704465860)(/Users/minato/myfile/Markdown文档辅助图/image-20210525205238784.png)]

  3. 按上述命令配置使用

回顾hellowworld是如何启动的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fpnq1PHa-1625704465861)(/Users/minato/myfile/Markdown文档辅助图/image-20210525210921622.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uIWIbODO-1625704465863)(/Users/minato/myfile/Markdown文档辅助图/image-20210525210837217.png)]

底层原理

docker是怎么工作的额

Docker是一个Client - Server结构的系统,Docker的守护进程运行在主机上,通过Socker从客户端访问!

DockerServer接收到DockerClient的指令,就会执行这个命令

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aHaAapjm-1625704465864)(/Users/minato/myfile/Markdown文档辅助图/image-20210525211442404.png)]

Docker为什么比vm快?

  1. Docker有着比虚拟机更少的抽象层

  2. docker利用的是宿主机的内核,vm需要的是Guest OS。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dJWAVp8u-1625704465865)(/Users/minato/myfile/Markdown文档辅助图/image-20210525211604235.png)]

    所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载Guest OS,分钟级别的,而docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级!

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PB2rY8On-1625704465866)(/Users/minato/myfile/Markdown文档辅助图/image-20210525212609694.png)]

之后学习完毕所有的命令没再回过头来看这段理论,就会很清晰!

docker的常用命令

docker version # 查看docker的版本信息
docker info # 现实docker的系统信息,包括镜像和容器的数量
docker 命令 --help # 帮助信息

镜像命令

docker images [options] # 查看所有本地主机所有镜像
-a #列出所有镜像
-f #过滤
-q #只显示镜像ID(常用)
REPOSITORY(镜像仓库源) TAG(标签) CREATED(镜像创建时间) IMAGE ID(镜像ID) SEZI(大小)

docker search #搜索镜像
docker pull [:tag] #下载镜像tag可选,不加默认拉取最新镜像
# pull complete部分为分层下载,docker image的核心,联合文件系统
# Digest 为签名
# docker.io/library/mysql:latest 为真实地址
# 直接用docker pull就等于docker.io/library/mysql:latest
# 指定版本下载 docker pull mysql:5.7
# 分层下载是很高明的。精髓在于不同的镜像版本也会有一些相同部分,这样分层下载,相同部分就相当于共用,不需要重复下载。具体如下图。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WAB7q9gW-1625704465866)(/Users/minato/myfile/Markdown文档辅助图/image-20210601195105937.png)]

docker rmi 删除镜像

docker rmi-f [options] # + 镜像ID,按ID删除, + 镜像名称,按名称删除,rmi就是 remove image
docker rmi -f # 也可以加多个镜像id同时删除多个镜像
docker rmi -f $(docker images -aq) #删除所有容器,递归删除

容器命令

说明:有了镜像才可以创建容器,linux,下载一个centos镜像来测试学习

docker pull centos

新建容器并启动

docker run [可选参数] image
# 参数说明
--name="Name"   # 给容器命名,用来区分容器
-d              # 后台方式运行
-it             # 使用交互方式运行,进入容器查看内容(进入容器)
-p              # 指定容器的端口 
					-p 主机ip:主机端口:容器端口(主机和容器映射)
					-p 主机端口:容器端口(主机和容器映射)  常用!!!
					-p 容器端口
					直接写容器端口也是可以的
-P              # 随机端口(大写P)

测试,启动并进入容器

docker run -it centos /bin/bash   

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hmnl7GUi-1625704465867)(/Users/minato/myfile/Markdown文档辅助图/image-20210601213751992.png)]

Ls查看容器内详情

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WVoMCtXj-1625704465867)(/Users/minato/myfile/Markdown文档辅助图/image-20210601214130866.png)]

你会发现其实容器内核容器外的内容几乎是一样的,因为他就是一个小型的服务器。 内部的centos与外部的centos没有任何关系

列出所有运行中的容器

docker ps [options] 参数可叠加
# 列出当前正在运行的容器
-a   # 列出当前正字啊运行的容器 + 历史运行过的容器
-n=? # 查询最近常见的容器
-q   # 只显示容器的编号

退出容器

exit    # 直接退出并停止容器
Ctrl + P + Q  #  容器不停止并退出

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xD7jaznQ-1625704465868)(file:///Users/minato/myfile/Markdown%E6%96%87%E6%A1%A3%E8%BE%85%E5%8A%A9%E5%9B%BE/image-20210601214405950.png?lastModify=1622555291)]

删除容器

docker rm  容器id   #删除指定容器,不能删除生在运行中的容器,如果要强制删除   rm -f
docker rm -f $(docker ps -ap) #删除所有容器
docker ps -a -q |xargs docker rm  # 利用管道符删除所有容器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oinwhxgc-1625704465868)(/Users/minato/myfile/Markdown文档辅助图/image-20210601215303387.png)]

启动和停止容器

docker start 容器id        # 启动容器
docker restart  容器id     # 重启容器
docker stop 容器id         # 停止当前正在运行的容器
docker kill 容器id		     # 杀掉容器,强制停止

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GWObHI3H-1625704465869)(/Users/minato/myfile/Markdown文档辅助图/image-20210601220223948.png)]

常用的其他命令(日志,元数据,进程的查看)

后台启动容器

docker run -d 镜像名   # 例如 docker run -d centos

问题:docker ps, 发现centos停止了

常见的坑: docker容器用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止。

例如docker启动一个nginx 但是发现nginx没有提供服务,就会立即停止,就是没有程序了

查看日志命令

# 启动容器并手动写一段shell脚本使容器不为空容器,保证容器处于运行中
docker run -d centos /bin/sh -c "while true;do echo Ken; sleep 1;done"(该脚本的含义为无限循环每隔一秒钟打印一个Ken)
# 显示日志
docker logs -ft --tail num 容器id(-ft:查看所有日志f代表时间戳、tail:以字符串的形式查看、num:查看最近的多少条)

查看容器中的进程信息

# top命令
docker top 容器id

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D75cDbEk-1625704465870)(/Users/minato/myfile/Markdown文档辅助图/image-20210601222343810.png)]

以后要杀进程的话可以通过这种方式杀

查看镜像的元数据(很重要:彻底了解镜像中有哪些数据)

docker inspect 容器id(显示容器的全部信息)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c2C5gAWQ-1625704465870)(/Users/minato/myfile/Markdown文档辅助图/image-20210601223127297.png)]我们可以看到我们常使用的id只是容器全路径的缩写

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-efhFdm57-1625704465871)(/Users/minato/myfile/Markdown文档辅助图/image-20210601223208271.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xjc6QSQj-1625704465871)(/Users/minato/myfile/Markdown文档辅助图/image-20210601223331733.png)]

以下为全部信息

# 命令
docker inspect 容器id

#测试
➜  ~ docker inspect 55321bcae33d
[
    {
        "Id": "55321bcae33d15da8280bcac1d2bc1141d213bcc8f8e792edfd832ff61ae5066",
        "Created": "2020-05-15T05:22:05.515909071Z",
        "Path": "/bin/sh",
        "Args": [
            "-c",
            "while true;do echo 6666;sleep 1;done"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 22973,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2020-05-15T05:22:06.165904633Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:470671670cac686c7cf0081e0b37da2e9f4f768ddc5f6a26102ccd1c6954c1ee",
        "ResolvConfPath": "/var/lib/docker/containers/55321bcae33d15da8280bcac1d2bc1141d213bcc8f8e792edfd832ff61ae5066/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/55321bcae33d15da8280bcac1d2bc1141d213bcc8f8e792edfd832ff61ae5066/hostname",
        "HostsPath": "/var/lib/docker/containers/55321bcae33d15da8280bcac1d2bc1141d213bcc8f8e792edfd832ff61ae5066/hosts",
        "LogPath": "/var/lib/docker/containers/55321bcae33d15da8280bcac1d2bc1141d213bcc8f8e792edfd832ff61ae5066/55321bcae33d15da8280bcac1d2bc1141d213bcc8f8e792edfd832ff61ae5066-json.log",
        "Name": "/bold_bell",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "docker-default",
        "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/1f347949ba49c4dbee70cea9ff3af39a14e602bc8fac8331c46347bf6708757a-init/diff:/var/lib/docker/overlay2/5afcd8220c51854a847a36f52775b4ed0acb16fe6cfaec3bd2e5df59863835ba/diff",
                "MergedDir": "/var/lib/docker/overlay2/1f347949ba49c4dbee70cea9ff3af39a14e602bc8fac8331c46347bf6708757a/merged",
                "UpperDir": "/var/lib/docker/overlay2/1f347949ba49c4dbee70cea9ff3af39a14e602bc8fac8331c46347bf6708757a/diff",
                "WorkDir": "/var/lib/docker/overlay2/1f347949ba49c4dbee70cea9ff3af39a14e602bc8fac8331c46347bf6708757a/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "55321bcae33d",
            "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 6666;sleep 1;done"
            ],
            "Image": "centos",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20200114",
                "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-01-14 00:00:00-08:00",
                "org.opencontainers.image.licenses": "GPL-2.0-only",
                "org.opencontainers.image.title": "CentOS Base Image",
                "org.opencontainers.image.vendor": "CentOS"
            }
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "63ed0c837f35c12453bae9661859f37a08541a0749afb86e881869bf6fd9031b",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/63ed0c837f35",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "b129d9a5a2cbb92722a2101244bd81a9e3d8af034e83f338c13790a1a94552a1",
            "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": "ad5ada6a106f5ba3dda9ce4bc1475a4bb593bf5f7fbead72196e66515e8ac36a",
                    "EndpointID": "b129d9a5a2cbb92722a2101244bd81a9e3d8af034e83f338c13790a1a94552a1",
                    "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
                }
            }
        }
    }
]

等等,还有一些主机的配置和自身的配置。还有挂载等等

进入当前正在运行的容器(更常用)

方式1

# 我们通常容易都是使用后台方式运行的,需要进入容器,修改一些配置
# 命令
docker exec -it 容器id bashshell
 exec  # 执行
 -it   #已交互的方式进入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wZayhumN-1625704465872)(/Users/minato/myfile/Markdown文档辅助图/image-20210601223900251.png)]

此时在输入命令,就是docker容器内部命令,也可执行部分linux命令,例如 ps -ef

方式2

docker attach 容器id

方式1 进入容器后开启一个新的终端(常用)

方式2 进入容器正在执行的终端,不会启动新的进程

从容器内拷贝文件到主机上

docker cp 容器id:容器内路径  目的主机路径

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kk4U3qkE-1625704465872)(/Users/minato/myfile/Markdown文档辅助图/image-20210601224921556.png)]

拷贝是一个手动过程,未来我们使用 -v卷的技术,可以实现自动同步,例如可以讲容日内的home目录和主机的home目录联通

小结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LvPKUTyK-1625704465873)(/Users/minato/myfile/Markdown文档辅助图/image-20210601230126025.png)]

docker 命令大全

  attach      Attach local standard input, output, and error streams 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 between a container and the local filesystem #拷贝文件
  create      Create a new container #创建一个新的容器
  diff        Inspect changes to files or directories on a container's filesystem # 查看docker容器的变化
  events      Get real time events from the server # 从服务获取容器实时时间
  exec        Run a command in a running container # 在运行中的容器上运行命令
  export      Export a container's filesystem as a tar archive # 导出容器文件系统作为一个tar归档文件[对应import]
  history     Show the history of an image # 展示一个镜像形成历史
  images      List images # 列出系统当前的镜像
  import      Import the contents from a tarball to create a filesystem image # 从tar包中导入内容创建一个文件系统镜像
  info        Display system-wide information # 显示全系统信息
  inspect     Return low-level information on Docker objects #查看容器详细信息
  kill        Kill one or more running containers # kill指定docker容器
  load        Load an image from a tar archive or STDIN # 从一个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 # 输出当前容器日志信息
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container # 查看映射端口对应的容器内部源端口
  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源服务器
  rename      Rename a container # 给容器重命名
  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 (streamed to STDOUT by default) # 保存一个镜像为一个 tar包 [对应load]
  search      Search the Docker Hub for images # 在docker hub中搜索镜像
  start       Start one or more stopped containers # 启动容器
  stats       Display a live stream of container(s) resource usage statistics # 查看容器状态
  stop        Stop one or more running containers # 停止容器
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE # 给源中镜像打标签
  top         Display the running processes of a container # 查看容器中运行的
  unpause     Unpause all processes within one or more containers # 取消暂停容器
  update      Update configuration of one or more containers # 更新一个或多个容器配置
  version     Show the Docker version information # 查看docker 版本号
  wait        Block until one or more containers stop, then print their exit codes # 截取容器停止时的退出状态值

基础实战1 docker部署nginx

端口暴露概念(宿主机与容器以及外网的关系)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hPynHf10-1625704465873)(/Users/minato/myfile/Markdown文档辅助图/image-20210603164250273.png)]

思考问题:我们每次改动nginx配置文件,都需要进入容器内部,十分麻烦。我要是可以在容器外部提供一个映射路径,达到在容器外部修改文件,容器内部就可以自动修改。 利用 -v 数据卷!(后续讲)

这里提一个官方文档的坑,以tomcat举例

官方文档里,tomcat的启动命令为

docker run -it --rm tomcat:9.0
# 这个--rm的意思就是启动完毕后,如果我们停止了这个容器,那么这个容器就会直接删除,所以一般这个命令都用于测试上,用完即删

思考问题:我们以后要部署项目,如果每次都要进入容器是不是十分麻烦?我要是可以在容器外部提供一个映射路径,我们在外部防止项目,就自动同步到内部就好了。现在docker容器包含着你的项目跟数据库的,但是如果我们把docker删掉相当于把这些都删掉了,那就不好了。那就真是删库跑路了。(后续解决)

问题:docker如何限制内存

例如elasticsearch这样的容器是非常非常耗内存的。像我们这样的学生机一般都是1核2G。一共才一点几个G的内存被一个es占了70%以上。即使不是学生机,那么这样耗内存的操作也是不好的。所以我们该如何限制docker的内存使用呢?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lA1V3W4G-1625704465874)(/Users/minato/myfile/Markdown文档辅助图/image-20210603211253896.png)]

利用 -e参数去限制,每个不同的容器可以到官方文档去查看,例如es

docker run -d --name elasticsearch -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="Xms64m -Xmx512m" elasticsearch:7.6.2    # 第二个-e参数就是限制es最大只占512M

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ynqr0M2K-1625704465874)(/Users/minato/myfile/Markdown文档辅助图/image-20210603211306118.png)]

经过限制之后,明显看到内存占用变小了。

作业练习:如何将两个容器联通。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1RelSVmF-1625704465875)(/Users/minato/myfile/Markdown文档辅助图/image-20210603212117507.png)]

可视化

portainer(先用着这个)

docker run -d -p 8088:9000 \ --restart=always -v /var/run/docker.sock:var/run/docker.sock --privileged=true portainer

Rancher(CI/CD再用(持续集成持续部署时))

什么是portainer?

Docker图形化界面管理工具! 提供一个后台面板供我们操作

大家自行安装测试着玩玩就行

Docker镜像讲解

镜像是什么

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码,运行时、库、环境变量和配置文件。通俗的讲,就是讲所有的应用,直接打包docker镜像,就可以直接跑起来。

如何得到镜像:

  1. 从远程仓库下载
  2. 朋友拷贝给你
  3. 自己制作一个镜像 Dockerfile

Docker镜像加载原理

UnionFS(联合文件系统)

UnionFS(联合文件系统):Union文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同事可以将不同目录挂载到同一个虚拟文件系统下。Uion文件系统是Docker镜像的基础。镜像可以通过分层来进行集成,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同事加载多个文件系统。但从外面看起来,只能看到一个文件系统。联合加强在会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

通俗的讲,大家都学过git,git可以控制版本。我们每操作一次都会被记录下来。比如我们在上面安装了centos 这是第一层,然后我又安装了docker,这就是第二层。每一层都会被记录下来。我们最开始下载镜像的时候看到的一层层的就是这个。

假设我们有一个mysql,还有一个tomcat,都用到了linux系统的内核(假设centos),那么现在我的tomcat下载了centos,那我的mysql就不需要下载了。他们之间是共用的。直接拿过去就可以了。这就是联合文件系统。节省了内存空间。

Docker镜像加载原理

docker的镜像实际上是由一层一层的文件系统组成,这种层级的文件系统就是联合文件系统(UnionFS)

bootfs系统启动的时候需要引导加载,这一块基本是不变的。就是一个内核在加一个加载器。这样我们的系统就运行起来了。运行起来之后这个bootfs就不要了。也就是说。我们从黑屏到开机进入系统之间,我们就称之为加载,我们的系统运行起来了。这个加载是不是就可以不要了。这一部分是共用的。

rootfs在bootfs之上,包含典型的Linux系统中的/dev, /proc,/etc等标准目录和文件,rootfs就是各种不同操作系统的发行版,比如Ubuntu,CentOS等。所以为什么说我们的容器就是一个小型的虚拟机环境,就因为此。

对于一个精简的OS,rootfs可以很小,主需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host和kernel,自己值需要提供rootfs就可以了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以共用bootfs。

通俗的讲。我们的内核是共用的。也就是说每次安装容器的时候。我们不需要在安装内核。只需要安装rootfs这一部分就可以了。这个时候容器的内部就是命令这些。真正的内核用的还是主机的。这也是虚拟机和容器的最大区别,为什么虚拟机启动这么慢,是因为这个内核的启动慢。而容器不需要启动内核。用的是宿主机的内核。所以说虚拟机的分钟级别的,而容器的秒级别的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5fWBR5wk-1625704465875)(/Users/minato/myfile/Markdown文档辅助图/image-20210603222946578.png)]

如上图所示。底下那一层就是共用的,安装什么就往上面叠加什么。

理解:

所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加信的内容时,就会在当前镜像层之上,常见信的镜像层。举一个简单的例子,例如基于Ubuntu Linux 16.04创建一个信的镜像,这就是新镜像的第一层,如果再该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层,如果继续添加一个安全补丁,就会创建第三个镜像层。该镜像当前已经包含3个镜像层,如下图所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oUE1kj4V-1625704465876)(/Users/minato/myfile/Markdown文档辅助图/image-20210603225727654.png)]

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5RxEoAFR-1625704465877)(/Users/minato/myfile/Markdown文档辅助图/image-20210603230009181.png)]

上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件。这是因为最上层中7是文件5的一个更新版本。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hM6HGx03-1625704465877)(/Users/minato/myfile/Markdown文档辅助图/image-20210603230249532.png)]

如果再有一个镜像。这个镜像还是三层,如果第一层还是centos,mysql,tomcat。那么这层也可以直接拿过来应用。(老千层饼了。。。)

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

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

Docker在Windows上仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW[1]。下图展示了与系统现实相同的三层镜像,所有镜像层堆叠并合并,对外提供统一的视图。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WZAR1Hh0-1625704465878)(/Users/minato/myfile/Markdown文档辅助图/image-20210603230956927.png)]

特点:

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

这一层就是我们通常说的容器层,容器之下的都叫镜像层,镜像层是无法改变的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VqiNW3m9-1625704465878)(/Users/minato/myfile/Markdown文档辅助图/image-20210603231515461.png)]

镜像从pull到run的过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xW1CQknM-1625704465879)(/Users/minato/myfile/Markdown文档辅助图/image-20210603231919584.png)]

commit镜像

docker commit -a="提交人" -m="提交信息描述" 容器ID 容器命名:tag
  1. 启动一个tomcat镜像
  2. 发现这个默认的tomcat 是没有webapps应用的,镜像的原因,官方镜像默认webapps下没有文件!
  3. 我自己拷贝进去了基本的文件
  4. 讲我们操作过的容器通过commit提交为一个镜像!我们以后就使用我们修改过的镜像即可,这就是我们自己的一个修改的镜像!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kaytdd0f-1625704465880)(/Users/minato/myfile/Markdown文档辅助图/image-20210604112415262.png)]

原理:通过分层原理进行打包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-inxWxSnI-1625704465881)(/Users/minato/myfile/Markdown文档辅助图/image-20210604112736388.png)]

提交总结:

如果你 要保存当前容器的状态,就可以通过commit提交,获得一个镜像。

到了这里我们才算是入门了Docker

容器数据卷*********

什么是容器数据卷

docker的理念回顾:将应用和环境打包成一个镜像!运行之后就变成一个容器。如果数据都在容器中,那么我们删除容器,数据就会丢失 需求:数据持久化

举例:我们用docker跑了一个mysql,跑了一段时间之后我们把它给停了然后把mysql这个容器给删了,那就相当于这段时间的数据也被我们删了,这可就是真的删库跑路了。需求:mysql数据可以存储在本地

容器之间有一个数据共享技术!,Docker容器中产生的数据,同步到本地。这就是卷技术,说白了就是目录的挂载,价格我们容器内的目录,挂载到Linux上!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VQgujQJ8-1625704465882)(/Users/minato/myfile/Markdown文档辅助图/image-20210604171207423.png)]

总结:容器的持久化和同步操作!容器间也是可以数据共享的!

使用数据卷

方式一:直接使用命令挂载 -v

docker run -it -v 主机目录:容器那内目录 

# 测试
docker run -it -v /home/ceshi:/home centos /bin/bash
# 启动之后可以通过docker inspect 容器id查看

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LyS5DYbn-1625704465882)(/Users/minato/myfile/Markdown文档辅助图/image-20210604171924957.png)]

此时两个容器内的目录home和容器外的home/ceshi目录就是打通状态。可以理解为双向绑定

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lBkonEbk-1625704465883)(/Users/minato/myfile/Markdown文档辅助图/image-20210604184208905.png)]

反过来也是一样的。

  1. 停止容器
  2. 宿主机上修改文件
  3. 启动容器
  4. 容器内的数据依旧是同步的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-22ZiWcQy-1625704465884)(/Users/minato/myfile/Markdown文档辅助图/image-20210604184446681.png)]

好处:我以后修改只需要在本地修改即可,容器内会自动同步。

实战测试:安装MySQL

思考:MySQL的数据持久化的问题!

# 获取镜像
docker pull mysql:5.7
# 运行容器,需要做数据挂载!可以同时挂载多个目录
# 安装启动mysql的时候要注意,一定需要配置密码。
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
# 参数解释
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置(此次为配置mysql密码)
--name 容器命名

现在可以自己测试一下。在远程的数据库上创建一个库,然后到自己本地目录下看看是不是也有,再反之。同样的也可以讲远程mysql容器直接干掉。然后看看自己本地存储的数据是否会丢失(一定不会)。这就实现了我们容器的持久化技术,也就是我们的卷技术。

具名挂载和匿名挂载

# 匿名挂载
-v 直接写容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的 volume 的情况
docker volume ls
# 这里发现,这种就是匿名挂载,我们在 -v只写了容器内的路径,没有写容器外的路径。 

# 具名挂载
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
# 这里我们在-v后只指定了一个容器外的文件而不是目录

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LAkfKOs7-1625704465885)(/Users/minato/myfile/Markdown文档辅助图/image-20210604190936517.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZKrCBOwP-1625704465886)(/Users/minato/myfile/Markdown文档辅助图/image-20210604191253504.png)]

所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxxx/_data

我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用具名挂载

# 如何确定是具名挂载还是匿名挂载,还是指定路径挂载!
-v 容器内路径  # 匿名挂载
-v 卷名:容器内路径   # 具名挂载
-v /宿主机路径:容器内路径  # 指定路径挂载

拓展:

# 通过-v 容器内路径:ro  rw 改写读写权限
ro  readonly # 只读
rw  readwrite # 可读可写

# 一旦设置了容器权限  容器对我们挂载出来的内容就有限定了
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:/etc/nginx:ro nginx

docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:/etc/nginx:ro nginx
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作的

Dockerfile就是用来构建docker镜像的构建文件!就是一段命令脚本!先体验一下

通过这个脚本可以生成一个镜像,镜像是一层一层的,脚本就是一个一个的命令,每个命令都是一层。

# 创建一个dockerfile文件, 名字可以随意,看一Dockerfile
mkdir dockerfile
vim dockerfile
# 文件中的内容
FROM centos
VOLUME ["volume01", "volume02"]  # 可以挂载多个
CMD echo "----end----"           # 打印----end----
CMD /bin/bash                    # 
# 这里的每个命令就是镜像的一层

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mDm9Hnnu-1625704465887)(/Users/minato/myfile/Markdown文档辅助图/image-20210606185058864.png)]

# 启动一下自己写的容器
docker run -it 镜像id /bin/bash

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b2XfPIwV-1625704465888)(/Users/minato/myfile/Markdown文档辅助图/image-20210606185638997.png)]

这个卷和外部一定有一个同步的目录!通过docker inspect命令查看

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZvRyesro-1625704465888)(/Users/minato/myfile/Markdown文档辅助图/image-20210606185910228.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E8hZbuDC-1625704465889)(/Users/minato/myfile/Markdown文档辅助图/image-20210606190036039.png)]

通过刚刚的查看我们知道,我生成的镜像中的挂载是匿名挂载

测试一下在容器内建一个文件,容器外是否有改变(自测)

这种方式我们未来使用非常多,因为我们通常会构建自己的镜像!

假设构建镜像时候没有挂在卷,要手动镜像挂载 -v 卷名:容器内路径!

数据卷容器


多个mysql同步数据!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X4Nduu6X-1625704465889)(/Users/minato/myfile/Markdown文档辅助图/image-20210606190658563.png)]

# 启动3个容器,通过我们刚才自己写的镜像启动
docker run -it --name docker01 容器名:版本 
docker run -it --name docker02 --volumes-from docker01 容器名:版本

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DQdobEbC-1625704465890)(/Users/minato/myfile/Markdown文档辅助图/image-20210606190912518.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rovx63s1-1625704465890)(/Users/minato/myfile/Markdown文档辅助图/image-20210606191245788.png)]

然后我们在docker01容器中被挂载的目录里创建一个文件,然后到docker02容器中查看是否存在(自测)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AirVpPtc-1625704465891)(/Users/minato/myfile/Markdown文档辅助图/image-20210606192802180.png)]

在来个docker03,在docker03中创建一个文件docker03(自测去吧)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FhvnwVYx-1625704465892)(/Users/minato/myfile/Markdown文档辅助图/image-20210606193141996.png)]

然后我们在停止并删除docker01,查看docker02和docker03是否还可以访问这个文件,测试依旧可以访问

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AOWV721c-1625704465892)(/Users/minato/myfile/Markdown文档辅助图/image-20210606193441501.png)]

多个mysql实现数据共享

docker run -it -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

docker run -it -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volume-from mysql01 mysql:5.7
# 这个时候,可以实现两个容器数据同步

结论:

容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止(所有使用它的容器都停止为止),但是一但你持久化到了本地,这个时候,本地的数据是不会删除的!

DockerFile**************

Dockerfile就是用来构建docker镜像的构建文件!就是一段命参数令脚本!先体验一下

通过这个脚本可以生成一个镜像,镜像是一层一层的,脚本就是一个一个的命令,每个命令都是一层。

构建步骤:

  1. 编写一个dockerfile文件
  2. docker build 构建成为一个镜像
  3. docker run 运行镜像
  4. docker push 发布镜像(docker hub、阿里云镜像仓库!)

查看一下官方是怎么做的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3SyF41zi-1625704465893)(/Users/minato/myfile/Markdown文档辅助图/image-20210606194824465.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V1q4M3tA-1625704465893)(/Users/minato/myfile/Markdown文档辅助图/image-20210606194919023.png)]

很多官方镜像都是基础包,很多功能都没有,我们通常会自己搭建自己的镜像!

官方既然可以制作镜像,那我们也可以!

DockerFile构建过程


基础知识:

  1. 每个保留关键字(指令)都必须是大写字母
  2. 执行从上到下顺序执行
  3. #表示注释
  4. 每一个指令都会创建提交一个新的镜像层!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cB11urW7-1625704465894)(/Users/minato/myfile/Markdown文档辅助图/image-20210606195640545.png)]

dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!

Docker镜像逐渐成为企业交付的标准,必须要掌握

DockerFile:构建文件,定义了一切的步骤,源代码

DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品

Docker容器:容器就是镜像运行起来提供服务的

DockerFile指令:


以前我们都是使用别人的,现在我们知道了这些指令后,我们来练习自己写一个镜像!

FROM            # 基础镜像,一切从这里开始后构建
MAINTAINER      # 镜像是谁写的,姓名+邮箱
RUN             # 镜像构建的时候海需要运行的命令
ADD             # 步骤:tomcat镜像,这个tomcat的压缩包!添加内容
WORKDIR         # 镜像的工作目录
VOLUME          # 挂载的目录
EXPOSE          # 暴露端口配置  
CMD             # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT      # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD         # 当构建一个被继承 DockerFile的容器时,就会运行ONBUILD指令,出发指令。
COPY            # 类似ADD命令,将我们的文件拷贝到镜像中
ENV             # 构建的时候设置光环境变量!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4suFiCil-1625704465894)(/Users/minato/myfile/Markdown文档辅助图/image-20210606200203704.png)]

实战测试


Docker Hub中99%的镜像都是从这个基础镜像过来的 FEOM scratch,然后配置需要的软件和配置来进行构建的!!!

官方的centos镜像很多基础的命令都没有,比如ll,vim等。镜像都是被压缩过的!我们要自己做一个centos镜像来添加这个命令

# 首先创建dockerfile的文件,名字随意
自己创建(略)
# vim打开这个文件
自己打(略)
# 进入文件之后
FROM centos                            # 基础镜像
MAINTAINER minato<taizi911203@126.com> # 作者
ENV MYPATH /usr/local                  # 我自己进去的目录是哪
WORKDIR $MYPATH                        # 工作目录,$是取地址,这里我们将工作目录指定到了我们刚刚指定的MYPATH上
RUN yum -y insgall vim                 # 构建镜像时安装cim命令
run yum -y install net-tools           # 这个是ifconfig的命令
EXPOSE 80                              # 默认暴露端口80
CMD echo $MYPATH                       # 输出这个地址
CMD echo "----end----"                 # 输出这句话
CMD /bin/bash                          # 启动后进入哪个命令行
# 构建镜像
docker build -f dockerfile文件路径 -t 镜像名:版本号 . # 一定注意后面这个点 .
# 运行我们自己写的centos
# 尝试运行我们添加的命令,如vim等

对比:原来的centos

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gFPNAALu-1625704465895)(/Users/minato/myfile/Markdown文档辅助图/image-20210606203914294.png)]

我们自己写的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e5S2i3s9-1625704465895)(/Users/minato/myfile/Markdown文档辅助图/image-20210606204020102.png)]

我们可以列出镜像变更的历史

docker history 容器ID

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HV8paqNE-1625704465896)(/Users/minato/myfile/Markdown文档辅助图/image-20210606204221577.png)]

我们平时拿到一个镜像,可以研究一下它是怎么做的了!

CMD 和ENTRYPOINT的区别

CMD添加的命令 比如我添加一个ls -a,添加完了之后。我docker run这个容器他就会执行这个ls -a打印我们当前目录下的所有内容。但是如果我执行docker run的时候 我突然想在加一个-l。也就是说我想最终执行的命令是ls -al。你会发现它会报错,这就是我在运行docker run -l的时候这个-l替换掉了原本的ls -a。而ENTRYPOINT就不会。如果我们构建镜像的时候是用ENTRYPOINT添加的命令。那么在运行容器是添加了一个-l参数,它最终执行的就会是 ls -al

发布自己的镜像


Docker Hub

  1. 在https://hub.docker.com/ 注册自己的账号
  2. 确定这个账号可以登录
  3. 在我们服务器上登录自己的账号
docker login -u 账号
# 回车后输入密码

  1. 登录完毕后就可以提交镜像了,就是一步, docker push
docker push minato/tomcat:1.0  # 带上作者名和版本号
# ***自己平时构建的镜像一定也要带上版本号,不然无法提交到仓库

发布到阿里云服务上

  1. 登录阿里云
  2. 找到容器机构箱服务
  3. 创建命名空间
  4. 创建容器镜像

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nBXoMPKX-1625704465896)(/Users/minato/myfile/Markdown文档辅助图/image-20210607163757945.png)]

自己看吧,人家写得很清楚了

Docker所有流程小结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4Dd5ojsN-1625704465897)(/Users/minato/myfile/Markdown文档辅助图/image-20210607164241917.png)]

Docker 网络*********

理解Docker0

清空所有环境

docker rmi -f(docker images -aq)

测试

id addr # 或者当前的ip地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qvO6tolV-1625704465898)(/Users/minato/myfile/Markdown文档辅助图/image-20210607170441774.png)]

三个网络

问题:docker是如何处理容器网络访问的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f3qfdGwD-1625704465898)(/Users/minato/myfile/Markdown文档辅助图/image-20210607170541694.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kEoj7dBf-1625704465899)(/Users/minato/myfile/Markdown文档辅助图/image-20210607170958632.png)]

查看容器内部网络 ip addr,发现容器启动的时候会得到一个eth0@if262这样的地址,docker分配的

思考:主机能不能ping这个地址

外部主机是可以ping通容器内部的

思考:主机可以ping通任何容器内的地址。那么容器之间是否能ping通其他容器呢?

原理

我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0(桥接模式),使用的技术是veth-pair技术

启动一个容器后再次测试ip addr,发现又多了一对网卡

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lmRy2s4e-1625704465899)(/Users/minato/myfile/Markdown文档辅助图/image-20210607171551269.png)]

我们发现它的地址和容器内部的地址惊人的相似。261,262

我们每启动一个容器,都会多一对网卡(容器内和容器外),这种一对一对的就是用了veth-pair技术

veth-pair技术

就是一对的虚拟设备借口,他们就是成对出现的,一端连着协议,一端彼此相连,正因为有这个特性,veth-pair充当一个桥梁,连接各种虚拟网络设备的。

openstac,Docker容器之间的连接,ovs的连接,都是使用veth-pair技术

所以同一宿主机下的容器与容器之间是可以ping通的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VUCeD7pf-1625704465900)(/Users/minato/myfile/Markdown文档辅助图/image-20210607184555999.png)]

总结:tomcat01和tomcat02是公用一个路由的,docker0.

所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用ip

Docker使用的是linux的桥接,宿主机是Docker容器的网桥docker0。如果不指定网络,docker就会自动往这里分配,大约65535个

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mKLj5PdG-1625704465900)(/Users/minato/myfile/Markdown文档辅助图/image-20210607185456519.png)]

Docker中的所有网络借口都是虚拟的,虚拟的转发效率高。

只要容器删除,对应的网桥一对就没了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5W5ZlEmH-1625704465901)(/Users/minato/myfile/Markdown文档辅助图/image-20210607191231529.png)]

思考一个问题,我们每一次启动一个容器,它的网段都会改变,因为是随机的,比如我这次启动了一个mysql,停止了之后我再次启动,它的ip就会改变。那我们随之的配置是不是也要改变。那我们在跑起来一个容器的时候不是给容器命了名吗,我们能不能用这个名字ping通这个容器,如果可以,那就代表这个mysql即使崩了重启导致ip改变了也没事。我们想做到的就是项目不重启,数据库ip换了,我们希望恶意处理这个问题,可以通过名字来进行访问。

容器互联–link

我们现在启动连个容器mysql01和mysql02,尝试着用mysql01 ping mysql02,发现是ping不通的。那如何可以解决呢?

那我们在启动一个mysql03

docker run -d -P --name mysql03 --link mysql02 mysql
# 然后我们再尝试用mysql03 ping mysql02
docker exec -it mysql03 ping mysql02

这次发现可以ping通了

但是如果我们用mysql02 去ping mysql03是不能ping通的,那怎么办?

# 我们可以通过docker network inspect 容器id 来查看网络详情

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mi5XVBGo-1625704465901)(/Users/minato/myfile/Markdown文档辅助图/image-20210607191334177.png)]

我们可以直接通过查看配置文件,/etc/host,这个文件就是配置本地绑定的,比如我们在这个下面绑定了百度,那么以后我们以后输入百度就会直接访问我们绑定的地址。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DyeSiL9M-1625704465902)(/Users/minato/myfile/Markdown文档辅助图/image-20210607193128699.png)]

这就是根本原因,我们访问mysql03的时候,相当于直接访问了mysql02,所以他们是可以ping通的

本质本就:–link就是我们在hosts配置中增加了另一个容器的绑定,但是另一个容器却没有绑定这个容器,所以才是单项连接。

我们现在玩docker已经不建议使用–link了!我们需要的是自定义网络。不想使用这个docker0.因为官方的这个docker0是局限的。它不支持容器名连接访问!

自定义网络

网络模式:

  1. bridge:桥接(默认,自己创建也使用桥接模式) docker搭桥 0.1 0.2 0.3
  2. none: 不配置网络
  3. host: 和宿主机共享网络
  4. container : 容器内网络连通(用的少)

测试

# 我们直接启动的命令 默认都有一个 --net bridge操作,而这个就是我们的docker0
docker run -d -P --name tomcat01
docker run -d -P --name tomcat01 --net bridge tomcat
# docekr特点:默认,域名不能访问, --link可以打通连接
# 我们可以自定义一个网络
docker network create --driver bridge -subnet 192.168.0.0/16 -gateway192.168.0.1 mynet
# 参数说明
--dirver # 指明我们要创建一个网络
bridge   # 连接模式:桥接
--subnet # 子网(/16代表我可以创建65535个,如果是/24就说明只能创建255个)
--gatway # 网关
myney    # 我们创建的这个网络名

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M7u9flv0-1625704465902)(/Users/minato/myfile/Markdown文档辅助图/image-20210607194802343.png)]

前面自己的一个网络就创建好了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ek8JruqP-1625704465903)(/Users/minato/myfile/Markdown文档辅助图/image-20210607194958933.png)]

docker run -d -P --name tomcat-net-01 --net mynet tomcat
docker run -d -P --name tomcat-net-02 --net mynet tomcat

此时我们在去尝试两个容器互ping,发现是可以互通的。也就是说我们自定义的这个网络修复了docker0的不可互通的缺点。

我们自定义的网络,docker都已经帮我们维护好了关系,推荐我们平时使用自定义网络。

好处:不同的集群使用不同的网络,宝恒集群是安全和健康的。

比如我有一个redis集群和一个mysql集群。每个集群都有各自的网络,各自是互通的。但是对外确实隔离的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QGZDJ369-1625704465903)(/Users/minato/myfile/Markdown文档辅助图/image-20210607195702660.png)]

网络连通

我们现在在我们自定义的mynet网络上连了两个容器tomcat-net-01、tomcat-net-02,那此时,我们在把docker0上也加两个容器tomcat01和tomcat02,那么,tomcat01是一定无法ping通tomcat-net-01的。而且我们还不能直接将这两个容器直接连通,因为网络性质就变了,那怎么办?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cTw5C6ri-1625704465904)(/Users/minato/myfile/Markdown文档辅助图/image-20210607200132762.png)]

上图命令就可以将一个容器连接到一个网络上

# 测试 打通tomcat01 =》mynet
docker network connect mynet tomcat01
# 查看mynet的网络详情
docker network inspect mynet
# 连通之后就是讲tomcat01 放到了mynet网络下
# 一个容器两个ip地址,好比阿里云,公网ip,私网ip。一个道理。就是这么暴力

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D0sOsV13-1625704465904)(/Users/minato/myfile/Markdown文档辅助图/image-20210607200728848.png)]

结论:结社要跨网络曹旭哦别人买酒需要使用docker network connect连通

实战:部署Redis集群。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zmp4LU2y-1625704465905)(/Users/minato/myfile/Markdown文档辅助图/image-20210607201422513.png)]

# 先建一个redis集群的网卡
docker network create redis --subnet 172.38.0.0/16

用脚本一次性创建6个redis配置文件

for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/mode-${port}/conf/redis.conf
cat <<EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4voBvMJV-1625704465905)(/Users/minato/myfile/Markdown文档辅助图/image-20210607201910025.png)]

分别启动这几个redis,记得改变名称跟ip

docker run -p 6371:6379 -p 16371:16379 --name redis-1\
-v /mydaya/redis/node-1/data:/data \
-v /mydaya/redis/node-1/conf/redis.conf:/ect/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /ect.redis/redis.conf

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I0eBMCDn-1625704465906)(/Users/minato/myfile/Markdown文档辅助图/image-20210607203249164.png)]

随便进入一个redis

docker exec -it redis-1 /bin/sh # 切记redis下是没有bash的,是sh,其实都一样
redis -cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
# 接下来会问你是否要这么配置,选yes就可以了

连接集群

redis-cli -c   # 一定要加-c  不然是单机不是集群
cluster info   # 查看集群
cluster nodes  # 查看节点

然后我们就可以完集群了。首先要试一下redis集群的高可用

我们随便set 一个值看看集群给我们分配在了那个redis上。因为我们没有设置分片,所以都会是主机。然后我们在停掉这台主机,看看还能否get到这个值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nziih9sC-1625704465906)(/Users/minato/myfile/Markdown文档辅助图/image-20210607204249812.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D9NSYAc9-1625704465907)(/Users/minato/myfile/Markdown文档辅助图/image-20210607204318548.png)]

Docker小结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值