备注:
学习内容资源来源于狂神说:https://www.bilibili.com/video/BV1og4y1q7M4
docker是一个应用容器,可以将应用打包发布到一个可以移植的镜像当中。
采用沙箱机制
docker、k8s都是go语言开发的
1. 安装
1.1 centos 安装
# 1、移除旧版本
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 2、设置镜像仓库
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新软件包缓存索引
yum makecache fast
#3、安装
# ce是社区版, ee是企业版
yum install docker-ce docker-ce-cli containerd.io
#4、启动docker
systemctl start docker
# 5、查看版本
docker version
# 若提示无权限
[xuyaohua@localhost ~]$ docker ps
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json: dial unix /var/run/docker.sock: connect: permission denied
[xuyaohua@localhost ~]$ sudo chmod a+rw /var/run/docker.sock
1.2 阿里云镜像加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://epyzwowj.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
1.3 底层原理
docker是一个client-server结构的系统,docker守护进程运行在主机上,然后通过socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。
容器,是一个运行时的环境,就是我们说的集装箱。
为什么docker比虚拟机vm快?
1)、docker有着比虚拟机更少的抽象层。
由于docker不需要hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的是实际物理机的硬件资源。因此在cpu、内存利用率上docker将会在效率上有明显的而优势;
2)、docker利用的是宿主机的内核,而不需要guest os。
因此当建立一个容器时,docker不需要和虚拟机一样重新加载一个操作系统的内核。从而避免加载操作系统内核返回比较费时的资源过程,当新建一个虚拟机时,虚拟机软件需要加载guest os,返回新建过程是分钟级的。而docker由于直接利用宿主机的操作系统,则省略了加载过程,因此新建一个docker容器只需要几秒。
2. 常用命令
2.1 帮助命令
docker version # 版本信息
docker info # 系统信息,包括镜像和容器
docker command --help # 帮助命令
2.2 镜像命令
查看所有镜像
docker images # 查看本机所有镜像
option:
-a # 查看所有
-q # 只显示镜像id
搜索镜像
docker search images_name --filter=stars=3000 # 查找镜像
下载镜像
docker pull images_name:version # 拉取镜像
删除镜像
docker rmi -f $(docker images -qa) # 删除全部镜像
2.3 容器命令
新建容器
# 新建容器并启动, 若没有找到镜像,会自动下载最新版
docker run [options] images_name
--name # 容器名字,用以区分
-d # 后台方式运行
-it # 交互方式运行,进入容器内部
-p # 主机端口:容器端口
--rm # 运行完就删除,常用于测试
# 测试
[root@localhost ~]# docker run -it centos /bin/bash
WARNING: IPv4 forwarding is disabled. Networking will not work.
[root@9bac75e8963f /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@9bac75e8963f /]# exit
exit
[root@localhost ~]#
查看容器
# 列出所有运行的容器
docker ps
option:
-a # 显示运行的容器,会带有历史运行
退出容器
exit
ctrl + p + q # 容器不停止退出
注意: Docker容器后台运行,就必须有一个前台进程,容器运行的命令如果不是那些一直挂起的命令(比如运行top
,tail),就是会自动退出的, 所以指定了端口映射的应用都不会自动退出
docker run -d -v hello:/world busybox ls /world
删除容器
docker rm container_id
docker rm -f $(docker ps -qa)
docker ps -q -a|xargs docker rm # 管道符
启动和停止
docker start container_id
docker restart container_id
docker kill container_id
docker stop container_id
docker stop $(docker ps -q)
2.4 常用其他命令
日志
docker logs -ft --tail 10 30c147332443 container_id
进程
docker top container_id # 容器中运行的进程信息
元数据
docker inspect container_id
docker image inspect image_id/image_name
exec
在运行的容器中执行命令
docker exec -it mynginx /bin/sh /root/runoob.sh
attach
进入容器正在运行的终端
docker attach container_id
2.5 小结
2.6 Portainer
https://documentation.portainer.io/v2.0/deploy/ceinstalldocker/
docker run -d -p 9001:9001 --name portainer_test --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
3. 镜像分层原理
参考资料: https://blog.csdn.net/pjsdsg/article/details/90445128
镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件, 它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
镜像加载原理
UnionFS(联合文件系统)
UnionFS(联合文件系统): Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承, 基于基础镜像(没有父镜像), 可以制作各种具体的应用镜像。
特性: 一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
**bootfs(boot file system)**主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的, 包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs(root file system), 在bootfs之上。包含的就是典型Linux系统中的/dev, /proc, /bin, /etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。
平时我们安装虚拟机的CentOS都是好几个G,为什么docker这里才200M?
对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就行了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以共用bootfs。
虚拟机启动是分钟级别的,容器启动是秒级别的!
分层理解
分层的镜像
镜像下载都是一层一层下载,已有的文件系统层次不在需要下载!
镜像分层下载的依据:
docker image inspect centos
镜像分层最大的好处
最大的一个好处就是共享资源。
比如:有多个镜像都从相同的base镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,同时内存中也只需加载一份base镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
镜像的特点
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。
这一层通常被称作为"容器层",“容器层”之下的都叫"镜像层"。
commit镜像
docker commit -a “作者” -m “备注” container_id 镜像名字:版本号
[root@localhost ~]# docker exec -it ea857ec9eead bash
root@ea857ec9eead:/usr/local/tomcat# ls
BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs native-jni-lib temp webapps webapps.dist work
root@ea857ec9eead:/usr/local/tomcat# cp -r webapps.dist/* webapps/
root@ea857ec9eead:/usr/local/tomcat# exit
exit
[root@localhost ~]# docker commit -a "xuyaohua" -m "my apache tomcat add webapps" ea857ec9eead mytomcat:v1
sha256:2b77aa06f9a64dd8a110c9ff245f80b3fe19fb94519504b84e9a4c7589ac3fc4
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mytomcat v1 2b77aa06f9a6 11 seconds ago 672MB
tomcat latest 5505f7218e4d 32 hours ago 667MB
nginx latest d1a364dc548d 3 weeks ago 133MB
portainer/portainer latest 580c0e4e98b0 3 months ago 79.1MB
4. 数据卷volumes
docker是将应用和环境打包成一个镜像。
数据都在容器中,如果容器删除,数据也就丢失了!需求:数据实现持久化
数据卷, 通过挂载目录,可以实现容器中的数据共享!将容器中的数据,同步到本地。
数据卷可以不仅可以实现数据同步本地,还可以实现容器内的数据共享!
volume create
volume create 匿名和指定名字方式都将数据卷存储在: /var/lib/docker/volumes/
ApI1.21+
volume create
/var/lib/docker/volumes/hello
docker volume create hello
# 运行时-v指定已创建本地挂载数据卷
docker run -d -v hello:/world busybox ls /world # 没有提供前台服务,自动退出
docker volume create # 自定创建匿名卷,不推荐
volume inspect
[root@localhost volumes]# docker volume inspect hello
[
{
"CreatedAt": "2021-06-19T08:25:21+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/hello/_data",
"Name": "hello",
"Options": {},
"Scope": "local"
}
]
volume prune
[root@localhost volumes]# docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
78963cdfe74cb775e98476dde76a129ee74035614ee0929501f0e7cdcf0f5c0d
01bf50d9438a9e9a9216940389455d4003f3dbb49c91b8de4d8fcb628a9e9867
Total reclaimed space: 131.9kB
volume ls
只会列出在该目录下的数据卷:/var/lib/docker/volumes/hello
docker run -v
创建容器时,设置数据卷挂载
-e # 指定环境变量
docker run -v /宿主机路径:容器内路径 # 指定存放位置的具名数据卷
docker run -v 容器内路径 # 匿名
docker run -v 卷名:容器内路径 # 具名挂载,使用数据卷默认存放位置
未指定宿主机路径,都将存放在/var/lib/docker/volumes/目录下
匿名挂载
docker run -it -v /home --name centos02 centos /bin/bash
docker inspect centos02
具名挂载1
docker run -it -v centos03:/home --name centos03 centos /bin/bash
docker inspect centos03
具名挂载2
实现MySQL数据同步
docker run -d -p 3333:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=111111 --name mysql01 mysql:5.7
容器删除,数据卷数据也不会删除
设置读写权限
container_path:rw # 容器具有读写权限,默认
container_path:ro # 容器只有读权限
–volumes-from
实现容器间的数据共享
具名挂载数据同步
docker run -d -p 8888:8080 --name tomcat01 -v /home/tomcat/webapps:/usr/local/tomcat/webapps/ROOT/ mytomcat:v1
docker run -d -p 8889:8080 --name tomcat02 --volumes-from tomcat01 mytomcat:v1
docker run -d -p 8890:8080 --name tomcat03 --volumes-from tomcat02 mytomcat:v1
docker exec -it tomcat02 /bin/bash
cd /usr/local/tomcat/webapps/ROOT
echo "tomcat02<br/>" >> index.jsp
...
数据备份与恢复
例如:
tomcat01是自制镜像 mytomcat:v1启动的应用
docker run --rm --volumes-from tomcat01: tomcat01同步到临时容器
临时容器中 /usr/local/tomcat/webapps目录压缩备份成webapps.tar
通过数据卷映射将webapps.tar同步到当前目录下
删除临时容器
docker run --rm --volumes-from tomcat01 -v $(pwd):/backup mytomcat:v1 tar cvf /backup/webapps.tar /usr/local/tomcat/webapps
恢复自身容器:直接进入容器,解压容器备份目录,拷贝到指定目录即可
恢复到新容器:
通过数据卷映射将webapps.tar同步到临时容器 backup目录下
解压临时容器 backup目录下webapps.tar到指定目录即可
docker run -d -p 9999:8080 -v $(pwd):/backup --name tomcat02 tomcat
docker exec -it tomcat02 /bin/bash
cd /backup
tar -xvf webapps.tar -C /usr/local/tomcat
# -C 指定解压到的目的路径
# c tar 压缩
# x tar 解压
小结
数据卷好处:
1、实现持久化
mysql
2、数据共享
通过修改本地文件,来修改容器配置文件数据
3、数据备份
–volume-from
5. dockerfile
用来构建docker镜像,是一个镜像编写脚本,构建镜像的步骤
dockerfile面向开发,发布项目,发布镜像,就需要使用到dockerfile
企业交付
dockfile指令
FROM # 基础镜像
MAINTAINER # 维护者 姓名+邮箱
RUN # 构建时候需要运行的命令
ADD # 添加内容
WORKDIR # 镜像工作目录
VOLUME # 挂载的目录
EXPOSE # 指定暴露的端口
CMD # 指定容器启动运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定容器启动运行的命令,可以追加命令
ONBUILD # 当构建一个被继承的dockerfiles时候,就会触发ONBUILD指令
COPY # 添加命令,添加文件到镜像中
ENV # 设置环境变量
构建centos
构建1
FROM centos
MAINTAINER Jxnuxyh<2466743619@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum install -y vim
RUN yum install -y net-tools
EXPOSE 80
CMD "----end---"
CMD /bin/bash
docker build -f centos-dockerfile -t mycentos:1.0 .
add 和 entrypoint区别
示例: docker run image_id -l
add [“ls”, “-a”] 生成的镜像在run的时候追加命令时会被替换
-l 会找不到命令
entrypoint [“ls”, “-a”] 生成的镜像在run的时候追加命令直接拼接
ls -al
构建2
centos添加tomcat, jdk
小结
6. Docker网络
docker0
查看宿主机ip addr:172.17.0.1
交换机、网关格式的ip, 充当docker的路由器
启动一个tomcat: docker run -d --name tomcat01 tomcat
查看tomcat01 ip: 126: eth0@if127
[root@localhost ~]# docker exec -it tomcat01 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
126: eth0@if127: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
宿主机多了一个对应tomcat01 IP: 127: vethd845067@if126
[root@localhost ~]# ip addr #
127: vethd845067@if126: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 0a:bf:e3:04:77:b3 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::8bf:e3ff:fe04:77b3/64 scope link
valid_lft forever preferred_lft forever
tomcat01容器能够ping通宿主机
[root@localhost ~]# docker exec -it tomcat01 ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1) 56(84) bytes of data.
64 bytes from 172.17.0.1: icmp_seq=1 ttl=64 time=0.122 ms
64 bytes from 172.17.0.1: icmp_seq=2 ttl=64 time=0.080 ms
64 bytes from 172.17.0.1: icmp_seq=3 ttl=64 time=0.094 ms
64 bytes from 172.17.0.1: icmp_seq=4 ttl=64 time=0.071 ms
64 bytes from 172.17.0.1: icmp_seq=5 ttl=64 time=0.061 ms
64 bytes from 172.17.0.1: icmp_seq=6 ttl=64 time=0.077 ms
宿主机能够ping通tomcat01容器
[root@localhost ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.051 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.055 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.061 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.055 ms
64 bytes from 172.17.0.2: icmp_seq=5 ttl=64 time=0.053 ms
容器间互通
再创建一个tomcat02, 两个容器之间也是能够互通的
[root@localhost ~]# docker exec -it tomcat02 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.100 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.062 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.064 ms
evth-pair技术
安装了docker,就会有一个网卡(docker0),网络模式为桥接模式,使用的是 evth-pair技术
每启动一个容器docker就会为它分配一个IP地址,对应的也会多一对网卡!
容器和linux主机可以ping通,而且每个容器之间也可以通过ip地址ping通
docker容器带来的网卡都是一对一对的,evth-pair 就是一对的虚拟设备接口,都是成对出现的,一段连着协议,
一段彼此连接,evth-pair 就像一个桥梁,连接各种虚拟网络设备。
–link
发布一个微服务,database url=ip, 项目不重启,数据库ip换掉了,希望可以通过名字来访问容器?
docker run -d --name tomcat03 --link tomcat02 tomcat
新建容器tomcat03 --link tomcat02
[root@localhost ~]# docker run -d --name tomcat03 --link tomcat02 tomcat
6e4c6784f888c2e300cacf1b9e75ff56d41a5ccc366faaaeb23f0d86765df30f
[root@localhost ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
[root@localhost ~]# docker exec -it tomcat03 ping tomcat02 # 单向
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.075 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.084 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.058 ms
[root@localhost ~]# docker exec -it tomcat03 cat /etc/hosts # 修改hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 tomcat02 055ef50c1eea
172.17.0.4 6e4c6784f888
–link是单向的, A —link B 就是在A的hosts文件中添加B的映射
通过docker0自动分配ip,无法实现通过容器名之间访问,需要借助–link,而且–link在容器中创建是应用,显得有些
乏力,还不如直接修改/etc/hosts来的直接。
自定义网络可以解决docker0的局限性。
自定义网络
容器互联可以通过docker0 + --link,但是不优雅。
查看docker网络支持的方式
docker run 默认是–net bridge
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
37ae3e698670 bridge bridge local # 桥接, 默认
2e0feba19ae5 host host local # 主机模式
c5043c8ce6b2 none null local # 不配置
创建自己的网段:docker network create --driver=bridge --subnet=192.168.0.0/16 --gateway=192.168.0.1 mynet
[root@localhost ~]# docker network create --help
Usage: docker network create [OPTIONS] NETWORK
Create a network
Options:
--attachable Enable manual container attachment
--aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
--config-from string The network from which to copy the configuration
--config-only Create a configuration only network
-d, --driver string Driver to manage the Network (default "bridge")
--gateway strings IPv4 or IPv6 Gateway for the master subnet
--ingress Create swarm routing-mesh network
--internal Restrict external access to the network
--ip-range strings Allocate container ip from a sub-range
--ipam-driver string IP Address Management Driver (default "default")
--ipam-opt map Set IPAM driver specific options (default map[])
--ipv6 Enable IPv6 networking
--label list Set metadata on a network
-o, --opt map Set driver specific options (default map[])
--scope string Control the network's scope
--subnet strings Subnet in CIDR format that represents a network segment
[root@localhost ~]# docker network create --driver=bridge --subnet=192.168.0.0/16 --gateway=192.168.0.1 mynet
f411dabc8b369d63c4ae0ff5da35e3e8584d55f320caa7b63e980bd244db78df
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
37ae3e698670 bridge bridge local
2e0feba19ae5 host host local
f411dabc8b36 mynet bridge local
c5043c8ce6b2 none null local
[root@localhost ~]# docker run -d --name tomcat04 --net mynet tomcat
64791eb330994fa30ddee3b13b164b51df79a20d603372f24f1e39b8d3917f63
[root@localhost ~]# docker run -d --name tomcat05 --net mynet tomcat
查看自定义网络详情, Containers记录了使用该网段的容器信息
[root@localhost ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "f411dabc8b369d63c4ae0ff5da35e3e8584d55f320caa7b63e980bd244db78df",
"Created": "2021-06-20T15:14:02.433386737+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"35e4348202c7141f7187de48653dc48e9546e3556dc95383100c868c92fb7a5c": {
"Name": "tomcat05",
"EndpointID": "cf75e4f90d32d7a912bf071acc1d1b66ad203b989a9998cada0e49afca2dea62",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"64791eb330994fa30ddee3b13b164b51df79a20d603372f24f1e39b8d3917f63": {
"Name": "tomcat04",
"EndpointID": "a7c98a8f266ca5ff5e6b70e857de25aebccda5c8da30ca3be973abb94b73d180",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
使用同一个网段的创建的容器可以通过容器名互联,解决了docker0的局限性
[root@localhost ~]# docker exec -it tomcat04 ping tomcat05
PING tomcat05 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat05.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.060 ms
64 bytes from tomcat05.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.086 ms
[root@localhost ~]# docker exec -it tomcat05 ping tomcat04
PING tomcat04 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat04.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.036 ms
64 bytes from tomcat04.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.074 ms
64 bytes from tomcat04.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.099 ms
docker跨网络
通过docker network connect可以实现
docker network connect [OPTIONS] NETWORK CONTAINER
docker network connect tomcat01 mynet
本质就是将容器tomcat01添加到指定网段中,达到容器与网络互联
docker打包微服务镜像
idea打包生成jar包,编写Dockerfile文件, 上传文件Dockerfile和jar包到服务器
服务器通过Dockerfile构建生成镜像
docker通过镜像创建容器启动应用
[root@localhost idea]# docker build -t spring-boot-demo .
Sending build context to Docker daemon 17.31MB
Step 1/5 : FROM java:8
8: Pulling from library/java
5040bd298390: Pull complete
fce5728aad85: Pull complete
76610ec20bf5: Pull complete
60170fec2151: Pull complete
e98f73de8f0d: Pull complete
11f7af24ed9c: Pull complete
49e2d6393f32: Pull complete
bb9cdec9c7f3: Pull complete
Digest: sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9d
Status: Downloaded newer image for java:8
---> d23bdf5b1b1b
Step 2/5 : COPY *.jar /app.jar
---> 24d343b58a97
Step 3/5 : CMD ["--server.port","8080"]
---> Running in 64adcd45ddd1
Removing intermediate container 64adcd45ddd1
---> 979890b5cbd6
Step 4/5 : EXPOSE 8080
---> Running in 70f355218c24
Removing intermediate container 70f355218c24
---> 99c8ed066ae2
Step 5/5 : ENTRYPOINT ["java", "-jar", "/app.jar"]
---> Running in 4e2909800526
Removing intermediate container 4e2909800526
---> 79cdc3f4b30d
Successfully built 79cdc3f4b30d
Successfully tagged spring-boot-demo:latest
[root@localhost idea]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
spring-boot-demo latest 79cdc3f4b30d 17 seconds ago 661MB
tomcat latest 5505f7218e4d 3 days ago 667MB
java 8 d23bdf5b1b1b 4 years ago 643MB
[root@localhost idea]# docker run -d -P --name boot-demo spring-boot-demo
badcfd6ab702607824b662150ce805daff9fc77e3faa45d69757811d4ef0eab6
[root@localhost idea]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
badcfd6ab702 spring-boot-demo "java -jar /app.jar …" 14 seconds ago Up 12 seconds 0.0.0.0:49153->8080/tcp, :::49153->8080/tcp boot-demo
[root@localhost idea]# curl localhost:49153
{"timestamp":"2021-06-20T12:20:11.529+00:00","status":404,"error":"Not Found","path":"/"}
[root@localhost idea]# curl localhost:49153/hello
docker package test demo....
7. Compose
Compose介绍
https://docs.docker.com/compose/install/
前面我们使用 Docker 的时候,定义 Dockerfile 文件,然后使用 docker build、docker run 等命令操作容器。然而微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,那么效率之低,维护量之大可想而知
使用 Docker Compose 可以轻松、高效的管理容器,它是一个用于定义和运行多容器 Docker 的应用程序工具
安装
sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
docker-compose.yml
编写规则:https://docs.docker.com/compose/compose-file/compose-file-v3/
version: "3"
services:
dockerapp:
build: .
image: dockerapp
depends_on:
- redis
ports:
- "8080:8080"
redis:
image: redis
运行
docker-compose up
[root@localhost dockercompose]# docker-compose up
Building dockerapp
Step 1/5 : FROM java:8
---> d23bdf5b1b1b
Step 2/5 : COPY *.jar /app.jar
---> f99b4bf986d8
Step 3/5 : CMD ["--server.port","8080"]
---> Running in 5ca32ab5cc61
Removing intermediate container 5ca32ab5cc61
---> a7d893fd5ab6
Step 4/5 : EXPOSE 8080
---> Running in 044df1274c83
Removing intermediate container 044df1274c83
---> b06bd12a6de8
Step 5/5 : ENTRYPOINT ["java", "-jar", "/app.jar"]
---> Running in e84673f03b17
Removing intermediate container e84673f03b17
---> 150dac1fd598
Successfully built 150dac1fd598
Successfully tagged dockerapp:latest
WARNING: Image for service dockerapp was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`. # dockerapp不存在,按照yml该服务指定build目录指定的Dockerfile构建image
Creating dockercompose_redis_1 ... done
Creating dockercompose_dockerapp_1 ... done
Attaching to dockercompose_redis_1, dockercompose_dockerapp_1
redis_1 | 1:C 20 Jun 2021 20:06:22.746 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1 | 1:C 20 Jun 2021 20:06:22.746 # Redis version=6.2.4, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1 | 1:C 20 Jun 2021 20:06:22.746 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1 | 1:M 20 Jun 2021 20:06:22.747 * monotonic clock: POSIX clock_gettime
redis_1 | 1:M 20 Jun 2021 20:06:22.756 * Running mode=standalone, port=6379.
redis_1 | 1:M 20 Jun 2021 20:06:22.756 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1 | 1:M 20 Jun 2021 20:06:22.756 # Server initialized
redis_1 | 1:M 20 Jun 2021 20:06:22.756 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis_1 | 1:M 20 Jun 2021 20:06:22.757 * Ready to accept connections
dockerapp_1 |
dockerapp_1 | . ____ _ __ _ _
dockerapp_1 | /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
dockerapp_1 | ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
dockerapp_1 | \\/ ___)| |_)| | | | | || (_| | ) ) ) )
dockerapp_1 | ' |____| .__|_| |_|_| |_\__, | / / / /
dockerapp_1 | =========|_|==============|___/=/_/_/_/
dockerapp_1 | :: Spring Boot :: (v2.5.0)
dockerapp_1 |
dockerapp_1 | 2021-06-20 20:06:25.281 INFO 1 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication v0.0.1-SNAPSHOT using Java 1.8.0_111 on 013af94cb46b with PID 1 (/app.jar started by root in /)
dockerapp_1 | 2021-06-20 20:06:25.291 INFO 1 --- [ main]
dockerapp不存在,按照yml该服务指定build目录指定的Dockerfile构建image
docker-compose up执行解析yml, 创建的服务都指定了镜像名,会先在本地找;若没有找到,同时指定了Dockerfile构建文件,就会在本地构建该镜像名的镜像;若本地没找到,同时也没有指定构建文件,就会去远程找到并下载到本地。
dockercompose会创建一个属于自己的网络
8. Swarm
不管是docker run还是docker-compose都是单机下创建容器服务
Swarm是管理docker集群的平台,几乎全部用GO语言来完成的开发的
代码开源在https://github.com/docker/swarm, 它是将一群Docker宿主机变成一个单一的虚拟主机。
Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排项目,但不同的是,Docker Compose 是
一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群
服务,对于微服务的部署,显然 Docker Swarm 会更加适合。
从 Docker 1.12.0 版本开始,Docker Swarm 已经包含在 Docker 引擎中(docker swarm),并且已经内置了服务发现工具。
并且,swarm可以实现扩缩容。
Swarm是典型的master-slave结构,通过发现服务来选举manager。
manager是中心管理节点,各个node上运行agent接受manager的统一管理,集群会自动通过Raft协议分布式选
举出manager节点,无需额外的发现服务支持,避免了单点的瓶颈问题,同时也内置了DNS的负载均衡和对外部
负载均衡机制的集成支持。
9. CI/CD
附录
1. 端口映射错误
docker: Error response from daemon: driver failed programming external connectivity on endpoint tomcat02 (659114ceffa773dbc45a3b389f7c9ccb1a8b087e373b06e8b281f851c6dca6da): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 9999 -j DNAT --to-destination 172.17.0.3:8080 ! -i docker0: iptables: No chain/target/match by that name.
解决方案: systemctl restart docker
重启docker