docker阶段03 docker容器hosts文件,DNS, 查docker空间占用, 部署自动化运维平台spug, 查docker run启动参数命令, Dockerfile多阶段构建, 容器数据管理, 容器通讯, 修改容器ip(网桥配置), 网络模型

容器内部的hosts文件

容器会自动将容器的ID加入自已的/etc/hosts文件中,并解析成容器的IP

范例: 修改容器的 hosts文件

[root@ubuntu1804 ~]#docker run -it --rm --add-host www.wangxiaochun.com:6.6.6.6 --add-host www.wang.org:8.8.8.8   busybox
/ # cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
6.6.6.6 www.wangxiaochun.com
8.8.8.8 www.wang.org
172.17.0.2 449bf0468efd

指定容器 DNS

容器的dns服务器,默认采用宿主机的dns 地址,可以用下面方式指定其它的DNS地址
修改宿主机的DNS地址址配置
在容器启动时加选项 --dns=x.x.x.x
在/etc/docker/daemon.json 文件中指定

 

查看docker空间磁盘占用情况, 清理不再使用的镜像

#查看docker空间磁盘占用情况
[root@ubuntu ~]#docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          2         0         85.25MB   85.25MB (100%)
Containers      0         0         0B        0B
Local Volumes   0         0         0B        0B    #
Build Cache     0         0         0B        0B

#清除不再使用的镜像
[root@ubuntu1804 ~]#docker system prune -f -a

 

实战案例: 利用 Docker 快速部署自动化运维平台

个人开发的小项目

[root@ubuntu1804 ~]# docker pull registry.aliyuncs.com/openspug/spug

[root@ubuntu1804 ~]#docker run -d --restart=always --name=spug -p 80:80 registry.aliyuncs.com/openspug/spug

#初始化(通过docker内部作者写的init_spug程序)
[root@ubuntu1804 ~]#docker exec spug init_spug admin 123456

 

查看docker run启动参数命令

忘记之前启动一个容器的启动命令是什么,现在需要找回来 docker run 的运行参数,可以使用 runlike 工具实现

https://github.com/lavie/runlike

安装 runlike

#安装方式1: pip
apt install -y python3-pip
pip3 install runlike
#安装方法2: by docker
alias runlike="docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike"

#范例
[root@ubuntu ~]#runlike -p spug    #根据返回选有用的启动参数
docker run --name=spug \
    --hostname=cbd8c758f8a4 \
    --mac-address=02:42:ac:11:00:02 \
    --network=bridge \
    -p 80:80 \
    --restart=always \
    --runtime=runc \
    --detach=true \
    registry.aliyuncs.com/openspug/spug

 

Dockerfile多阶段构建

属于dockerfile构建的优化,能节省空间

先构建个镜像,然后再构建个镜像把之前镜像生成的文件拷贝过来,前面那个镜像就不要了

go编译完的文件,不需要go就能运行
也就是说构建用一个镜像,运行用另一个镜像
这样可以节省空间

#优化
[root@ubuntu2004 go-hello]#vim Dockerfile
FROM golang:1.18-alpine as builder
COPY hello.go /opt
WORKDIR /opt
RUN go build hello.go 

FROM alpine:3.15.0
#FROM scratch
COPY --from=builder /opt/hello /hello    #只保留上面镜像的文件
#COPY --from=0 /opt/hello /hello    #from=0可以指代前一次构建
CMD ["/hello"]

[root@ubuntu2004 go-hello]#bash build.sh v2.0
[root@ubuntu2004 go-hello]#docker run --name hello2 go-hello:v2.0
hello, world

#进一步优化
#实际上go编译后依赖内核就能运行,所以可以镜像内不放系统
[root@ubuntu2004 go-hello]#vim Dockerfile
FROM golang:1.18-alpine as builder
COPY hello.go /opt
WORKDIR /opt
RUN go build hello.go 

#FROM alpine:3.15.0
FROM scratch    #空镜像
COPY --from=builder /opt/hello /hello
#COPY --from=0 /opt/hello /hello
CMD ["/hello"]

[root@ubuntu2004 go-hello]#bash build.sh v3.0
[root@ubuntu2004 go-hello]#docker run --name hello2 go-hello:v3.0
hello, world

#比较三次构建的结果
[root@ubuntu2004 go-hello]#docker images go-hello
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
go-hello     v3.0     6b12922337d4   4 minutes ago    1.76MB
go-hello     v2.0     9d6b2abc190a   28 seconds ago   7.35MB
go-hello     v1.0     54c7203e3a60   5 minutes ago   330MB

范例: 多阶段构建 Vue 前端项目

FROM node:14.17.6 AS build
COPY . /opt/vue
WORKDIR /opt/vue
RUN sed -i 's/config.headers/\/\/&/' src/api/request.js
RUN npm install && npm run build

FROM nginx:1.20.1
COPY --from=build /opt/vue/dist /opt/vue/dist
COPY nginx.conf /etc/nginx/nginx.conf
CMD ["nginx", "-g","daemon off;"]

 

容器的数据管理介绍

Docker容器的分层

容器的数据分层目录

1.LowerDir: image 镜像层,即镜像本身,只读
2.UpperDir: 容器的上层,可读写 ,容器变化的数据存放在此处
3.MergedDir: 容器的文件系统,使用Union FS(联合文件系统)将lowerdir 和 upperdir 合并完成
后给容器使用,最终呈现给用户的统一视图
4.WorkDir: 容器在宿主机的工作目录,挂载后内容会被清空,且在使用过程中其内容用户不可见

容器数据持久保存方式

1. 卷(Volume) 
2. 绑定挂载(Bind Mount)
3. tmpfs 挂载    #放入内存,做不到真正的持久化(容器停了或删了,数据就没了)
    #针对性能高要求,又不想真正持久化的时候用这种方式
#范例: tmpfs 挂载
#把容器的/data路径挂载的宿主机的内存文件中(写入/data速度快)
[root@ubuntu2204 ~]#docker run -d --tmpfs /data --name test wangxiaochun/pod-test:v0.1

数据卷(data volume)

方式1: 绑定挂载(Bind Mount)

#指定宿主机目录或文件进行映射: 
-v   <宿主机绝对路径的目录或文件>:<容器目录或文件>    #将宿主机目录挂载容器目录,两个目录都可自动创建
#如果是文件进行的话,要写路径(相对路径),如: ./nginx.conf:/etc/nginx/nginx.conf

方式2: 匿名卷 (不推荐)

方式3: 命名卷

dockerfile中定义了匿名卷可以接用命名卷的方式启动(就不是匿名卷了)

#命名卷将固定的存放在/var/lib/docker/volumes/<卷名>/_data
#注意:如果初始容器中有旧数据,将被复制到宿主机数据卷目录

-v <卷名>:<容器目录路径>
#可以通过以下命令事先创建,如可没有事先创建卷名,docker run时也会自动创建卷
docker volume create <卷名>

#示例:    会创建/var/lib/docker/volumes/vol1/_data目录进行映射
docker run -d  -p 80:80 --name nginx01 -v vol1:/usr/share/nginx/html nginx

#查看所有卷
docke volume ls

查看数据卷的挂载关系

docker inspect 容器名
看Mounts列

 

数据卷容器

 实现

 使用数据卷容器

#第一个容器正常挂,后面的容器直接使用第一个容器的(挂几个就是几个),用命令--volumes-from
--volumes-from <数据卷容器>

例:
#创建一个数据卷容器 Server(即使没起来,也不影响后面镜像使用数据卷容器挂载)
[root@ubuntu1804 ~]#docker run -d --name volume-server -v /data/bin/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v /data/testapp:/data/tomcat/webapps/testapp   tomcat-web:app1

#启动多个数据卷容器 Client
[root@ubuntu1804 ~]#docker run -d --name client1 --volumes-from volume-server -p 8081:8080 tomcat-web:app1
fe6ce0548dfee924cd39a8d86d5ed0e8ce9ea65323742f1336fa3b002c1b4a8c
[root@ubuntu1804 ~]#docker run -d --name client2 --volumes-from volume-server -p 8082:8080 tomcat-web:app1
10397838df9a489d7af2112850d4285bff5c2c262ea05cc9c5fb265af538f2c8

 

容器间的通信

修改默认docker0网桥的网络配置

默认docker后会自动生成一个docker0的网桥,使用的IP是172.17.0.1/16,可能和宿主机的网段发生冲突, 可以将其修改为其它网段的地址,避免冲突

#当内网地址刚好与网桥地址172.17一样,这时修改

#范例: 将docker0的IP修改为指定IP
#方法1
[root@ubuntu1804 ~]#vim /etc/docker/daemon.json 
[root@ubuntu1804 ~]#cat /etc/docker/daemon.json
{
   "bip": "192.168.100.1/24",
  "registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"]
}
[root@ubuntu1804 ~]#systemctl restart docker.service

#方法2
[root@ubuntu1804 ~]#vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock 
--bip=192.168.100.1/24 
[root@ubuntu1804 ~]#systemctl daemon-reload 
[root@ubuntu1804 ~]#systemctl restart docker.service

#注意两种方法不可混用,否则将无法启动docker服务

#验证结果
[root@ubuntu1804 ~]#ip a

容器名称互联

通过容器名称互联

因为docker的ip会变动,通过名称连接保证ip变动也能连接

docker run 创建容器,可使用--link选项实现容器名称的引用,其本质就是在容器内的/etc/hosts中添加--link后指定的容器的IP和主机名的对应关系,从而实现名称解析

--link list                          #Add link to another container
格式:  
docker run --name <容器名称>         #先创建指定名称的容器
docker run --link <目标通信的容器ID或容器名称>     #再创建容器时引用上面容器的名称

#
1. 先创建第一个指定容器名称的容器
[root@ubuntu1804 ~]#docker run -it --name server1 --rm alpine:3.11 sh / # cat /etc/hosts
2. 新建第二个容器时引用第一个容器的名称
[root@ubuntu1804 ~]#docker run -it --rm --name server2 --link server1 alpine:3.11 sh
#--link server1: 把server1的名称ip地址放到host文件中
/ # cat /etc/hosts    #查看内部的host文件有server1
...
172.17.0.2 server1 cdb5173003f5

通过自定义容器别名互联

名称有可能也会变,通过别名连接

docker run --name <容器名称> 
#先创建指定名称的容器
docker run --name <容器名称> --link <目标容器名称>:"<容器别名1> <容器别名2> ..." 
#给上面创建的容器起别名,来创建新容器

#范例: 创建第三个容器,引用前面创建的容器,并起别名
[root@ubuntu1804 ~]#docker run -it --rm --name server3 --link server1:server1-alias alpine:3.11 sh
/ # cat /etc/hosts
172.17.0.2 server1-alias cdb5173003f5 server1

#ping容器名或别名都行
/ # ping server1
/ # ping server1-alias

 

网络模式指定

docker会自动开启ip_forward, ip_forward为1。默认是bridge模式

1.Host 模式

效率高, 很少用, 相当于名称空间不隔离了, 容器和宿主机统一ip地址, 端口互相会冲突

2.None 模式

很少用, 没有外部网络

#例 (端口暴露也没用,无法和宿主机通讯)
[root@ubuntu1804 ~]#docker run -d --network none --name web1-none nginx-centos7-base:1.6.1

3.Container 模式

容器和容器之间共享名称空间,容器ip地址相同(只是网络不独立,其他像进等都是独立的)

#方法1
[root@ubuntu2004 ~]#docker run -d -p 80:80 --name wordpress -v /data/wordpress:/var/www/html --restart=always wordpress:php7.4-apache
[root@ubuntu2004 ~]#docker run --network container:wordpress -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=123456 --name mysql -d -v /data/mysql:/var/lib/mysql --restart=always mysql:8.0.29-oracle

#方法2
#MySQL提前为wordpress暴露端口
[root@ubuntu2004 ~]#docker run -d -p 80:80 -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=123456 --name mysql --restart=always mysql:8.0.29-oracle
[root@ubuntu2004 ~]#docker run -d --network container:mysql --name wordpress --restart=always wordpress:php7.4-apache

#注意:数据库主机地址为127.0.0.1或wordpress容器的IP,不支持localhost

4.自定义网络模式

本质是是bridge,但是是自定义网络
独有特性: 自定义网络可以通过容器名进行通讯
创建自定义网络: 
docker network create -d <mode> --subnet <CIDR> --gateway <网关> <自定义网络名称>
#注意mode不支持host和none,默认是bridge模式
-d <mode> 可省略,默认为bridge

#引用自定义网络
docker run --network <自定义网络名称> <镜像名称>
docker run --net <自定义网络名称> --ip <指定静态IP> <镜像名称>
#注意:静态IP只支持自定义网络模型

#指定自定义网络中的容器的别名
docker run --network <自定义网络名称> --network-alias list <镜像名称>

#删除自定义网络
doccker network rm <自定义网络名称或网络ID>

#例:创建自定义的网络
[root@ubuntu1804 ~]#docker network create -d bridge --subnet 172.27.0.0/16 --
gateway 172.27.0.1 test-net
c90dee3b7937e007ed31a8d016a9e54c0174d0d26487b154db0aff04d9016d5b
[root@ubuntu1804 ~]#docker network ls
NETWORK ID         NAME               DRIVER             SCOPE
cabde0b33c94       bridge             bridge             local
cb64aa83626c       host               host               local
10619d45dcd4       none               null               local
c90dee3b7937       test-net           bridge             local

[root@ubuntu1804 ~]#docker inspect test-net
[root@ubuntu1804 ~]#ip a
#新加了一个网桥
[root@ubuntu1804 ~]#brctl show
bridge name bridge id STP enabled interfaces
br-00ab0f2d29e8 8000.024245e647ec no 
docker0 8000.0242cfd26f0a no 

#利用自定义的网络创建容器
[root@ubuntu1804 ~]#docker run -it --rm --network test-net alpine sh

 

同一个宿主机之间不同网络的容器通信

开两个容器,一个使用自定义网络容器,一个使用默认brideg网络的容器,默认因iptables规则导致无法通信

本质是iptables导致的

#通过解决docker network connect 实现同一个宿主机不同网络的容器间通信

#将CONTAINER连入指定的NETWORK中,使此CONTAINER可以与NETWORK中的其它容器进行通信
docker network connect [OPTIONS] NETWORK CONTAINER
#本质上相当于又创建了一张网卡,ip在对方网段里

#
#让默认网络中容器test1可以连通自定义网络test-net的容器test2
[root@ubuntu1804 ~]#docker network connect test-net test1
#让自定义网络中容器test2可以连通默认网络的容器test1
[root@ubuntu1804 ~]#docker network connect bridge test2

 

实现跨宿主机的容器之间网络互联

保证两个宿主机的容器网段不同, 了解原理, 生产中使用k8s解决

 

posted @ 2024-09-21 17:54  战斗小人  阅读(44)  评论(0编辑  收藏  举报