Docker容器之网络管理、端口映射、容器间的互联、Dockerfile完成镜像封装

docker的四种网络模式

Docker 在启动时会创建一个虚拟网桥 docker0,默认地址为 172.17.0.1/16, 容器启动后都会被桥接到 docker0 上,并自动分配到一个 IP 地址。
启动容器时可以使用 –net参数指定,默认是桥接模式;
1)bridge桥接模式
实现步骤:
a. Docker Daemmon利用veth pair技术在物理机创建2个虚拟网络接口设备veth0 和veth1;
b. Docker Daemon将veth0附加到创建的docker0网桥上;将veth1添加到Docker Container所属的namespace下,并将改名为eth0

缺陷:
该模式下 Docker Container 不具有一个公有 IP,即和物理机的 eth0 不处于同一个网段,所以除了宿主机以外,它都不能直接和容器进行通信;

[root@foundation45 ~]# docker network ls

这里写图片描述

[root@foundation45 ~]# docker run -d --name vm1 nginx
459d90371193916bdba81aa9a9b46112acb09b4d4e87b61bcbf709f4e8ec8c10
[root@foundation45 ~]# brctl show

这里写图片描述
这里写图片描述

[root@foundation45 ~]# docker stop vm1
vm1
[root@foundation45 ~]# brctl show

这里写图片描述
2)host 模式
最大的特点是:docker container和宿主机(即物理机)的网路资源是共享的,但是这样极大地弱化了网络环境的隔离性,还有该容器会与宿主机进行网络栈使用的竞争;

[root@foundation45 ~]# docker run -it --name vm2 --net host ubuntu
root@foundation45:/# ip addr   ##可以看到host模式下,docker和宿主机(物理机)的网络资源是共享的;
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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: enp0s25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
    link/ether 00:21:cc:70:ce:d7 brd ff:ff:ff:ff:ff:ff
3: wlp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 10:0b:a9:14:4d:ec brd ff:ff:ff:ff:ff:ff
    inet 192.168.43.48/24 brd 192.168.43.255 scope global dynamic wlp3s0
       valid_lft 2468sec preferred_lft 2468sec
    inet6 fe80::7d89:6331:9efb:7d99/64 scope link 
       valid_lft forever preferred_lft forever
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:21:cc:70:ce:d7 brd ff:ff:ff:ff:ff:ff
    inet 172.25.45.250/24 brd 172.25.45.255 scope global br0
       valid_lft forever preferred_lft forever
    inet 172.25.254.45/24 brd 172.25.254.255 scope global br0
       valid_lft forever preferred_lft forever
    inet6 fe80::221:ccff:fe70:ced7/64 scope link 
       valid_lft forever preferred_lft forever
5: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:53:8b:04 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
6: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:53:8b:04 brd ff:ff:ff:ff:ff:ff
7: virbr1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:61:fa:73 brd ff:ff:ff:ff:ff:ff
8: virbr1-nic: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast master virbr1 state DOWN group default qlen 1000
    link/ether 52:54:00:61:fa:73 brd ff:ff:ff:ff:ff:ff
9: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:df:08:32:ea brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:dfff:fe08:32ea/64 scope link 
       valid_lft forever preferred_lft forever
22: veth2de49c1@if21: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 92:af:a2:f4:bd:f0 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::90af:a2ff:fef4:bdf0/64 scope link 
       valid_lft forever preferred_lft forever

3)container模式
可以用来更好的服务于容器间的通信。在这种模式下的 Docker Container 可以通过 localhost 来访问 namespace 下的其他容器,传输效率较高。还节约了一定数量的网络资源。但是和桥接模式是一样,不能连接除宿主机以外的其他设备;

[root@foundation45 ~]# docker run -it --name vm3 --net container:vm1 ubuntu
root@459d90371193:/# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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
21: eth0@if22: <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
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link 
       valid_lft forever preferred_lft forever

[root@foundation45 ~]# docker ps  ##有2个容器;
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
7d86b62445cd        ubuntu              "/bin/bash"              38 seconds ago      Up 37 seconds                           vm3
459d90371193        nginx               "nginx -g 'daemon ..."   15 minutes ago      Up 8 minutes        80/tcp              vm1
[root@foundation45 ~]# brctl show   ##但是桥接只有一个;新创建的vm3容器 使用的是vm1的namespace;
bridge name bridge id       STP enabled interfaces
br0     8000.0021cc70ced7   no      enp0s25
docker0     8000.0242df0832ea   no      veth2de49c1
virbr0      8000.525400538b04   yes     virbr0-nic
virbr1      8000.52540061fa73   yes     virbr1-nic

4)none模式
none模式不提供任何的网络环境,只能使用loopback网络设备即lo;
所以说我们可以自己做网络配置的设定;

[root@foundation45 ~]# docker run -it --name vm4 --net none ubuntu
root@7413bc599338:/# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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
root@7413bc599338:/# ip addr add 172.17.0.100/24 dev lo  ##没有权限;
RTNETLINK answers: Operation not permitted
root@7413bc599338:/# id
uid=0(root) gid=0(root) groups=0(root)

注:当前不要直接结束这个shell窗口,新开一个shell窗口,完成以下设置,否则Pid将会发生改变,所有设定将会无效;

none 模式为 Docker Container 做了极少的网络设定;我们现在在 none 网络模式下尝试分配固定 ip

[root@foundation45 ~]# docker inspect vm4 | grep Pid

这里写图片描述

[root@foundation45 docker]# cd /proc/6061  ##6061是当前vm4的Pid
[root@foundation45 6061]# cd ns
[root@foundation45 ns]# ll

这里写图片描述
使用 netns 网络空间虚拟化可以在本地虚拟化出多个网络环境

扫描二维码关注公众号,回复: 3444621 查看本文章
[root@foundation45 ns]# ip netns add test  ##添加一个namespace
[root@foundation45 ns]# ip netns list
test
[root@foundation45 ns]# cd /var/run/netns/
[root@foundation45 netns]# ls
test
[root@foundation45 netns]# ip netns del test

[root@foundation45 netns]# ls
[root@foundation45 netns]# pwd
/var/run/netns
[root@foundation45 netns]# ln -s /proc/6061/ns/net /var/run/netns/6061   ##软链接
[root@foundation45 netns]# ip netns list
6061
[root@foundation45 netns]# ip link add name veth0 type veth peer name veth1  ##veth0、veth1没有被激活
[root@foundation45 netns]# ip addr
23: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 36:cf:a2:50:82:51 brd ff:ff:ff:ff:ff:ff
24: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether de:15:31:cd:92:f0 brd ff:ff:ff:ff:ff:ff
[root@foundation45 netns]# brctl addif docker0 veth0
[root@foundation45 netns]# brctl show
bridge name bridge id       STP enabled interfaces
br0     8000.0021cc70ced7   no      enp0s25
docker0     8000.0242df0832ea   no      veth0
                            veth2de49c1
virbr0      8000.525400538b04   yes     virbr0-nic
virbr1      8000.52540061fa73   yes     virbr1-nic
[root@foundation45 netns]# ip link set up veth0  ##激活veth0
[root@foundation45 netns]# ip link set up veth1  ##激活veth1
[root@foundation45 netns]# ip addr
23: veth1@veth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether 36:cf:a2:50:82:51 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::34cf:a2ff:fe50:8251/64 scope link 
       valid_lft forever preferred_lft forever
24: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP qlen 1000
    link/ether de:15:31:cd:92:f0 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::dc15:31ff:fecd:92f0/64 scope link 
       valid_lft forever preferred_lft forever
[root@foundation45 netns]# ip link set veth1 netns 60616061的namesapce 添加一个设备
[root@foundation45 netns]# ip netns exec 6061 ip link set veth1 name eth0 
[root@foundation45 netns]# ip netns exec 6061 ip link set up dev eth0  ##启用设备
[root@foundation45 netns]# ip netns exec 6061 ip addr add 172.17.0.45/24 dev eth0   ##为namespace 中指定设备设置ip
[root@foundation45 netns]# ip netns exec 6061 ip route add default via 172.17.0.1 ##添加网关
##在原来没有结束的shell 用ip addr命令查看,是否有新增的端口;
root@cd21022d6285:/# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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
48: eth0@if49: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 06:df:7a:08:5c:b0 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.45/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::4df:7aff:fe08:5cb0/64 scope link 
       valid_lft forever preferred_lft forever

root@cd21022d6285:/# route -n 

尝试看能不能上网:
这里写图片描述
这里写图片描述


端口映射

首先结束以上的所有创建的容器,保证纯实验环境;

[root@foundation45 netns]# docker rm -f `docker ps -aq` ##
2c59599cabe1
7d86b62445cd
b6f038e1cab4
459d90371193
[root@foundation45 netns]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@foundation45 netns]# docker run -d --name vm1 -p 8080:80 nginx  ##将8080端口映射到80;
7bbfdccc63fcb512c5af459655beb87a392bc91ca841d51cb91fe6d9d005a20b
[root@foundation45 netns]# iptables -t nat -nL
Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8080 to:172.17.0.2:80

浏览器查看:
这里写图片描述


容器互联

[root@foundation45 netns]# docker run -it --name vm2 --link  vm1:nginx ubuntu
root@2dc3de9c655b:/# env
HOSTNAME=2dc3de9c655b
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
root@2dc3de9c655b:/# cat /etc/hosts

这里写图片描述

root@2dc3de9c655b:/# ping nginx

这里写图片描述


镜像封装

(1)Dockerfile 自启动httpd服务

[root@foundation45 netns]# docker rm -f `docker ps -aq`
ad1c9f589cab
aa94b3de1e09
[root@foundation45 ~]# cd /tmp/docker/
[root@foundation45 docker]# ls
web
[root@foundation45 docker]# vim dvd.repo
[rhel7.3]
name=rhel7.3
baseurl=http://172.25.45.250/source7.3
gpgcheck=0

[root@foundation45 docker]# vim index.html
www.westos.org
www.westos.org
www.westos.org
www.westos.org
www.westos.org

[root@foundation45 docker]# vim Dockerfile

FROM rhel7  ##指定基础镜像
MAINTAINER 1658011140@qq.com  ##作者信息(可选)
ENV HOSRNAME server1  ##设定容器主机名
EXPOSE 80  ##暴露容器端口
COPY dvd.repo /etc/yum.repos.d/dvd.repo  ##yum源的配置
RUN rpmdb --rebuilddb && yum install -y httpd && yum clean all
VOLUME ["/var/www/html"]   ##镜像操作命令
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]  ##镜像启动命令

[root@foundation45 docker]# docker build -t rhel7:v1 . ##创建镜像rhel:v1

这里写图片描述

[root@foundation45 docker]# docker images rhel7

这里写图片描述

[root@foundation45 docker]#  docker run -d --name vm3 -v /tmp/docker/web:/var/www/html rhel7:v1
e0de99f362f4207813990537e24d5714e941e5d43a9dc82ef5e79e8d269ac562

[root@foundation45 docker]# docker inspect vm3
 "IPAddress": "172.17.0.3",

浏览器查看:
这里写图片描述

(2)Dockerfile自启动ssh服务;

[root@foundation45 docker]# ls
Dockerfile  dvd.repo  web
[root@foundation45 docker]# pwd
/tmp/docker
[root@foundation45 docker]# mkdir ssh
[root@foundation45 docker]# cp dvd.repo ssh/
[root@foundation45 docker]# cd ssh/
[root@foundation45 ssh]# ls
 dvd.repo
[root@foundation45 ssh]# vim Dockerfile 
FROM rhel7
MAINTAINER 1658011140@qq.com
ENV HOSRNAME server2
EXPOSE 22
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y openssh-server openssh-clients && yum clean all && ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" && ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N "" && ssh-keygen -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" && echo root:westos | chpasswd
CMD ["/usr/sbin/sshd","-D"]

[root@foundation45 ssh]# docker build -t rhel7:v2 .
Successfully built 97148afe4138
[root@foundation45 ssh]# docker run -d --name vm4 rhel7:v2
460b16820ecb09472c95df9c7a9d9d5decbc66338b31944360f2bb9e705d505b
[root@foundation45 ssh]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
460b16820ecb        rhel7:v2            "/usr/sbin/sshd -D"      6 seconds ago       Up 4 seconds        22/tcp              vm4
8eed5f77fbb0        rhel7:v1            "/usr/sbin/httpd -..."   32 minutes ago      Up 32 minutes       80/tcp              vm3
791c6257dbaf        rhel7               "bash"                   About an hour ago   Up About an hour                        vm1

[root@foundation45 ssh]# ssh 172.17.0.2  ##输入密码,测试
-bash-4.2#

注意
镜像的每一层都有自己的ID;
镜像分层的意义:共享资源;
不仅镜像之间是共享的,容器和物理机之间也是共享的;

(3)ssh和http的整合:

在官网下载supervisor-2.1-9.el6.noarch.rpm,将其放在/var/www/html/source7.3/Packages下

[root@foundation45 ~]# cd /tmp/docker
[root@foundation45 docker]# ls
Dockerfile  dvd.repo  ssh  web
[root@foundation45 docker]# vim supervisord.conf

[supervisord]
nodaemon=true    ##nodaemon =true 表示有后台程序;      

[program:sshd]
command=/usr/sbin/sshd -D

[program:httpd]
command=/usr/sbin/httpd

[root@foundation45 docker]# vim Dockerfile

FROM rhel7
EXPOSE 80 22
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y httpd supervisor openssh-server openssh-clients && yum clean all && ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" && ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N "" && ssh-keygen -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" && echo root:westos | chpasswd
COPY supervisord.conf /etc/supervisord.conf
CMD ["/usr/bin/supervisord"]

[root@foundation45 docker]# docker build -t rhel7:v3 .
Successfully built 8c385a139bf8

[root@foundation45 docker]# docker run -d --name vm1 -v /tmp/docker/web/:/var/www/html rhel7:v3
af7d9385b6896a786e856584d99d3032fd1c1c6ba6b7140a8d9d44ab58209e55

[root@foundation45 docker]# docker inspect vm1
                    "IPAddress": "172.17.0.2",

测试:

[root@foundation45 docker]# curl 172.17.0.2
<h1>www.westos.org</h1>
<h1>www.westos.org</h1>
<h1>www.westos.org</h1>
<h1>www.westos.org</h1>
<h1>www.westos.org</h1>

[root@foundation45 docker]# ssh -l root 172.17.0.2
The authenticity of host '172.17.0.2 (172.17.0.2)' can't be established.
ECDSA key fingerprint is 76:b7:46:70:20:b3:63:da:35:3f:bc:c0:c6:4c:83:f7.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.17.0.2' (ECDSA) to the list of known hosts.
root@172.17.0.2's password: 
-bash-4.2#

误区:

1.关于docker run的说明;

docker run <=> docker create + start  

docker run -d  --name vm1 nginx  打入后台
docker run -d  --name vm1 nginx bash  交互式

2.CMD 、ENTRYPOINT与RUN的区别:

  • CMD:容器启动,是可以被覆盖的;可以用来传参;
  • ENTRYPOINT:是不可被覆盖的,有些地方容器必须执行的地方用它;
  • RUN :装包,并执行脚本(大批量的);

(1)测试CMD:

[root@foundation45 docker]# mkdir test
[root@foundation45 docker]# cd test/
[root@foundation45 test]# vim Dockerfile

FROM rhel7
CMD echo "hello,world!"

[root@foundation45 test]# docker build -t rhel7:v4 .  
[root@foundation45 test]# docker run --rm rhel7:v4 
hello,world!
[root@foundation45 test]# docker run --rm rhel7:v4 echo westos  ##文件内容被覆盖
westos

(2)测试ENTRYPOINT:

[root@foundation45 test]# docker rmi rhel7:v4  ##删除镜像
Untagged: rhel7:v4
Deleted: sha256:eaebcb6107b2825a4428ac52c2a280a479af60db73f80473781205799319c9a3
[root@foundation45 test]# vim Dockerfile

FROM rhel7
ENTRYPOINT echo "hello,world!"

[root@foundation45 test]# docker build -t rhel7:v4 .
Successfully built c4143be5034c
[root@foundation45 test]# docker run --rm rhel7:v4 
hello,world!
[root@foundation45 test]# docker run --rm rhel7:v4 echo westos  ##结果没有被覆盖
hello,world!
[root@foundation45 test]# docker rmi rhel7:v4
[root@foundation45 test]# vim Dockerfile

FROM rhel7
ENTRYPOINT ["/bin/echo","hello"]
CMD ["world"]

[root@foundation45 test]# docker build -t rhel7:v4 .
[root@foundation45 test]# docker run --rm rhel7:v4 
hello world
[root@foundation45 test]# docker run --rm rhel7:v4 westos
hello westos
[root@foundation45 test]# vim Dockerfile 
[root@foundation45 test]# docker rmi rhel7:v4
[root@foundation45 test]# docker build -t rhel7:v4 .

FROM rhel7
ENV name westos
ENTRYPOINT echo "hello, $name"

[root@foundation45 test]# docker run --rm rhel7:v4 
hello, westos
[root@foundation45 test]# vim Dockerfile 
[root@foundation45 test]# docker build -t rhel7:v4 .

FROM rhel7
ENV name westos
ENTRYPOINT ["/bin/sh","-c","echo $name"]

[root@foundation45 test]# docker run --rm rhel7:v4 
westos

猜你喜欢

转载自blog.csdn.net/wangkana/article/details/81979534