开篇提要
学习文档:docker官网
环境:
Centos8.0
学习:
docker基础我主要是根据b站上面狂神视频(狂神b站视频地址)进行学习,该笔记是跟着其学习自己做的笔记,我也将该笔记的文档以及最后搭建的一个简易微服务上传到了我的码云,欢迎大家来踩(码云地址)
Docker的出现
在传统的开发模式中,开发人员完成项目之后,将项目达成一个jar或者一个war包,之后交由运维人员,并告知运维人员所使用的MySQL、Redis等的应用环境以及对应的版本信息,由运维人员进行相应的部署,这样操作造成的问题很明显:
- 运维人员部署项目的时候需要首先部署大量的开发环境
- 在不同的环境下,运维人员都需要进行重复性的部署环境操作
所以,Docker应运而生,docker可以将开发人员完成的项目打成一个镜像(image),该镜像中会包含该项目中使用的项目所有的环境信息,从而极大减轻运维人员的工作量,且开发人员可以将开发部署上线一条龙进行服务。
名词概念
镜像(image):相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
容器(container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
仓库(repository):仓库可看成一个代码控制中心,用来保存镜像。
安装
按照以下文档提示进行相应的安装
其中在设置仓库的时候,docker默认使用的是https://download.docker.com/linux/centos/docker-ce.repo,可将其修改为阿里云仓库,方便加速:http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
配置阿里云镜像加速
在镜像加速服务中进行相应的设置:
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["阿里云中自己显示的地址"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
常用命令
帮助命令
docker version #查看版本信息
docker info #查看docker有关的信息,包括镜像数量等
docker 命令 --help
镜像命令
查看
#查看镜像
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 6 months ago 13.3kB
#查看所有的镜像
# docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 6 months ago 13.3kB
#查看所有镜像的ID
# docker images -q
d1165f221234
查询
#查询镜像
[root@localhost ~]# docker search mysql
#查询所有镜像的前几条
[root@localhost ~]# docker search mysql --limit 2
#查询超过点击率大于N的镜像
[root@localhost ~]# docker search mysql --filter STARS=3000
下载
#拉取镜像
[root@localhost ~]# docker pull mysql
#拉取指定版本的镜像,该版本需要在dockerHub中存在
[root@localhost ~]# docker pull mysql [:tag]
删除
#根据镜像的ID对镜像进行删除
[root@localhost ~]# docker rmi 1d7aba917169
#删除全部的镜像,注意:当还在运行的镜像是不能进行删除的,如果需要删除,可以进行强制删除(-f)
[root@localhost ~]# docker rmi $(docker images -aq)
容器命令
主要的参数
docker run [可选参数] image
--name 名称 #为新创建的容器起一个名称
-d #以后台的方式运行
-it #以交互式的方式运行容器
-P #指定端口
-p #随即指定一个端口
交互式运行一个容器
docker run --name myCentos -it 300e315adb2f #此方式会直接进入容器内部
查看
docker ps #查看正在运行的容器
docker ps -a #查看所有运行过的容器,包括此时正在运行的容器
退出容器
exit #该方式容器会关闭并退出
也可以采用CTRL + P + Q退出容器,该种方式容器依旧会运行,退出之后想再进入容器内部可以使用:
docker attach 容器ID
删除容器
#删除指定的容器ID
docker rm 容器ID
#删除所有的容器(包括正在运行的)
docker rm -f $(docker ps -aq)
容器相关的系统命令
#开启一个容器
docker start containerID
#停止一个容器
docker stop containerID
#重启一个容器
docker restart containerID
#kill一个容器
docker kill containerID
常用命令
日志查看
#可选参数
-f #始终保持日志窗口打开
-t #带有时间戳
-n #只展示最近的几条日志
docker logs 容器ID
进程查看
docker top 容器ID
查看容器元数据
#使用的命令为 docker inspect 容器ID
[root@localhost ~]# docker inspect 2bb757896428
[
{
"Id": "2bb75789642827ee9bfe9aa749b881a7ac940f3fd7e764c8fafe768be5cf6508",
"Created": "2021-09-05T14:57:15.340037949Z",
"Path": "catalina.sh",
"Args": [
"run"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 1163699,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-09-05T14:57:17.045678108Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:ab1f0e1bb1a1ccf9f15097484ae4389253c0378ef1883b28d9d7849db10c7481",
"ResolvConfPath": "/var/lib/docker/containers/2bb75789642827ee9bfe9aa749b881a7ac940f3fd7e764c8fafe768be5cf6508/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/2bb75789642827ee9bfe9aa749b881a7ac940f3fd7e764c8fafe768be5cf6508/hostname",
"HostsPath": "/var/lib/docker/containers/2bb75789642827ee9bfe9aa749b881a7ac940f3fd7e764c8fafe768be5cf6508/hosts",
"LogPath": "/var/lib/docker/containers/2bb75789642827ee9bfe9aa749b881a7ac940f3fd7e764c8fafe768be5cf6508/2bb75789642827ee9bfe9aa749b881a7ac940f3fd7e764c8fafe768be5cf6508-json.log",
"Name": "/cranky_diffie",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {
"8080/tcp": [
{
"HostIp": "",
"HostPort": "8080"
}
]
},
"RestartPolicy": {
"Name": "no",
"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/a780240082fa6a70c41a2ce4b5223d5c0ea94fc30cb6602f120a83be1b619269-init/diff:/var/lib/docker/overlay2/ad33995b801cf6d7d35c26072c726e2b70f2154632acebe646ab3d9d5ced3ffd/diff:/var/lib/docker/overlay2/43070c1cf8808ff998315206f50b4129afeacb4559df8aeb0e49a1e09aa712d0/diff:/var/lib/docker/overlay2/895dfe0a19d95be47a2b1f4cb738bed63dbe607bb34f1519d5c10ab9910b2129/diff:/var/lib/docker/overlay2/02a64752068b88bbb647138ea652b2fd31e67044f438ff8fbd75a5966732d240/diff:/var/lib/docker/overlay2/535ee71ad5ed485b141cfabf5d32d713f7fc0847f4f5b609293f902254829b04/diff:/var/lib/docker/overlay2/6ffa718dcd68fcbe3505a2f0f80130e0f4f7b4afdbbe835eca1d2fa2d8fa0673/diff:/var/lib/docker/overlay2/6d776bbd288b2599edacaad9f717794d781c6500031c66cab8583c954f1aa31d/diff:/var/lib/docker/overlay2/dda3f5d538e6ba9556a29a646597daaf8a8485fc2c74569000299fd1711d85be/diff:/var/lib/docker/overlay2/c4707451c0a47beb3a958d40bd2c4e767583b5aa9e3c63e6acbe015ea03e53cb/diff:/var/lib/docker/overlay2/d07b4c0249359a2a9bc5285a89f9cc520a23448698f8fa9a735c0d618ba09c05/diff",
"MergedDir": "/var/lib/docker/overlay2/a780240082fa6a70c41a2ce4b5223d5c0ea94fc30cb6602f120a83be1b619269/merged",
"UpperDir": "/var/lib/docker/overlay2/a780240082fa6a70c41a2ce4b5223d5c0ea94fc30cb6602f120a83be1b619269/diff",
"WorkDir": "/var/lib/docker/overlay2/a780240082fa6a70c41a2ce4b5223d5c0ea94fc30cb6602f120a83be1b619269/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "2bb757896428",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"8080/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/tomcat/bin:/usr/local/openjdk-11/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"JAVA_HOME=/usr/local/openjdk-11",
"LANG=C.UTF-8",
"JAVA_VERSION=11.0.12",
"CATALINA_HOME=/usr/local/tomcat",
"TOMCAT_NATIVE_LIBDIR=/usr/local/tomcat/native-jni-lib",
"LD_LIBRARY_PATH=/usr/local/tomcat/native-jni-lib",
"GPG_KEYS=A9C5DF4D22E99998D9875A5110C01C5A2F6059E7",
"TOMCAT_MAJOR=10",
"TOMCAT_VERSION=10.0.10",
"TOMCAT_SHA512=3f6d5d292ab67348b3134c1013044c948caf5a4bf142b4e856b5ee63693a6e80994b0b4dbb3404d0fd3542fd6f7f52b4cbe404fc5a0f716ac98d68db879b7112"
],
"Cmd": [
"catalina.sh",
"run"
],
"Image": "tomcat",
"Volumes": null,
"WorkingDir": "/usr/local/tomcat",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "0ab63ff0e4444936dd872b0fb6e3cc9345a70af1b1974359c2a5f4e975177a53",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"8080/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "8080"
},
{
"HostIp": "::",
"HostPort": "8080"
}
]
},
"SandboxKey": "/var/run/docker/netns/0ab63ff0e444",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "4a83ab1a7f70a31a9155bcdca9248825cfd093e94abdaf4fccfa86e2e3faed4f",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:03",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "b107c6ec6f14bed015f3a5a79c48372b88aa29b798fd9bf0d08ce7e320aaa3c5",
"EndpointID": "4a83ab1a7f70a31a9155bcdca9248825cfd093e94abdaf4fccfa86e2e3faed4f",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:03",
"DriverOpts": null
}
}
}
}
]
复制文件
该复制文件的过程是将容器内部的文件复制到宿主机上
docker cp 容器ID:fileName 宿主机address
安装portainer
介绍
Portainer 是一个开源、轻量级Docker管理用户界面,基于Docker API,提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和操作、登录用户管理和控制等功能。功能十分全面,基本能满足中小型单位对容器管理的全部需求。
其功能与Rancher一致
安装
docker pull portainer/portainer
docker run -d -p 9000:9000 -v /root/portainer:/data -v /var/run/docker.sock:/var/run/docker.sock --name dev-portainer portainer/portainer
参数说明:
-d #容器在后台运行
-p 9000:9000 # 宿主机9000端口映射容器中的9000端口
-v /var/run/docker.sock:/var/run/docker.sock # 把宿主机的Docker守护进程(docker daemon)默认监听的Unix域套接字挂载到容器中
-v /root/portainer:/data # 把宿主机目录 /root/portainer 挂载到容器 /data 目录;
–name dev-portainer # 指定运行容器的名称
注意: 在启动容器时必须挂载本地 /var/run/docker.socker与容器内的/var/run/docker.socker连接。
安装tomcat
与其他镜像安装的过程基本一致,需要注意webapps文件中是空的,而对应的localhost:8080文件是存储在webapps.disk文件中的。
Docker镜像
镜像是什么
镜像是一个轻量级的、可执行的独立软件包,包括代码、运行时库、环境变量和配置文件
特点
Docker镜像都是可读的,当容器启动的时候,一个新的可写的层会加载到镜像的顶部
这一层就是我们所说的容器层,容器层底下的统称为镜像层
Docker镜像加载原理
联合文件系统(UnionFS)
UnionFS是一种轻量级的、分层并且高性能的文件系统,他支持对文件的每一次提交(commit)来一层一层的提交,同时可以将不同目录挂载到同一个虚拟文件系统目录下。UnionFS是Docker镜像的基础。镜像可以通过分层来实现继承,基于基础镜像(没有父镜像),可以制作各种镜像。
特性:一次同时加载多个文件系统,但是从外面看来,只能看到一个文件系统,联合加载会把各类文件系统叠加到一起,这样最终的文件系统会包含所有的文件系统
加载原理
bootfs:主要是包含内核和引导加载
rootfs:主要是具体的镜像文件
Docker的Commit操作
基于上述的了解,可以将从remote仓库中pull拉取的镜像,经过自己的提交使其成为需要的images,之后,便可以直接运行经过自己提交的images
docker commit [-m="message" -a="author"] containerID [imageName:tag]
imageName:需要的是均为小写。。。。。
Docker的数据卷
来源:
假如我们使用Docker安装了Mysql数据库,当我们run之后,并且成功的create the database,但是由于误操作,将该container删除,则会造成数据的丢失,传说中的删库跑路?
解决方案:
将容器中的某个目录与宿主机上的某个目录实现挂载,即当container中的该文件存在数据的时候,宿主机上同时会有数据,而宿主机上有数据的时候,container中同时会具有数据,效果类似于实现两个目录对数据的双向绑定
实现:
docker run [-p 宿主机port:containerPort] -v 宿主机目录:container目录 imageID
运行inspect之后,可以发现挂载的具体信息
"Mounts": [
{
"Type": "bind",
"Source": "/root/桌面/test",
"Destination": "/home",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
数据卷挂载
数据卷名称统一存放于 /var/lib/docker/volumes 目录下面
挂载的几种方式:
- 指定目录挂载
- 匿名挂载
- 具名挂载
- Dockerfile实现挂载
以下对其分别进行说明
指定目录挂载
与Dokcer数据卷中的实现方式保持一致,需要在宿主机上指定一个目录与container中的目录实现类似于双向绑定的关系
匿名挂载
可以不指定数据卷的名称,直接指定container内的目录,在宿主机上 /var/lib/docker/volumes/ 目录下面会随机生成一个随机值
#匿名挂载的实现
docker run -v /home centos
#可以通过以下命令进行查看
docker volume ls
DRIVER VOLUME NAME
local 0dd4e77a9cab609f9edc04ae6a6445a95d12a98d5b8293911cfc658be56d90ca
具名挂载
指定具体的数据卷名称,直接指定container内的目录
#具名挂载的实现
docker run -v myvolume:/home centos
#查看
docker volume ls
DRIVER VOLUME NAME
local 0dd4e77a9cab609f9edc04ae6a6445a95d12a98d5b8293911cfc658be56d90ca
local aa8481d45e2fcc59fa1933e9aeb67d7d2170dcaa484c273c3be8684b2c9956b7
local myvolume
Dockerfile挂载
可具体查看Docker章节
Dockerfile
什么是 Dockerfile?
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
Dockerfile命令
CMD与ENTRYPOINT的区别
CMD #指定这个容器要启动时执行的命令,只有最后一个命令会生效,对Dockerfile中的CMD命令会进行替代、覆盖
ENTRYPOINT #指定这个容器要启动时执行的命令,对Dockerfile文件中的ENTRYPOINT命令进行追加
验证
CMD命令的Dockerfile
FROM centos
CMD ["ls","-a"]
ENTRYPOINT命令的Dockerfile
FROM centos
ENTRYPOINT ["ls","-a"]
同时启动以下命令:
docker run imageId -l
CMD构建的容器报错:因为Dockerfile文件中的CMD命令已被覆盖,-l命令不存在
Error response from daemon: conflict: unable to delete a6eb71706a47 (must be forced) - image is being used by stopped container c10aeb8dec80
ENTRYPOINT启动容器结果如下:
total 0
drwxr-xr-x. 1 root root 6 Sep 11 08:43 .
drwxr-xr-x. 1 root root 6 Sep 11 08:43 ..
-rwxr-xr-x. 1 root root 0 Sep 11 08:43 .dockerenv
lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x. 5 root root 340 Sep 11 08:43 dev
drwxr-xr-x. 1 root root 66 Sep 11 08:43 etc
drwxr-xr-x. 2 root root 6 Nov 3 2020 home
lrwxrwxrwx. 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx. 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------. 2 root root 6 Dec 4 2020 lost+found
drwxr-xr-x. 2 root root 6 Nov 3 2020 media
drwxr-xr-x. 2 root root 6 Nov 3 2020 mnt
drwxr-xr-x. 2 root root 6 Nov 3 2020 opt
dr-xr-xr-x. 269 root root 0 Sep 11 08:43 proc
dr-xr-x---. 2 root root 162 Dec 4 2020 root
drwxr-xr-x. 11 root root 163 Dec 4 2020 run
lrwxrwxrwx. 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x. 2 root root 6 Nov 3 2020 srv
dr-xr-xr-x. 13 root root 0 Sep 11 07:42 sys
drwxrwxrwt. 7 root root 145 Dec 4 2020 tmp
drwxr-xr-x. 12 root root 144 Dec 4 2020 usr
drwxr-xr-x. 20 root root 262 Dec 4 2020 var ``
实例
自己构建一个centos,在该centos镜像中安装vim命令,挂载数据卷,指定工作目录为/home,以/bin/bash进入
#基础镜像
FROM centos
#作者信息
MAINTAINER xzy<2315643546@qq.com>
#工作目录
WORKDIR /home
#挂载目录
VOLUME ["volume1","volume2"]
#安装vim命令
RUN yum install -y vim
#结束命令
CMD echo "==========end============="
#以各种方式进入后台
CMD "/bin/bash"
安装完成后,进入容器
#进入容器默认目录/home
#在根目录中存在挂载的目录“volume1”,“volume2”
[root@localhost dockerfile]# docker run -it mycentos:1.0
[root@3c2bb1a182e3 home]# cd ..
[root@3c2bb1a182e3 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var volume1 volume2
[root@3c2bb1a182e3 /]# exit
对于docker build命令执行的时候,最后的“.”号的作用是:
指定构建镜像的上下文环境
看到网上的一篇文章对其进行了详细的解释,如下:
https://blog.csdn.net/whatday/article/details/105135763
发布镜像到DockerHub
步骤跟git的命令一样
都是直接采用push命令即可(前提需要登录进去DockerHub)
Docker网络
原理:
我们在宿主机上安装并启动一个Dokcer的时候,就会有一个网卡docker0,当我们每启动一个docker容器的时候,docker便会给docker容器分配一个IP,使用的技术是evth-pair技术!
Docker0网卡
[root@localhost ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:dd:25:b9 brd ff:ff:ff:ff:ff:ff
inet 192.168.65.128/24 brd 192.168.65.255 scope global dynamic noprefixroute ens33
valid_lft 1499sec preferred_lft 1499sec
inet6 fe80::20c:29ff:fedd:25b9/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether 52:54:00:7d:91:e6 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000
link/ether 52:54:00:7d:91:e6 brd ff:ff:ff:ff:ff:ff
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:ca:06:c3:07 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
可以看到:
- lo:本机回环地址:127.0.0.1
- ens33:本机地址:192.168.65.128
- docker0:docker0网卡:172.17.0.1
evth-pair
分别启动两个nginx:
docker run -it -P --name nginx01 nginx
docker run -it -P --name nginx02 nginx
#再次查看地址:
[root@localhost ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:dd:25:b9 brd ff:ff:ff:ff:ff:ff
inet 192.168.65.128/24 brd 192.168.65.255 scope global dynamic noprefixroute ens33
valid_lft 1279sec preferred_lft 1279sec
inet6 fe80::20c:29ff:fedd:25b9/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether 52:54:00:7d:91:e6 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000
link/ether 52:54:00:7d:91:e6 brd ff:ff:ff:ff:ff:ff
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ca:06:c3:07 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:caff:fe06:c307/64 scope link
valid_lft forever preferred_lft forever
11: veth9110d38@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 7a:39:e3:2f:76:c3 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::7839:e3ff:fe2f:76c3/64 scope link
valid_lft forever preferred_lft forever
13: veth31a4c6c@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether ba:60:d2:c9:82:d8 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::b860:d2ff:fec9:82d8/64 scope link
valid_lft forever preferred_lft forever
我们可以看到地址会出现两个ip,其中,每个IP都是成对出现,即evth-pair技术,其一端连接container,一端连接docker0网卡,通过协议实现互联,其实现原理如下:
https://processon.com/diagraming/613d669e6376896280e78585
分析
其中nginx01是可以直接和docker0连接的,也是直接可以ping的通的,niginx02一样的道理
但是nginx01与nginx两个容器之间ping是通过docker0来实现的
自定义网络
为什么要自定义网络?
因为容器之间想进行链接的话,只能通过ip来进行连接,会比较麻烦,当然也是可以通过**–link**,来进行连接,但是随着容器越来越多,则需要进行配置的越来越多,所以,出现了自定义网络。
利用自定义网络,我们可以实现不需要通过ip进行容器间的互联而是可以直接通过微服务名称进行连接。
步骤如下:
- 自定义网络
- 将容器加入到自定义的网络之中
自定义网络
#自定义创建网络
[root@localhost ~]# docker network create mynet --gateway 134.12.0.1 --subnet 134.12.0.0/16
4c4c019ca1554914682048c00f7c4c32be68d7495bb252751164dffab8f98e45
#查看所有的网络
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
f2b50feeaf24 bridge bridge local
63208561388f host host local
4c4c019ca155 mynet bridge local
53e036e6aed5 none null local
创建网络的几点说明:
subnet:子网掩码:/16,表示16位前16为属于同一网关,则该网段内还剩下256*256-2
将容器加入到网络中
#将tomcat01加入到mynet网络中
[root@localhost ~]# docker run -P -itd --name tomcat01 --network mynet tomcat
ca7c5d1e6c87b698a3c05e382758b96955e86e586cde9a7e71376557b3eef685
#将tomcat02加入到mynet网络中
[root@localhost ~]# docker run -P -itd --name tomcat02 --network mynet tomcat
7e1b3b0cc2f3857cee79ac2e40d53cff7f78cf4843ce4bb50436d22fdfd6f96c
#测试是否可以ping通
[root@localhost ~]# docker exec -it tomcat01 ping tomcat02
补充
如果对于docker0中的container与mynet中的container想要实现互联的话,需要使用docker network connet命令,实现容器与network的互联,暂不做展示
SpringBoot微服务打包镜像
使用Dockerfile打包一个简易的镜像
步骤如下:
- 创建一个简单的SpringBoot项目
- 创建一个接口,方便测试
package com.example.hello_boot.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello Docker!!!";
}
}
- 编写Dockerfile
#java环境基于java11
FROM openjdk:11
#作者信息
MAINTAINER xuzhenyang<2315643546@qq.com>
#jar包信息
COPY *.jar /hello_boot.jar
#暴露端口
EXPOSE 9000
#打包信息
CMD ["java","-jar","./hello_boot.jar"]
- 将该SpringBoot微服务项目生成一个jar包(利用package)
- 将该jar包与Dockerfile上传至服务器
- 打包镜像
docker build -f Dockerfile -t hello_boot:1.0 .
- 运行容器
docker run -d -p 9000:9000 --name hello_boot hello_boot:1.0
- 测试
curl localhost:9000/hello
SpringBoot微服务打包镜像
使用Dockerfile打包一个简易的镜像
步骤如下:
- 创建一个简单的SpringBoot项目
- 创建一个接口,方便测试
package com.example.hello_boot.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello Docker!!!";
}
}
- 编写Dockerfile
#java环境基于java11
FROM openjdk:11
#作者信息
MAINTAINER xuzhenyang<2315643546@qq.com>
#jar包信息
COPY *.jar /hello_boot.jar
#暴露端口
EXPOSE 9000
#打包信息
CMD ["java","-jar","./hello_boot.jar"]
- 将该SpringBoot微服务项目生成一个jar包(利用package)
- 将该jar包与Dockerfile上传至服务器
- 打包镜像
docker build -f Dockerfile -t hello_boot:1.0 .
- 运行容器
docker run -d -p 9000:9000 --name hello_boot hello_boot:1.0
- 测试
curl localhost:9000/hello