Docker 进阶篇(二)数据管理,网络管理,使用Dockerfile构建镜像

    技术2022-07-14  60

    Docker 进阶篇(二)数据管理,网络管理,使用Dockerfile构建镜像

    数据管理使用现有本地目录挂载使用Docker Volumes挂载使用数据卷容器挂载 网络管理外部访问容器Docker 的网络模式Host模式Container模式none模式bridge模式 配置容器使用宿主机网段IP 使用Dockerfile构建镜像Dockerfile常用指令

    数据管理

    Docker挂载数据卷的形式有一下三种

    使用现有本地目录自定义挂载使用Docker Volumes挂载使用数据卷容器挂载

    使用现有本地目录挂载

    ## 命令格式为 -v /宿主机目录/:/容器目录/

    ##在宿主及上手动创建目录 [root@node_1 ~]# mkdir /data [root@node_1 ~]# echo "Nginx test" >> /data/index.html ##运行容器测试 [root@node_1 ~]# docker run -d -p 80:80 -v /data/:/usr/share/nginx/html --name nginx_test nginx:latest 3151524a01b51c76ae0bfd50e79f63edd25a6bfeed806a065aabe4209fe834e4 [root@node_1 ~]# curl 127.0.0.1 Nginx test [root@node_1 ~]# echo "Nginx test 2" > /data/index.html [root@node_1 ~]# curl 127.0.0.1 Nginx test 2 ##删除容器测试 [root@node_1 ~]# docker stop nginx_test nginx_test [root@node_1 ~]# docker rm nginx_test nginx_test [root@node_1 ~]# ls /data/ index.html ##宿主机节点数据不会受到影响

    使用Docker Volumes挂载

    ## 命令格式为 -v /容器目录/

    [root@node_1 ~]# docker run -d -p 80:80 --name nginx_test -v /usr/share/nginx/html nginx:latest d41c1762134ecfa4f19874a0173d17fe833f8d76e7fa44c163a05c442795f141 ##查看容器挂载目录对应关系 [root@node_1 ~]# docker inspect -f {{.Mounts}} nginx_test [{volume 8bc32cf5b71faf78552fd9a5fa6af95e07c5a3ea7f24d5357e577acc4a07a6f6 /var/lib/docker/volumes/8bc32cf5b71faf78552fd9a5fa6af95e07c5a3ea7f24d5357e577acc4a07a6f6/_data /usr/share/nginx/html local true }] ##写入文件测试 [root@node_1 ~]# echo "Nginx test" > /var/lib/docker/volumes/8bc32cf5b71faf78552fd9a5fa6af95e07c5a3ea7f24d5357e577acc4a07a6f6/_data/index.html [root@node_1 ~]# curl 127.0.0.1 Nginx test ##删除容器测试 [root@node_1 ~]# docker stop nginx_test nginx_test [root@node_1 ~]# docker rm nginx_test nginx_test [root@node_1 ~]# ls /var/lib/docker/volumes/8bc32cf5b71faf78552fd9a5fa6af95e07c5a3ea7f24d5357e577acc4a07a6f6/_data/ 50x.html index.html [root@node_1 ~]# docker volume ls DRIVER VOLUME NAME local 8bc32cf5b71faf78552fd9a5fa6af95e07c5a3ea7f24d5357e577acc4a07a6f6 ##Docker Volumes数据不会受到影响 ##若要删除容器并且删除Volume 可在docker rm 后面加上-v参数 [root@node_1 ~]# docker run -d -p 80:80 --name nginx_test -v /usr/share/nginx/html nginx:latest da053b579e13bcd05710b2e316b8bb0183a5e0d577706d487f6ce11875dda2e3 [root@node_1 ~]# docker volume ls DRIVER VOLUME NAME local d30bff9f4617a395bfd7c5d9c4f4aa76971ff329fb33c02f779f13c58dbeff78 [root@node_1 ~]# docker stop nginx_test nginx_test [root@node_1 ~]# docker rm -v nginx_test nginx_test [root@node_1 ~]# docker volume ls DRIVER VOLUME NAME ##如果使用 docker run -v 启动的容器被删除时没有加-v参数,那么会在主机上会遗留下来孤单的卷。 ##可以使用下面的简单方法来做清理(在删除是先看一下卷中的数据是否无用,确认无用后再进行操作): [root@node_1 ~]# for i in `docker volume ls -qf dangling=true` ;do docker volume rm $i ;done

    使用数据卷容器挂载

    有时候,我们需要多个容器之间相互共享数据,类似于linux里面的NFS,所以就可以搭建一个专门的数据卷容器,然后其他容器直接挂载该数据卷。当然在创建数据卷容器的时候也可以使用本地已经创建好的目录

    ##创建数据卷容器 [root@node_1 ~]# docker run -itd -v /data/ --name volume_data centos:6 bash 599f5373dc17ca7f301d3e8dc6c25b17a089b430dfab6b1e92ca44997f115821 [root@node_1 ~]# docker exec -it volume_data bash [root@599f5373dc17 /]# echo "test" >/data/test ##创建客户端关联 [root@node_1 ~]# docker run -itd --volumes-from volume_data --name client centos:6 bash 0547c0c212941998cba58310c6bcf4b0eee791fc6fa24f5de9b923766c76eb82 [root@node_1 ~]# docker exec -it client cat /data/test test

    网络管理

    外部访问容器

    外部访问容器可以在运行容器时指定-p 参数映射,如果需要同时映射多个端口,只需增加多个-p参数即可

    ##运行容器 ##将本地80端口映射到容器的80端口上 [root@node_1 ~]# docker run -d -p 80:80 --name nginx nginx:latest [root@node_1 ~]# curl 127.0.0.1 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body>

    Docker 的网络模式

    Host模式 :使用docker run时使用–net=host指定,共享宿主机的IP地址Container模式 :使用–net=container:container_id/container_name,多个容器使用共同的网络,看到的ip是一样的none模式 :使用–net=none指定,这种模式下,不会配置任何网络bridge模式 :使用–net=bridge指定,Dcoker 网络的默认模式。这种模式会为每个容器分配一个独立的Network Namespace。类似于vmware的nat网络模式。同一个宿主机上的所有容器会在同一个网段下,相互之间是可以通信的。

    Host模式

    使用docker run时使用–net=host指定,共享宿主机的IP地址,无需加-p参数映射端口,但需要注意在运行多个容器使用host模式时ip端口冲突的问题

    [root@node_1 ~]# docker run -itd --net=host --name host centos:6 bash 68ccd7753e853531db1b6c69aa7a0fbf7f5ed068ed8456db12ea449812e295a1 [root@node_1 ~]# docker exec -it host ifconfig ens33 Link encap:Ethernet HWaddr 00:0C:29:0C:D9:24 inet addr:192.168.100.150 Bcast:192.168.100.255 Mask:255.255.255.0 inet6 addr: fe80::97ef:3c22:1c0e:3784/64 Scope:Link [root@node_1 ~]# docker run -d --net=host --name nginx nginx:latest f3a4caba37fb162fe59b5cb2e1d1b8f13d847b12ef3d6556701cd4bfe6676c7d [root@node_1 ~]# curl 192.168.100.150 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body>

    Container模式

    使用–net=container:container_id/container_name,多个容器使用共同的网络,看到的ip是一样的

    ##运行一个Nginx容器 [root@node_1 ~]# docker run -d --name nginx_server nginx:latest af34bf9e6a7fc7d5c3aa765a362761091fefb2a5fe53ff5bc51585ada6a1efb6 ##在运行一个客户端容器,访问本地端口的80端口,看能否通信 [root@node_1 ~]# docker run -it --net=container:nginx_server --name nginx_server_client centos:6 curl 127.0.0.1 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> ##运行的client 容器里面没有启动http服务,理论上容器和容器之间是隔离的,但是client容器使用--net参数链接到了nginx_server_client,两个容器的ip是一样的,所以在client端能够访问到本地的127.0.0.1 的80端口

    none模式

    使用–net=none指定,这种模式下,不会配置任何网络,适用于启动容器做数据备份,或者启动不需要网络支持的容器

    由于用处较少,在这里不做展示

    bridge模式

    使用–net=bridge指定,Dcoker 网络的默认模式。这种模式会为每个容器分配一个独立的Network Namespace。类似于vmware的nat网络模式。同一个宿主机上的所有容器会在同一个网段下,相互之间是可以通信的。

    ##查看本地docker 网卡信息 [root@node_1 ~]# ip a 3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:1a:ae:22:e8 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:1aff:feae:22e8/64 scope link valid_lft forever preferred_lft forever ##运行两个容器验证ip地址是否在同一网段时候能工通过内部ip进行通信 [root@node_1 ~]# docker run -d --name c1 nginx:latest bash 5eda666dd0c0e8e91470c5546e2042f4876ea45f262e67102f30e542ba5886bd [root@node_1 ~]# docker run -d --name c2 nginx:latest bash 3a4790af3117d09bf06638b0bcb7510b598734b4e213d14fa4ee46ea72bec8ce ##查看两个容器的ip地址 [root@node_1 ~]# docker inspect c1 |grep "IPAddress" "SecondaryIPAddresses": null, "IPAddress": "172.17.0.7", "IPAddress": "172.17.0.7", [root@node_1 ~]# docker inspect c2 |grep "IPAddress" "SecondaryIPAddresses": null, "IPAddress": "172.17.0.6", "IPAddress": "172.17.0.6", ##验证在容器内部两个容器是能够通过内网IP进行通信 [root@node_1 ~]# docker exec -it c2 curl 172.17.0.7 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body>

    配置容器使用宿主机网段IP

    为了使本地网络中的机器和Docker容器更方便的通信,我们经常会有将Docker容器配置到和主机同一网段的需求。这个需求其实很容易实现,我们只要将Docker容器和宿主机的网卡桥接起来,再给Docker容器配上IP就可以了。

    ##添加桥接网卡 [root@node_1 ~]# cd /etc/sysconfig/network-scripts/ [root@node_1 network-scripts]# cp ifcfg-ens33 ifcfg-br0 [root@node_1 network-scripts]# vi ifcfg-ens33 删除 IPADDR,GATEWAY,NETMASK,DNS1 增加BRIDGE=br0 [root@node_1 network-scripts]# vi ifcfg-br0 修改NAME=br0 修改TYPE=Bridge 修改DEVICE=br0 [root@node_1 network-scripts]# systemctl restart network ##安装pipwork工具 [root@node_1 ~]# git clone https://github.com/jpetazzo/pipework [root@node_1 ~]# cp pipework/pipework /usr/bin/ ##运行容器 [root@node_1 ~]# docker run -itd --net=none --name net-br centos:6 bash b0c798d1714ffa1d46e3579c37451f81fc52b46202523644c02b19a40154a163 ##为容器分配ip地址 [root@node_1 ~]# pipework br0 net-br 192.168.100.151/24@192.168.100.2 ## net-br为刚才运行容器的name,151为容器的ip,@后面的ip为网关ip [root@node_1 ~]# docker exec -it net-br bash [root@b0c798d1714f /]# ifconfig eth1 Link encap:Ethernet HWaddr D2:0A:3E:EB:66:86 inet addr:192.168.100.151 Bcast:192.168.100.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:12 errors:0 dropped:0 overruns:0 frame:0 TX packets:1 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:1520 (1.4 KiB) TX bytes:42 (42.0 b)

    在宿主机上ping测试一下,或者在其他同网段机器中测试

    使用Dockerfile构建镜像

    之前有介绍过在容器里面操作然后通过docker commit命令保存容器状态,相当于是一种容器的“快照”,里面包括了容器正在运行时所产生的数据,增加了镜像的大小 而通过Dockerfile的形式构建镜像的话他可以使用指定的容器来进行构建镜像,里面也就不会存在一些垃圾数据导致镜像文件过大的问题

    Dockerfile常用指令

    FROM # 所使用的基础镜像,一切从这里开始构建 MAINTAINER # 镜像信息,可自定义 ENV # 构建的时候设置环境变量,跟 -e 是一个意思 RUN # 镜像构建的时候所需要在容器中运行的命令 ADD # 将本地的一个文件或目录拷贝到容器的某个目录里 COPY # 类似ADD,将我们文件拷贝到镜像中 WORKDIR # 镜像的工作目录 VOLUME # 挂载的目录,可选,在运行容器的时候可以手动添加-v选项 EXPOSE # 容器所需暴露的端口 CMD # 指定这个容器启动时要执行的命令,只有最后一个命令会生效,可被docker run命令最后跟的参数替代 USER # 指定容器内部运行的用户 ONBUILD # 当构建一个被继承DockerFile 这个时候就会运行ONBUILD的指令。触发指令 ENTRYPOINT # 指定这个容器启动的时候要执行的命令,只有最后一个命令会生效,不可被docker run命令最后跟的参数替代,但可以作为ENTRYPOINT 命令的最后一个参数 假如我定义 ENTRYPOINT [“echo”, “test”] 我运行容器: docker run -it xmtao 123 则会输出 test 123 ,这相当于容器在启动时执行命令 echo test 123

    使用Dockerfile的形式简单构建一个NGINX

    ##创建Nginx的Dockerfile [root@node_1 ~]# mkdir Nginx [root@node_1 ~]# cd Nginx [root@node_1 Nginx ]# vi Dockerfile #使用基于centos6的镜像制作 FROM centos:6 #容器所暴露端口 EXPOSE 80 #安装编译工具 RUN yum -y install gcc-c++ gcc wget #下载依赖包,编译安装 RUN wget https://sourceforge.net/projects/pcre/files/pcre/8.42/pcre-8.42.tar.gz/download -O pcre-8.42.tar.gz RUN tar zxf pcre-8.42.tar.gz RUN cd /pcre-8.42 &&./configure && make && make install && cd / RUN wget http://www.zlib.net/zlib-1.2.11.tar.gz RUN tar zxf zlib-1.2.11.tar.gz RUN cd /zlib-1.2.11 && ./configure && make && make install && cd / #下载nginx 进行编译安装 RUN wget http://nginx.org/download/nginx-1.16.1.tar.gz RUN tar zxf nginx-1.16.1.tar.gz RUN cd /nginx-1.16.1 && ./configure --prefix=/usr/local/nginx --with-pcre=/pcre-8.42 --with-zlib=/zlib-1.2.11 && make && make install #删除无用压缩包 RUN rm -rf /pcre-8.42.tar.gz && rm -rf /zlib-1.2.11.tar.gz && rm -rf nginx-1.16.1.tar.gz #将当前目录的index.html 添加到 /usr/local/nginx/html/ 下,并命名为index.html ADD ./index.html /usr/local/nginx/html/index.html #容器启动所执行的命令 ENTRYPOINT ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"] [root@node_1 Nginx ]# echo "Nginx Test" > index.html ##构建镜像 [root@node_1 Nginx ]# docker build -t mynginx:1.16.1 . ##构建成功后查看大小 [root@node_1 Nginx ]# docker images |grep mynginx mynginx 1.16.1 37a41c1d0a03 5 minutes ago 529MB ##运行测试 docker run -d --p 80:80 --name mynginx mynginx:1.16.1 [root@node_1 Nginx ]# curl 127.0.0.1 Nginx Test
    Processed: 0.010, SQL: 9