1、DockerFile
用于制作自己的镜像。
1.1、DockerFile相关命令
FROM:定制的镜像都是基于 FROM 的镜像。
RUN:用于执行后面跟着的命令行命令, docker build时执行。
COPY:复制指令,从上下文目录中复制文件或者目录到容器里指定路径。
ADD:ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:
ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
CMD:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。
CMD 在docker run 时运行。
RUN 是在 docker build。
ENTRYPOINT: 类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 CMD 指令指定的程序。
优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
ENV:设置环境变量。K-V键值方式,在后续的使用过程中可以使用$K的当时使用
VOLUME:定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
EXPOSE:暴漏端口。
WORKDIR:设置工作目录
MAINTIANER:设置镜像的作者信息 姓名<邮箱>
2、构建自己的centos
[root@node1 mycentos]# cat Dockerfile
FROM centos
MAINTAINER liu<247202624@qq.com>
WORKDIR /etc
RUN yum -y install vim
EXPOSE 80
CMD /bin/bash
#构建镜像
[root@node1 mycentos]# docker build -f Dockerfile -t mycentos:1.0 .
#启动镜像
[root@node1 mycentos]# docker run -it mycentos:1.0
3、Docker网络
3.1、docker0
在docker中所有的容器之间的网络是相互隔离的,如果需要将容器将网络联通,应该怎么办?
docker提供了一个docker0的虚拟网络来实现容器间的网络联通
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:d7:0e:71:0b 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:d7ff:fe0e:710b/64 scope link
valid_lft forever preferred_lft forever
172.17.0.1/16:表示docker0这个虚拟网络可以管理的网络是从172.17.0.2一直到172.17.255.254的网络,也就是可以管理255*255-2个容器,如果172.17.0.1/32,则表示可管理172.17.0.2到172.17.0.254的网络。
也就是说每当你启动一个容器时,docker就会自动根据docker0的网络自动分配一个虚拟的ip,一般情况下是递增的。
当容器A要和容器B进行通信时,直接访问容器B的虚拟ip就可以了,因为容器A和容器B同属于同一个docker0的网段内。
举例:进入容器B 去ping容器A(172.17.0.2),就可以ping通
root@4c4404728d65:/usr/local/tomcat# 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.046 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.086 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.087 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.087 ms
64 bytes from 172.17.0.2: icmp_seq=5 ttl=64 time=0.067 ms
64 bytes from 172.17.0.2: icmp_seq=6 ttl=64 time=0.056 ms
64 bytes from 172.17.0.2: icmp_seq=7 ttl=64 time=0.049 ms
64 bytes from 172.17.0.2: icmp_seq=8 ttl=64 time=0.044 ms
64 bytes from 172.17.0.2: icmp_seq=9 ttl=64 time=0.047 ms
64 bytes from 172.17.0.2: icmp_seq=10 ttl=64 time=0.044 ms
64 bytes from 172.17.0.2: icmp_seq=11 ttl=64 time=0.040 ms
64 bytes from 172.17.0.2: icmp_seq=12 ttl=64 time=0.040 ms
^C
--- 172.17.0.2 ping statistics ---
12 packets transmitted, 12 received, 0% packet loss, time 29ms
rtt min/avg/max/mdev = 0.040/0.057/0.087/0.020 ms
具体访问原理如下图
启动容器A,并进入容器内部如何 ip addr 查看网络发现出现了成对的网络配置
退出容器A,查看宿主机的网络,也同样出现了成对的网络配置,恰好数字是相反的。
容器B也会出现同样的成对网络配置
其实,当容器A去ping容器B的地址时,先通过这个成对的网络配置到达docker0 由docker0去寻找容器B的成对网络配置,然后将请求转发到容器B,这样就完成了通信。
问题!!!
容器每次重启都会随机分配一个ip,显然这种网络联通模式是不便捷的。所以就需要一种比较便捷的通信。这就是link
3.2 、link
link就是在启动的时候通过绑定容器名称,实现网络的通信,类似于域名访问
举例:启动三个名字分别为tomcat01,tomcat02,tomcat03的容器,在启动tomcat03的时候绑定tomcat01的容器名,不绑定tomcat02,进行测试。
[root@node1 ~]# docker run -d -P --link tomcat01 --name tomcat03 tomcat:8.5
4e722dcf11d4efe6e2e2369e38374a14fce8658335af578f137f3434f17f4eff
[root@node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4e722dcf11d4 tomcat:8.5 "catalina.sh run" 5 seconds ago Up 5 seconds 0.0.0.0:49156->8080/tcp, :::49156->8080/tcp tomcat03
9ef584ffca4f tomcat:8.5 "catalina.sh run" 4 minutes ago Up 4 minutes 0.0.0.0:49155->8080/tcp, :::49155->8080/tcp tomcat02
4c4404728d65 tomcat:8.5 "catalina.sh run" 5 minutes ago Up 4 minutes 0.0.0.0:49154->8080/tcp, :::49154->8080/tcp tomcat01
[root@node1 ~]# docker exec -it tomcat03 ping tomcat01
PING tomcat01 (172.17.0.2) 56(84) bytes of data.
64 bytes from tomcat01 (172.17.0.2): icmp_seq=1 ttl=64 time=0.150 ms
64 bytes from tomcat01 (172.17.0.2): icmp_seq=2 ttl=64 time=0.124 ms
64 bytes from tomcat01 (172.17.0.2): icmp_seq=3 ttl=64 time=0.121 ms
64 bytes from tomcat01 (172.17.0.2): icmp_seq=4 ttl=64 time=0.123 ms
64 bytes from tomcat01 (172.17.0.2): icmp_seq=5 ttl=64 time=0.096 ms
64 bytes from tomcat01 (172.17.0.2): icmp_seq=6 ttl=64 time=0.121 ms
^C
--- tomcat01 ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 11ms
rtt min/avg/max/mdev = 0.096/0.122/0.150/0.019 ms
[root@node1 ~]# docker exec -it tomcat03 ping tomcat02
ping: tomcat02: Name or service not known
结果显示,tomcat03绑定tomcat01之后可以通过容器名字直接ping通,但是没有绑定tomcat02,所以无法ping通。
原理:
进入tomcat03容器内查看host文件发现,tomcat03的host文件中配置了tomcat01域名访问,所以才可以ping通。
问题!!!
虽然–link可以解决容器重启之后的网络通信,但是在每次run的时候都需要去配置–link,很麻烦,而且如果搭建一个集群的时候,集群的网络和其他的应用的网络都同处于一个网络下面,没有办法进行网络隔离,很难保证网络的健康。
所以,我们需自定义一个类似于docker0的网络来解决这个问题。
3.3自定义网络
查看docker网络
[root@node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
ef70fb31e63c bridge bridge local #docker0 的网络 桥接模式
5a90a9073842 host host local #主机模式,使用宿主机的ip通信
55323c86fa97 none null local #无模式
新建mynet的网络,模式为桥接
[root@node1 ~]# docker network create -d bridge --gateway 192.168.0.1 --subnet 192.168.0.0/16 mynet
e9abdffe2cd9c26c0fa211de1de437c295822f46faf17a4aab910327f4815ef2
[root@node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
ef70fb31e63c bridge bridge local
5a90a9073842 host host local
e9abdffe2cd9 mynet bridge local
55323c86fa97 none null local
查看宿主机的网络发现,生成了一个虚拟的网络,ip是从192.168.0.1开始的。
通过这个网络来启动容器测试网络联通,在不需要link的情况下是否可以直接通过容器名通信呢?
启动tomcat01和tomcat02
[root@node1 ~]# docker run -d -P --name tomcat01 --network mynet tomcat:8.5
6761b9bbbcce34c2ba63eda4dacb9881eb707a3570af0e0279c51abdde61677b
[root@node1 ~]# docker run -d -P --name tomcat02 --network mynet tomcat:8.5
a9b3f2c705537a1f979cdd2dc6b575e047c34af458485ecf31d7dcbe308d65a2
测试结果如下:可以通过容器名通信。
所以自定义docker网络弥补docker0需要link 的确定,也同样可以满足不同的组件集群可以部署在不同的网络环境当中,保证了网络的健康。
问题!!!
如果容器A在docker0中,容器B在自定义网络中,那么这个两个容器如何通信呢?
解决方法:
将容器A加入到容器B所处的网络中即可,测试通过,访问成功,操作如下:
[root@node1 ~]# docker network connect mynet tomcat03
[root@node1 ~]# docker exec -it tomcat03 ping tomcat01
PING tomcat01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.046 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.124 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.056 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=4 ttl=64 time=0.123 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=5 ttl=64 time=0.054 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=6 ttl=64 time=0.111 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=7 ttl=64 time=0.121 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=8 ttl=64 time=0.125 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=9 ttl=64 time=0.122 ms
^C
--- tomcat01 ping statistics ---
9 packets transmitted, 9 received, 0% packet loss, time 46ms
rtt min/avg/max/mdev = 0.046/0.098/0.125/0.032 ms
[root@node1 ~]# docker exec -it tomcat03 ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.072 ms
64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.120 ms
64 bytes from 192.168.0.2: icmp_seq=3 ttl=64 time=0.120 ms
64 bytes from 192.168.0.2: icmp_seq=4 ttl=64 time=0.119 ms
^C
--- 192.168.0.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 8ms
rtt min/avg/max/mdev = 0.072/0.107/0.120/0.024 ms