是什么?
白话点, 是个提供了必要环境
的虚拟机(类似于java的导入部分包一样和c++的头文件差不多), 所以它比普通的VMWare或者VirtualBox安装的虚拟机要轻
总体来说类似于jvm那样的存在, 只不过jvm运行的是java编译的字节码, docker运行的是各种组件, 比如mysql, redis, zookeeper或者我们的项目
有哪些关键的概念
- 镜像
docker镜像类似于系统安装包ISO
, 或者我们对某个程序的备份, 将这个备份压缩成rar压缩包
, 备份了很多程序的数据和配置, 我们只要把这个压缩包丢给别人, 别人解压并使用这个程序
- 容器
容器类似于我们的程序(前面的镜像是压缩包), 可以直接运行
总结
镜像和容器的关系是 一个镜像对应可以多个容器(只要你创建的多)
怎么用?
Docker安装与启动
安装Docker
由于我们学习的环境都使用的是CentOS,因此这里我们将Docker安装到CentOS上。注意:这里建议安装在CentOS7.x以上的版本,在CentOS6.x的版本中,安装前需要安装其他很多的环境而且Docker很多补丁不支持更新。
请直接挂载课程配套的Centos7.x
镜像
(1)yum
包更新到最新
sudo yum update
(2)安装需要的软件包, yum-util
提供yum-config-manager
功能,另外两个是devicemapper
驱动依赖的
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
(3)设置yum
源为阿里云
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
(4)安装docker
sudo yum install docker-ce
(5)安装后查看docker版本
docker -v
设置镜像加速
创建或编辑该文件:
vi /etc/docker/daemon.json
在该文件中输入如下内容:
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com",
"https://mirror.ccs.tencentyun.com",
"https://registry.docker-cn.com"
]
}
docker基本指令
service docker start # 开启docker
service docker stop # 关闭docker
service docker restart # 重启docker
当然也可以使用systemctl
systemctl start docker # 同上
镜像管理
导入导出镜像
docker save java > /home/java.tar.gz
docker load < /home/java.tar.gz
镜像的下载其实是分层的, 具体可以使用docker inspect 镜像名
, 可以看到
当我们有些层级在其他镜像中也存在则不需要重新下载, 直接复用了事
这里涉及到docker底层镜像的原理, 联合文件系统
unionFS
, 简单点说就是对于一个文件的修改是一层一层的叠加的, 类似于 github 提交修改的文件一样, 使用该系统后, docker 的镜像文件可以被继承, 复用
使用这套系统将会特别精简, 只需要加载必要继续环境和层级来完成我们的环境搭建, 不会想VMware虚拟机一样(一下子几G), 直接一个加载一个系统, 而使用docker我们只需要环境需要的
相关的 bootfs 和 rootfs 自行百度
镜像查找
docker search java
我们还可以添加
--filter stars=3000
, 表示镜像的stars
大于3000
镜像下载
docker pull java
镜像上传
镜像上传到 dockerhub 远程仓库
-
登入
docker login --username 用户名
回车后需要输入密码 -
docker push
注意: 最好加上 tag
不过最终我还是失败了, 为什么呢?
很简单
假设我 hub docker 上的账户名称是
docker tag my_centos:1.0.0 libai/centos:1.0.0
比如我 hub docker 的账号名称是
libai
, 则镜像的名称必须是libai
开头
将镜像上传到阿里云
- 打开阿里云控制台
- 搜索容器镜像
- 点击个人实例
- 点击命名空间, 并创建命名空间
命名空间的功能有点像 C++ 的namespace
- 创建镜像仓库
下一步, 发现有很多仓库, 这里根据需要选择就行
我选择了本地仓库
接下来就能看到非常详细的步骤
根据步骤就能够上传我们的镜像
查看镜像列表
docker images
查看镜像信息
docker inspect java
[
{
"Id": "sha256:d23bdf5b1b1b1afce5f1d0fd33e7ed8afbc084b594b9ccf742a5b27080d8a4a8",
"RepoTags": [
"java:latest"
],
"RepoDigests": [
"java@sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9d"
],
"Parent": "",
"Comment": "",
"Created": "2017-01-17T00:52:54.890877145Z",
"Container": "4b4ab1e131616e04a88f26f9811e5847dd0c3ec5f8178b634b388d3c510ee606",
"ContainerConfig": {
"Hostname": "33842653d6db",
"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",
"LANG=C.UTF-8",
"JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64",
"JAVA_VERSION=8u111",
"JAVA_DEBIAN_VERSION=8u111-b14-2~bpo8+1",
"CA_CERTIFICATES_JAVA_VERSION=20140324"
],
"Cmd": [
"/bin/sh",
"-c",
"/var/lib/dpkg/info/ca-certificates-java.postinst configure"
],
"ArgsEscaped": true,
"Image": "sha256:7cfe1ce37b990ea20d6377b8901f5ffccd463ed2f965e9730d834e693b53baec",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": [],
"Labels": {}
},
"DockerVersion": "1.12.3",
"Author": "",
"Config": {
"Hostname": "33842653d6db",
"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",
"LANG=C.UTF-8",
"JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64",
"JAVA_VERSION=8u111",
"JAVA_DEBIAN_VERSION=8u111-b14-2~bpo8+1",
"CA_CERTIFICATES_JAVA_VERSION=20140324"
],
"Cmd": [
"/bin/bash"
],
"ArgsEscaped": true,
"Image": "sha256:7cfe1ce37b990ea20d6377b8901f5ffccd463ed2f965e9730d834e693b53baec",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": [],
"Labels": {}
},
"Architecture": "amd64",
"Os": "linux",
"Size": 643195347,
"VirtualSize": 643195347,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/fcdfe412499e0b1afe9cb8d6800eb56af9c578b1c49fbf0fc9f38fead4f32b2d/diff:/var/lib/docker/overlay2/5d79e6646df2342376ba59d8d21b70142d0e3fd0c9a0de2229c1cfa4c2d98e93/diff:/var/lib/docker/overlay2/47b9afdc585a2c847d112283d7d884f00140dab44c33203eeeccc4a592a23378/diff:/var/lib/docker/overlay2/9565b7df775e50948f7713b8a1b1ba6610eb055c958bbd23a7646b4414ccefab/diff:/var/lib/docker/overlay2/dd8233c055d2241a6e52a0f0acd48220f87a75e50fbe2a7355445bcc75bbfbb9/diff:/var/lib/docker/overlay2/64bb2d108355eb53a495cdb6804e602baa651888a27c10c19dfb0fa2351648b6/diff:/var/lib/docker/overlay2/3fb4d1d79e7b1966b16dfb4d7dcde2ac6ac602f932395acf2c5d3bd0573a9c67/diff",
"MergedDir": "/var/lib/docker/overlay2/09e28e456caf00dd0ab82af1f594f248f05e0e64a4b931f69251ab2f1c9c4df3/merged",
"UpperDir": "/var/lib/docker/overlay2/09e28e456caf00dd0ab82af1f594f248f05e0e64a4b931f69251ab2f1c9c4df3/diff",
"WorkDir": "/var/lib/docker/overlay2/09e28e456caf00dd0ab82af1f594f248f05e0e64a4b931f69251ab2f1c9c4df3/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:a2ae92ffcd29f7ededa0320f4a4fd709a723beae9a4e681696874932db7aee2c",
"sha256:0eb22bfb707db44a8e5ba46a21b2ac59c83dfa946228f04be511aba313bdc090",
"sha256:30339f20ced009fc394410ac3360f387351641ed40d6b2a44b0d39098e2e2c40",
"sha256:ce6c8756685b2bff514e0b28f78eedb671380084555af2b3833e54bb191b262a",
"sha256:a3483ce177ce1278dd26f992b7c0cfe8b8175dd45bc28fee2628ff2cf063604c",
"sha256:6ed1a81ba5b6811a62563b80ea12a405ed442a297574de7440beeafe8512a00a",
"sha256:c3fe59dd955634c3fa1808b8053353f03f4399d9d071be015fdfb98b3e105709",
"sha256:35c20f26d18852b74cc90afc4fb1995f1af45537a857eef042a227bd8d0822a3"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
镜像删除
docker rmi java
删除所有镜像
docker rmi $(docker images -q)
查看一个镜像如何创建的
docker history 镜像id
可以通过 Portainer 查看
容器管理
启动镜像(镜像初次产生容器)
启动镜像会默认创建出一个容器
docker run -it --name myjava java bash
使用bash运行保持控制台方式运行docker run -it --name myjava -p 9000:8080 -p 9050:8050 java bash
以控制台方式运行java并且映射了java的端口8080到主机的9000, 映射到java的8050到主机的9050端口docker run -it -name myjava -v /home/project:/soft --privileged java bash
映射java应用的路径/soft
到主机的/home/project
路径并使用--privileged
给了修改权限
mkdir /home/project
docker run -it --name myjava -p 9000:8080 -p 9050:8050 -v /home/project:/soft --privileged java bash
添加
[option] -d
创建和以后台方式启动容器
给容器内的应用添加环境参数
docker run -it 容器id -e 容器应用的参数 -e xxx -e yyy
进入正在运行的容器
方式一:
docker exec -it 容器id 容器对应的命令
docker exec -it centos /bin/bash
方式二:
docker attcah 容器id
这两种方式不同之处在于:
docker exec
是启动一个新的终端
docker attcah
进入容器正在执行的终端, 而不启动新的进程
暂停、停止和开启容器
docker pause 容器id # 可以在另一个控制台暂停
docker unpause 容器id # 可以在另一个控制台执行
docker stop 容器id # 可以停止掉容器
docker start 容器id # 启动容器
docker kill 容器id # 强制停止容器
docker restart 容器id # 重启容器
退出容器
exit # 直接推出容器, 并停止
ctrl + P + Q # 容器不停止, 退出
查看容器和查看运行中的容器
docker ps -a # 查看所有容器, 包括未运行的容器
docker ps -aq # 查看所有容器的id, 包括未运行的容器
docker ps # 查看正在运行的容器
删除容器
docker rm myjava
删除容器
docker rm -f $(docker ps -aq)
删除所有容器
查看容器日志
docker logs
docker logs -f -t --tail 容器id
查看容器内进程信息
docker top 容器id
从容器中拷贝
docker cp 容器id:容器内目录 本地目录
提交容器
- 首先下载
docker pull tomcat
- 运行
docker run -d tomcat
- 进入容器内部
docker exec -it 3e369e0c31d4 /bin/bash
- 修改
webapp
whereis tomcat
cd /usr/local/tomcat
ls
cp -r webapps.dist/ROOT/ webapps
- 打包(完毕)
[root@localhost mysql]# docker commit --help
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Create a new image from a container's changes
Options:
-a, --author string Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
-c, --change list Apply Dockerfile instruction to the created image
-m, --message string Commit message
-p, --pause Pause container during commit (default true)
docker commit -a '你的名字' -m '消息, 你对容器的修改' 容器id 镜像名称:版本
docker commit -a 'zhazha' -m 'change webapp' 3e369e0c31d4 my_tomcat:0.0.1
命令总结
字典
创建docker卷
为什么需要数据卷?
这得从 docker 容器的文件系统说起。出于效率等一系列原因,docker 容器的文件系统在宿主机上存在的方式很复杂,这会带来下面几个问题:
- 不能在宿主机上很方便地访问容器中的文件。
- 无法在多个容器之间共享数据。
- 当容器删除时,容器中产生的数据将丢失。
为了解决这些问题,docker 引入了数据卷(volume) 机制。数据卷是存在于一个或多个容器中的特定文件或文件夹,这个文件或文件夹以独立于 docker 文件系统的形式存在于宿主机中。数据卷的最大特定是:其生存周期独立于容器的生存周期。
使用数据卷的最佳场景
- 在多个容器之间共享数据,多个容器可以同时以只读或者读写的方式挂载同一个数据卷,从而共享数据卷中的数据。
- 当宿主机不能保证一定存在某个目录或一些固定路径的文件时,使用数据卷可以规避这种限制带来的问题。
- 当你想把容器中的数据存储在宿主机之外的地方时,比如远程主机上或云存储上。
- 当你需要把容器数据在不同的宿主机之间备份、恢复或迁移时,数据卷是很好的选择。
使用方法
docker volume create --name v1
例如:
root@ubuntu:/# docker volume create --name node1
node1
root@ubuntu:/# docker volume inspect node1
[
{
"CreatedAt": "2020-07-08T14:03:16+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/node1/_data",
"Name": "node1",
"Options": {},
"Scope": "local"
}
]
它把卷创建到了宿主机的/var/lib/docker/volumes/node1/_data
目录下
匿名和具名卷
匿名卷
docker run -v /etc/nginx --name nginx01 -d nginx
这种方式创建的容器是匿名卷
具名卷
docker volume create nginx_volume
docker volume ls
DRIVER VOLUME NAME
local nginx_volume
local portainer_data
docker run -v nginx_volume:/etc/nginx --name nginx02 -d nginx
这样就创建了一个具名卷的nginx
总结下
docker 卷有三种方式
- 匿名卷
- 具名卷
- 主机目录和docker虚拟机目录映射
安装mysql, 并映射卷的例子
这里我们选择使用
-v
的方式实现主机和docker虚拟机的映射(docker卷)
docker run -p 23306:3306 -v /root/mysql/my.cnf:/etc/mysql/my.cnf -v /root/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --privileged=true --name mysql01 -d mysql
这段代码是通过官方命令修改而成的, 至于为什么知道需要映射那些目录, 主要还是查资料, 查linux系统安装完毕 mysql 之后, 主要涉及的目录是些什么, 我们就在docker上添加什么
-e
的mysql密码, 需要我们主动添加, 否则会报错
--privileged=true
, 默认给容器内部的系统提升权限到 root
-p 23306:3306
将docker虚拟机的 3306 映射到主机的 23306 端口中
-d mysql
默认后台运行, 我发现这项放在前面经常会报错, 所以最高好还是放到最后
如果运行 mysql 会报错
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
, 可能需要在映射到主机的/root/mysql/my.cnf
文件中添加secure_file_priv=/var/lib/mysql
注意, 里面的参数
port=3306
端口不能修改, 因为我们的端口映射虚拟机就是3306
成功连接上去
数据卷
主要用于同步文件使用
简单的Dockerfile入门
- 简单的写个dockerfile
FROM centos
VOLUME ["volume01", "volume02"]
CMD 'echo "=======end======="'
CMD /bin/bash
- build
docker build -f Dockerfile -t zhazha/centos:0.0.1 .
.
号,其实是在指定镜像构建过程中的上下文环境的目录。
docker build
其实是在 docker 引擎中构建的, 所以需要传递我们的上下文环境给docker
使用Portainer 查看我们创建的镜像, 就会发现 , 我们的指令在下面这个地方
Image layers
又遇到熟悉的 layer
了
我们写的 Dockerfile
每一行代码都算一个层, docker限制我们的层不能超过 127 层
现在我们启动我们的镜像文件
docker run -it f2fbcaac50da /bin/bash
可以看到两个 volume
查看docker的inspect
就可以发现
这两个映射
现在我们正式开始学习数据卷
多个系统都有一个卷是共享的
- 写简单的Dockerfile
FROM centos
VOLUME ["volume"]
CMD echo "====end====="
CMD /bin/bash
使用
docker build -f Dockerfile -t zhazha/centos:0.0.1 .
创建出一个镜像文件
现在我们在三个控制台上创建
docker run --name=centos01 -it 3cc90e8bc91c /bin/bash
docker run --volumes-from centos01 --name=centos02 -it 3cc90e8bc91c /bin/bash
docker run --volumes-from centos01 --name=centos03 -it 3cc90e8bc91c /bin/bash
现在我们在 volume
中创建一个新的文件
touch zhazha.txt
在其他控制台中看看
我们写入hello centos2
然后到 centos3
上看看
这个文件的volume
在三个系统中以复制的方式存在, 所以即便删除掉其中一个系统, 另外两个系统都不会收到任何影响
CMD 、 RUN 和 ENTRYPOINT 的区别
- RUN
- 构建镜像时运行的指令
说白了, 就是
docker build
时运行的RUN
- CMD
- 运行容器时执行的shell环境, 但它可以被代替
说白了, 就是
docker run
时运行的, 比如 CMD echo "容器执行了", 它被放在dockerfile的最后一行
FROM centos:7
MAINTAINER zhazha<22222@qq.com>
RUN echo "容器构建了"
CMD echo "容器执行了"
CMD用于指定容器启动时执行的命令,每个
Dockerfile
只能有一个CMD
命令,多个CMD
命令只执行最后一个。 若容器启动时指定了运行的命令,则会覆盖掉CMD中指定的命令。
- ENTRYPOINT
ENTRYPOINT
和CMD
一样, Dockerfile中,只能有 一个ENTRYPOINT 指令,如果有多个 ENTRYPOINT 指令则以最后 一个 为准
- 类似于
CMD
指令,但其不会被docker run
的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给ENTRYPOINT
指令指定的程序。
什么叫不被命令参数执行的指令覆盖?
现在我们把 dockerfile
修改下
FROM centos:7
MAINTAINER zhazha<22222@qq.com>
RUN echo "容器构建了"
CMD ls -a
docker run -it 0ff248d85404 -l
报错了
将 CMD
替换成 ENTRYPOINT
docker build -f centos_dockerfile -t mm_centos02 .
docker run -it b6b9a3fe10cb -l
现在知道什么覆盖了吧?
使用
CMD
的方式, 如果在docker run
的最后又有新的指令, 则会立即代替掉我们dockerfile
里面最终一行, 所写的CMD
指令, 如果使用的是ENTRYPOINT
则,docker run
最后命令将会添加到dockerfile
里
需要注意的是, RUN 这些命令是一层包装的意思, docker里面的镜像最多包装127层, 所以前一个
RUN cd /home
后一个RUN touch 1.txt
所处的目录不同, 前一个RUN
的目录可能是在home
下面, 而第二个RUN
目录其实还在根目录下, 所以下面的代码最多会在根目录下创建一个1.txt
文件
FROM centos:7
MAINTAINER zhazha<22222@qq.com>
RUN ["cd", "/home"]
RUN ["touch", "1.txt"]
需要这样:
FROM centos:7
MAINTAINER zhazha<22222@qq.com>
RUN ["touch", "/home/1.txt"]
DockerFile文件编写
- 编写dockerfile
FROM centos:7
MAINTAINER zhazha<2222222222@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "=====end====="
CMD /bin/bash
- 执行命令
docker build -f Dockerfile -t zhazha/centos:1.0.0 .
- 成功创建, 现在可以看到镜像了
现在我们的这个镜像创建的容器可以使用 vim
和 net
相关的指令
使用dockerfile定制自己的tomcat虚拟机
如果我们编写的Dockerfile文件名是
Dockerfile
, 则不需要添加docker build -f
不需要添加-f
, 他会自动找到Dockerfile
的文件
- 准备资源文件
- 编写Dockerfile
vi Dockerfile
FROM centos:7
MAINTAINER zhazha<2222222222@qq.com>
ENV MYPATH /usr/local
COPY readMe.txt $MYPATH/readMe.txt
WORKDIR $MYPATH
ADD openJdk11.tar.gz $MYPATH
ADD apache-tomcat-10.tar.gz $MYPATH
RUN yum -y install vim
ENV JAVA_HOME /usr/local/jdk-11.0.14.1+1
ENV CLASS_PATH $JAVA_HOME/lib
CMD ["export", "PATH JAVA_HOME CLASSPATH"]
CMD source /etc/profile.d/java.sh
ENV CATALINA_HOME /usr/local/apache-tomcat-10.0.17
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-10.0.17/bin/startup.sh && tail -F /usr/local/apache-tomcat-10.0.17/logs/catalina.out
创建镜像:
docker build -t my_tomcat .
创建成功:
创建容器:
docker run -it b49f9241556e /bin/bash
环境变量添加成功:
docker 网络
要了解 docker 的网络, 需要了解 veth-pair
技术
Virtual Ethernet Pair 简称 veth pair ,是一个成对的端口,所有从这对端口一端进入的数据包都将从另一端出来,反之也是一样
探索过程
我们编写 Dockerfile
FROM tomcat:latest
MAINTAINER zhazha<222@qq.com>
RUN apt update
RUN apt -y install iputils-ping # 让你可以使用 ping
RUN apt -y install iproute2 # 让你可以使用 ip addr
RUN apt -y install net-tools # 让你可以使用 ifconfig
然后启动起来
docker run -P -it 镜像ID
现在我们在容器内输入ip a
查看 ip 180: eth0@if181
然后在主机上输入 ip a
看看 181: veth005201b@if180
然后就能得到下面这张图片:
PS: 需要更多的 docker 图片可以查百度
上图的紫色 NAT
表示直连
如果我们再次启动另一个 tomcat 照上面的方式还是能看到
虚拟机:
主机:
总体来说, 就类似于 docker 在虚拟机与虚拟机间搭建了一座桥梁, 虚拟机借助这座桥梁与另外的虚拟机通讯
也可以当作管道, 虚拟机在管道间通讯
我们需要注意的是现在 不仅仅是主机能与虚拟机ping通, 而且虚拟机和虚拟机之间也是可以ping通的
link(不推荐)
link的方式已经不被推荐使用
为什么需要?
问: 前面我们知道虚拟机已经可以和虚拟机相互 ping 通, 那为什么还需要 link 呢?
ip 到 域名 的改变
答: 其实很简单, 就因为一段代码: ping 172.17.0.3
① ip 不好记忆, 是硬编码
② 虚拟机的 ip 是 docker
随机分配的, 假设虚拟机 tomcat01
现在的地址是 172.17.0.3
下次可不一定还是它, 所以我们需要已经类似域名的东西作为 ip
的代替品, 类似DNS的方式
③ 容器的端口也可以自定义
所以 link
诞生了
是什么?
简洁版: 通过
docker
的link
机制可以通过一个name
来和另一个容器通信,link
机制方便了容器去发现其它的容器并且可以安全的传递一些连接信息给其它的容器。
需要注意的是
link
的方式存在发送端和接收端, 他是单向的
怎么用?
docker run --name=tomcat01 -it 5372cc765456 /bin/bash
docker run --link=tomcat01 --name=tomcat02 -it 5372cc765456 /bin/bash
进入容器 tomcat01 去 ping 容器 tomcat02 无法 ping 通
反之可以:
docker run --link=tomcat01 --name=tomcat02 -it 5372cc765456 ping tomcat01
怎么实现的?
link
底层的实际上使用的是 修改 hosts
的方式
现在我们知道为什么在 tomcat02
内部使用 ping
通 tomcat01
了
那如果 tomcat01
的 ip
变了呢? 没关系, docker
会主动修改 tomcat02
内的 hosts
的 tomcat01
的 ip
, 全自动的, 不需要用户自己修改
缺点
虽然link
打通了一个单向的管道, 但无法反向访问, 所以这是他的缺点
所以 自定义 docker 网络 的方式出现了
自定义 docker 内部网络
前置知识
在创建内网前, 我们需要知道一些网络方面的知识
我们经常能看到这样:
172.17.0.1/16
这后面的 16
是什么?
它表示了 16
个 1
, 而这里的 16
个 1
用于下面的 ip
11111111.11111111.0.0
子网掩码: 255.255.0.0
而他的作用是限定了我们主机的 ip 的数量可以是 172.17.0.0 ~ 172.17.255.255
去除掉 网络号(全0) 172.17.0.0
和 广播地址 172.17.0.255
(全1), 剩下的都是主机号
不过据说出现了 CIDR 已经不需要减 2 , 不过这不是本文重点
现在可以学习docker网络方面的知识了
docker的网络模式
docker
的网络模式:
bridge
: 桥接模式, 就是我们说的docker0
, 一般默认创建的虚拟机就使用的docker0
进行桥接host
: 主机直连none
: 不配置网络
怎么用? (创建docker网络)
[root@localhost ~]# docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
connect 将容器连接到网络
create 创建 docker 的网络
disconnect 断开容器与网络的链接
inspect 显示一个或多个网络的详细信息
ls 列出网络
prune 删除所有未使用的网络
rm 移除一个或多个网络
- 创建网络
docker network create -d bridge --subnet 192.167.0.0/16 --gateway 192.167.0.1 mynet
看注解, 我们可以把上面的代码精简下
docker network create --subnet 192.167.0.0/16 --gateway 192.167.0.1 mynet
指定 子网 ip
和 网关 ip
- 创建容器并连接
docker run -P --network mynet --name tomcat01 -it 5372cc765456 /bin/bash
借助Portainer
我们也可以看见:
主机和tomcat01
也互通
docker run -P --network mynet --name tomcat02 -it 5372cc765456 /bin/bash
现在 tomcat01
和 tomcat02
也是互通的
ping tomcat01
ping tomcat02
外部容器连接到一个网络集群
有一两个外部的虚拟机需要连接到一个网络集群中这种场景, docker
提供了这种场景的支持
docker network connect mynet 8fcf9d6f2624