Docker-10 端口转发、容器卷 、网络、数据存储

端口转发

image.png

使用端口转发解决容器端口访问问题

-p:创建应用容器的时候,一般会做端口映射,这样是为了让外部能够访问这些容器里的应用。可以用多个-p指定多个端口映射关系。 

mysql应用端口转发:

查看本地地址:

[root@yixuan ~]# ip a 
...
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:9c:bf:66 brd ff:ff:ff:ff:ff:ff
    inet 192.168.246.141/24 brd 192.168.246.255 scope global dynamic ens33
       valid_lft 5217593sec preferred_lft 5217593sec
    inet6 fe80::a541:d470:4d9a:bc29/64 scope link 
       valid_lft forever preferred_lft forever

运行容器:使用-p作端口转发,把本地3307转发到容器的3306,其他参数需要查看发布容器的页面提示

[root@yixuan ~]# docker pull daocloud.io/library/mysql:5.7
[root@yixuan ~]# docker run -d --name mysql1 -p 3307:3306  -e MYSQL_ROOT_PASSWORD=Qf@123! daocloud.io/library/mysql:5.7
a4327dbddf665b4302c549320bff869b8a027c2e1eead363d84ce5d06acf2698

-e MYSQL_ROOT_PASSWORD= 设置环境变量,这里是设置mysql的root用户的密码

通过本地IP:192.168.246.141的3307端口访问容器mysql1内的数据库,出现如下提示恭喜你

1.安装一个mysql客户端
[root@yixuan ~]# yum install -y mysql
2.登录
[root@yixuan ~]# mysql -uroot -p'Qf@123!' -h 192.168.246.141 -P3307
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.26 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]>
-P(大P):当使用-P标记时,Docker 会随机映射一个 32768~49900 的端口到内部容器开放的网络端口。如下:
[root@yixuan ~]# docker pull daocloud.io/library/redis
[root@yixuan ~]# docker images
REPOSITORY                   TAG        IMAGE ID            CREATED           SIZE
daocloud.io/library/redis    latest     598a6f110d01        2months ago       118MB
[root@yixuan ~]# docker run --name myredis -P -d daocloud.io/library/redis
ca06a026d84a0605d9a9ce6975389a79f4ab9a9a043a03f088cd909c1fe52e29
[root@yixuan ~]# docker ps 
CONTAINER ID        IMAGE                           COMMAND                  CREATED             STATUS              PORTS                               NAMES
ca06a026d84a        daocloud.io/library/redis       "docker-entrypoint.s…"   22 seconds ago      Up 21 seconds       0.0.0.0:32768->6379/tcp             myredis

从上面的结果中可以看出,本地主机的32768端口被映射到了redis容器的6379端口上,也就是说访问本机的32768端口即可访问容器内redis端口。

在别的机器上通过上面映射的端口32768连接这个容器的redis

[root@docker-server2 ~]# yum install -y redis
[root@docker-server2 ~]# redis-cli -h 192.168.246.141 -p 32768
192.168.246.141:32768> ping
PONG
192.168.246.141:32768>

容器卷

把本地宿主机上面的某一个目录挂载到容器里面的目录去。这两个目录都不用提前存在,会自动创建

新卷只能在容器创建过程当中挂载

[root@yixuan ~]# docker run -it --name testnginx -v /test:/test2 daocloud.io/library/nginx /bin/bash
root@86320e734cd1:/# ls
root@86320e734cd1:/# ctrl+p+q  #退出

测试:
[root@yixuan ~]# cd /test/
[root@yixuan test]# ls
[root@yixuan test]# touch a.txt 
[root@yixuan test]# cd
[root@yixuan ~]# docker exec -it testnginx /bin/bash
root@86320e734cd1:/# cd test2/
root@86320e734cd1:/test2# ls
a.txt

共享文件:
[root@yixuan ~]# mkdir /dir
[root@yixuan ~]# vim /dir/a.txt
123
[root@yixuan ~]# docker run -it --name testnginx2 -v /dir/a.txt:/dir1/a.txt daocloud.io/library/nginx /bin/bash
root@f899be627552:/# cat dir1/a.txt 
123
root@f899be627552:/#
注意:如果是共享文件,修改宿主机上面的文件内容,容器里面的文件不会同步更新,如果在容器里面进行修改文件,本地会同步。

共享其他容器的卷(其他容器用同一个卷):

[root@yixuan ~]# docker run -it --name testnginx1 --volumes-from testnginx daocloud.io/library/nginx /bin/bash
root@50e6f726335c:/# ls
bin   dev  home  lib64  mnt  proc  run   srv  test2  usr
boot  etc  lib   media  opt  root  sbin  sys  tmp    var
root@50e6f726335c:/# cd test2/
root@50e6f726335c:/test2# ls
a.txt

实际应用中可以利用多个-v选项把宿主机上的多个目录同时共享给新建容器:

比如:

# docker run -it -v /abc:/abc -v /def:/def 1ae9

部署centos7容器应用

镜像下载:

[root@yixuan ~]# docker pull daocloud.io/library/centos:7

systemd 整合:

因为 systemd 要求 CAPSYSADMIN 权限,从而得到了读取到宿主机 cgroup 的能力,CentOS7 中已经用 fakesystemd 代替了 systemd 。 但是我们使用 systemd,可用参考下面的 Dockerfile:
[root@yixuan ~]# mkdir test
[root@yixuan ~]# cd test/
[root@yixuan test]# vim Dockerfile
FROM daocloud.io/library/centos:7
MAINTAINER "soso"  soso@qq.com
ENV container docker

RUN yum -y swap -- remove fakesystemd -- install systemd systemd-libs
RUN yum -y update; yum clean all; \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;

VOLUME [ "/sys/fs/cgroup" ]

CMD ["/usr/sbin/init"]

这个Dockerfile删除fakesystemd 并安装了 systemd。然后再构建基础镜像:

[root@yixuan test]# docker build -t local/c7-systemd .

执行没有问题这就生成一个包含 systemd 的应用容器示例

[root@yixuan test]# docker images
REPOSITORY         TAG                 IMAGE ID            CREATED             SIZE
local/c7-systemd   latest              a153dcaa642e        6 minutes ago       391MB

为了使用像上面那样包含 systemd 的容器,需要创建一个类似下面的Dockerfile:

[root@yixuan test]# mkdir http
[root@yixuan test]# cd http/
[root@yixuan http]# vim Dockerfile
FROM local/c7-systemd
RUN yum -y install httpd; yum clean all; systemctl enable httpd.service
EXPOSE 80
CMD ["/usr/sbin/init"]

构建镜像:

[root@yixuan http]# docker build -t local/c7-systemd-httpd .

运行包含 systemd 的应用容器:

为了运行一个包含 systemd 的容器,需要使用--privileged选项, 并且挂载主机的 cgroups 文件夹。 下面是运行包含 systemd 的 httpd 容器的示例命令:

[root@yixuan http]# docker run --privileged -tid -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 80:80 local/c7-systemd-httpd

--privileged:授权提权。让容器内的root用户拥有正真root权限(有些权限是没有的)

注意:如果不加会运行在前台(没有用-d),可以用ctrl+p+q放到后台去

测试可用:

[root@yixuan http]# yum install -y elinks
[root@yixuan http]# elinks --dump http://192.168.246.141  #apache的默认页面
                                 Testing 123..

   This page is used to test the proper operation of the [1]Apache HTTP
   server after it has been installed. If you can read this page it means
   that this site is working properly. This server is powered by [2]CentOS.

再来个安装openssh-server的例子:

[root@yixuan http]# cd ..
[root@yixuan test]# mkdir ssh
[root@yixuan test]# cd ssh/
[root@yixuan ssh]# vim Dockerfile
FROM local/c7-systemd
RUN yum -y install openssh-server; yum clean all; systemctl enable sshd.service
RUN echo 1 | passwd --stdin root
EXPOSE 22
CMD ["/usr/sbin/init"]
[root@yixuan ssh]# docker build --rm -t local/c7-systemd-sshd .
[root@yixuan ssh]# docker run --privileged -tid -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 2222:22 local/c7-systemd-sshd
[root@yixuan ssh]# ssh 192.168.246.141 -p 2222
[root@ce1af52a6f6c ~]# 

docker数据存储位置

查看存储路径
[root@yixuan ~]# docker info | grep Root
 Docker Root Dir: /var/lib/docker
 
修改默认存储位置:
在dockerd的启动命令后面追加--data-root参数指定新的位置
[root@yixuan ~]# vim  /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --data-root=/data

[root@yixuan ~]# systemctl daemon-reload 
[root@yixuan ~]# systemctl restart docker

查看是否生效:
[root@yixuan ~]# docker info | grep Root
 Docker Root Dir: /data
 
 [root@yixuan ~]# cd /data/
[root@yixuan data]# ls
builder  buildkit  containers  image  network  overlay2  plugins  runtimes  swarm  tmp  trust  volumes

docker网络

容器网络分类

注:

面试用,用了编排之后就没有用了

查看当前网络:

[root@yixuan ~]# docker network list
NETWORK ID          NAME                DRIVER              SCOPE
9b902ee3eafb        bridge              bridge              local
140a9ff4bb94        host                host                local
d1210426b3b0        none                null                local

docker安装后,默认会创建三种网络类型,bridge、host和none

1、bridge:网络桥接

默认情况下启动、创建容器都是用该模式,所以每次docker容器重启时会按照顺序获取对应ip地址。

2、none:无指定网络

启动容器时,可以通过--network=none,docker容器不会分配局域网ip 

3、host:主机网络

 docker容器和主机共用一个ip地址。
 使用host网络创建容器:
[root@yixuan ~]# docker run -it --name testnginx2 --net host 98ebf73ab
[root@yixuan ~]# netstat -lntp | grep 80
tcp6       0      0 :::80                   :::*                    LISTEN      3237/docker-proxy

浏览器访问宿主ip地址

4、固定ip:

创建固定Ip的容器:

4.1、创建自定义网络类型,并且指定网段
[root@yixuan ~]# docker network create --subnet=192.168.0.0/16 staticnet
4efd309244c6ad70eda2d047a818a3aec5b162f5ca29fb6024c09a5efbf15854
通过docker network ls可以查看到网络类型中多了一个staticnet:
[root@yixuan ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
9b902ee3eafb        bridge              bridge              local
140a9ff4bb94        host                host                local
d1210426b3b0        none                null                local
4efd309244c6        staticnet           bridge              local
 4.2、使用新的网络类型创建并启动容器
 [root@yixuan ~]# docker run -itd --name userserver --net staticnet --ip 192.168.0.2 daocloud.io/library/centos:7
 通过docker inspect可以查看容器ip为192.168.0.2:
 [root@yixuan ~]# docker inspect userserver | grep -i ipaddress
            "SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "192.168.0.2",

关闭容器并重启,发现容器ip并未发生改变

异主容器互联

方式1、路由方式

小规模docker环境大部分运行在单台主机上,如果公司大规模采用docker,那么多个宿主机上的docker如何互联

image.png

Docker默认的内部ip为172.17.42.0网段,所以必须要修改其中一台的默认网段以免ip冲突。

注:docker版本为1.13
1.在docker-server1上面操作----192.168.246.141
[root@docker-server1 ~]# docker pull daocloud.io/library/centos
[root@docker-server1 ~]# vim /etc/sysconfig/docker-network
DOCKER_NETWORK_OPTIONS=--bip=172.17.0.1/16
[root@docker-server1 ~]# vim /etc/sysctl.conf
net.ipv4.ip_forward=1
[root@docker-server1 ~]# sysctl -p
[root@docker-server1 ~]# reboot
[root@docker-server1 ~]# docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
daocloud.io/library/centos   latest              0f3e07c0138f        3 weeks ago         220MB
[root@docker-server1 ~]# docker run -it --name centos 0f3e07c0138f /bin/bash
[root@ef1a4d6be97f /]#
[root@docker-server1 ~]# docker inspect centos | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",
===============================================
2.docker-server2(192.168.246.143)上:
[root@docker-server2 ~]# vim /etc/sysconfig/docker-network
DOCKER_NETWORK_OPTIONS=--bip=172.18.0.1/16
[root@docker-server2 ~]# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
[root@docker-server2 ~]# sysctl -p
[root@docker-server2 ~]# reboot
[root@docker-server2 ~]# systemctl daemon-reload
[root@docker-server2 ~]# systemctl restart docker
[root@docker-server2 ~]# docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
daocloud.io/library/centos   latest              0f3e07c0138f        3 weeks ago         220MB
[root@docker-server2 ~]# docker run -it --name centos 0f3e07c0138f /bin/bash 
[root@c84a8c704d03 /]#
[root@docker-server2 ~]# docker inspect c | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.18.0.2",
                    "IPAddress": "172.18.0.2",

添加路由:

[root@docker-server1 ~]# route add -net 172.18.0.0/16 gw 192.168.246.143
[root@docker-server2 ~]# route add -net 172.17.0.0/16 gw 192.168.246.141

验证:

image.png

现在两台宿主机里的容器就可以通信了。

方式二、open vswitch

如果要在生产和测试环境大规模采用docker技术,首先就需要解决不同物理机建的docker容器互联问题。

centos7环境下可以采用open vswitch实现不同物理服务器上的docker容器互联

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。