文章目录
一、 docker的四种网络模式
Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。
Docker有以下4种网络模式:
- bridge模式:使用–net =bridge指定,默认设置;
- host模式:使用–net =host指定;
- none模式:使用–net =none指定;
- container模式:使用–net =container:NAME or ID指定。
1.1 host模式
如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。
[root@localhost ~]# docker run -it --name test --network=host centos:7
1.2 container模式
这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
已有一个容器在运行
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ec00df3ff4c9 centos:7 "/bin/bash" 8 minutes ago Up 8 minutes
创建一个新容器与已有容器共享一个Network Namespace
[root@localhost ~]# docker run -it --net "container:ec00df3ff4c9" centos:7
1.3 none模式
使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过–network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
[root@localhost ~]# docker run -it --network=none centos:7
[root@044890fdf101 /]#
1.4 bridge模式(最常用)
当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。
使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看,所以防火墙不能关闭。
每一个新建的网卡与其连接的容器形成的区域,我们就称之为namespace命名空间。
首先创建新的网关
[root@localhost ~]# docker network create --subnet=172.18.0.0/24 mycard
3f8a7349502753b94558d43cc76b6beb3aa6604f23d38a5da4bf643384ab3dd1
[root@localhost ~]# ifconfig
br-3f8a73495027: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.18.0.1 netmask 255.255.255.0 broadcast 172.18.0.255
ether 02:42:0d:c1:1a:b3 txqueuelen 0 (Ethernet)
RX packets 32 bytes 5206 (5.0 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 60 bytes 8933 (8.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:46ff:fe75:460 prefixlen 64 scopeid 0x20<link>
ether 02:42:46:75:04:60 txqueuelen 0 (Ethernet)
RX packets 37150 bytes 1603857 (1.5 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 42367 bytes 166148247 (158.4 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
创建指定IP的容器,并运行
[root@localhost ~]# docker run -itd --name test17 --network mycard --ip 172.18.0.17 centos:7 /bin/bash
304379f0d6efeaf9b4268fab7d2085484a0eb416df4086bef5d30c4c8bc50842
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
304379f0d6ef centos:7 "/bin/bash" 8 seconds ago Up 8 seconds test17
ec00df3ff4c9 centos:7 "/bin/bash" 7 hours ago Up 7 hours test01
1c1111a332ff nginx:centos "/usr/local/nginx/sb…" 20 hours ago Up 20 hours 0.0.0.0:32771->80/tcp, 0.0.0.0:32770->443/tcp festive_haslett
ec138882e99c systemctl:centos "/sbin/init" 21 hours ago Up 21 hours 22/tcp sharp_cannon
6dc8b8eff3ca sshd:centos "/usr/sbin/sshd -D" 24 hours ago Up 24 hours 0.0.0.0:32769->22/tcp jolly_black
0d75466654d3 mysql:centos "init" 24 hours ago Up 24 hours 0.0.0.0:32768->3306/tcp mysql
进入容器查看IP
[root@localhost ~]# docker attach 304379f0d6ef ##进入容器中,attach进入的前提是容器处于运行中
[root@304379f0d6ef /]# yum install net-tools -y ##安装网络工具查看网卡信息
[root@304379f0d6ef /]# ifconfig ##IP为设置的172.18.0.17
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.18.0.17 netmask 255.255.255.0 broadcast 172.18.0.255
ether 02:42:ac:12:00:11 txqueuelen 0 (Ethernet)
RX packets 4020 bytes 11976920 (11.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3622 bytes 198971 (194.3 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 79 bytes 6516 (6.3 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 79 bytes 6516 (6.3 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
二、Docker Compose容器编排
2.1 Docker Compose
Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。
Docker Compose 的前身是Fig,使用Docker Compose不再需要使用shell脚本来启动容器,Docker Compose非常适合组合使用多个容器进行开发的场景。
-
Compose默认管理对象是项目,通过子命令对项目中的一组容器进行生命周期的管理。
-
Compose项目由Python实现,实现上调用了Docker服务提供的API来对容器进行管理。
2.2 YML文件
YAML是一种标记语言很直观的数据序列化格式,非常适合用来表达或者编辑数据结构、各种配置文件、文件大纲等,例如:许多电子邮件标题格式和YAML非常接近
文件格式以及编写注意事项
- 不支持制表符tab键缩进,需要使用空格缩进,使用缩进表示层级关系
- 通常开头缩进2个空格,缩进的空格数不重要,只要相同层级的元素左对齐即可
- 字符后缩进一个空格,如冒号、逗号、横杆
- 用#号注释
- 如果包含特殊字符用单引号引起来
- 布尔值必须用引号括起来
2.3 使用Docker Compose
- 使用Dockerfile定义应用程序的环境
- 使用docker-compose.yml定义构成应用程序的服务,这样它们可以在隔离环境中一起运行
- 最后执行docker-compose up命令来启动并运行整个应用程序
下载compose
[root@docker ~]# curl -L https://github.com/docker/compose/releases/download/1.21.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose ##在Linux上我们可以从GitHub上下载它的二进制包来使用,此命令是下载Docker Compose的当前稳定版本
[root@docker ~]# chmod +x /usr/local/bin/docker-compose
[root@docker ~]# docker-compose -v
docker-compose version 1.21.1, build 5a3f1a3
三、 使用compose编排一个nginx服务
编辑nginx的Dockerfile文件,并将软件包放在Dockerfile文件所在目录下
[root@localhost ~]# mkdir compose_nginx
[root@localhost ~]# cd compose_nginx/
[root@localhost compose_nginx]# mkdir nginx
[root@localhost compose_nginx]# cd nginx/
[root@localhost nginx]# vim Dockerfile
FROM centos:7
MAINTAINER this is nginx
RUN yum -y update
RUN yum -y install gcc gcc-c++ pcre-devel make zlib-devel
ADD nginx-1.12.2.tar.gz /usr/local/src
RUN useradd -M -s /sbin/nologin nginx
WORKDIR /usr/local/src/nginx-1.12.2
RUN ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module
RUN make && make install
ENV PATH /usr/local/nginx/sbin/:$PATH
RUN ln -s /usr/local/nginx/sbin/* /usr/local/sbin/
EXPOSE 80
EXPOSE 443
RUN echo "daemon off;" >> /usr/local/nginx/conf/nginx.conf ##将nginx的守护进程关闭,以容器的守护进程开启
CMD ["/usr/local/nginx/sbin/nginx"]
[root@localhost nginx]# ls
Dockerfile nginx-1.12.2.tar.gz
编辑yml文件,严格按照格式,注意空格
[root@localhost nginx]# cd ..
[root@localhost compose_nginx]# vim docker-compose.yml
version: '3'
services:
nginx:
hostname: nginx
build:
context: ./nginx
dockerfile: Dockerfile
ports:
- 1216:80
- 1217:443
networks:
- cloud
volumes:
- ./wwwroot:/usr/local/nginx/html
network:
cloud:
[root@localhost compose_nginx]# ls
docker-compose.yml nginx
使用docker-compose命令运行,-f指定文件,-d守护进程
[root@localhost compose_nginx]# docker-compose -f docker-compose.yml up -d
...
省略部分信息
Recreating 09d8868566db_compose_nginx_nginx_1 ... done
最后出现这条信息就是成功执行
[root@localhost compose_nginx]# ls ##看是否产生了wwwroot
docker-compose.yml nginx wwwroot
[root@localhost compose_nginx]# cd wwwroot
[root@localhost wwwroot]# vim index.html ##写一个网站首页
<h1>this is web</h1>
安装tree软件,看所需的文件是否都在
[root@localhost wwwroot]# cd ..
[root@localhost compose_nginx]# yum install tree -y
[root@localhost compose_nginx]# tree ./
./
├── docker-compose.yml ##模板脚本
├── nginx
│ ├── Dockerfile ##容器脚本
│ └── nginx-1.12.2.tar.gz ##源码包
└── wwwroot
└── index.html ##站点
2 directories, 4 files
[root@localhost compose_nginx]# docker ps -a ##查看容器是否up状态
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3c99f16ba9ca compose_nginx_nginx "/usr/local/nginx/sb…" 8 minutes ago Up 8 minutes 0.0.0.0:1216->80/tcp, 0.0.0.0:1217->443/tcp compose_nginx_nginx_1
[root@localhost compose_nginx]# docker images ##查看镜像是否建立
REPOSITORY TAG IMAGE ID CREATED SIZE
compose_nginx_nginx latest e187ecc784ba 2 hours ago 480MB