容器和物理机直接运行相比缺点
1性能
2隔离性,管理不方便 docker exec
3排错方法:docker logs;docker exec; docker 前台运行;docker ps -a ;cat /var/log/syslog;message
上期·总览
FROM 指定
LABEL 标签
ENV 变量
COPY 复制 解压打包在可
ADD 复制
RUN 运行Linux命令
ENTRYPOINT ["init.sh"] 和CMD相似金蝉推敲 ,通常用于初始化环境 脚本
CMD ["app"] 第2遍运行
EXPOSE 80 声明 docker run -P xxxxx:80 docker run -p xxx:yyy 端口声明,P默认引用p盖
目录
修改默认docker0(172.17.0.1)网桥的网络配置
无聊小知识:修改iptables实现同一宿主机上的不同网络的容器间通信
添加静态路由和iptables规则 (生产中没法用讲原理而已)
定制镜像,需要先有一个基础镜像,在这个基础镜像上进行定制。
FROM 就是指定基础镜像,此指令通常必需放在Dockerfile文件第一个非注释行。后续的指令都是运行于此基准镜像所提供的运行环境
- ARG CODE=22.04-20221017-v1.0
- FROM ubuntu:${CODE}
- ENV VERSTON="1.22.0"
- ENV NGINX_INSTALL_DIR="/web/nginx"
- LABEL Author=weizhaohui version=nginx-${VERSTON}
在容器中创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等,默认会将宿主机上的目录挂载至VOLUME 指令指定的容器目录。即使容器后期被删除,此宿主机的目录仍会保留,从而实现容器数据的持久保存
名字乱码没啥用,有比没有好
/var/lib/docker/volumes/
/_data
没运行时


为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录,当容器运行后,进入容器内WORKDIR指定的默认目录
WORKDIR 指定工作目录(或称当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会自行创建
WORKDIR 来代替cd的效果 在目录中切换文件是没法子集体的 他切换后,后面的文件就是基于他的基础上了
和CMD他俩在一起用,文件调转转换没法自用,如果我做错了,欢迎指点


可以用来配置当构建当前镜像的子镜像时,会自动触发执行的指令,但在当前镜像构建时,并不会执行,即延迟到子镜像构建时才执行
这玩意简单来说,你创建一个镜像在里面写入ONBUILD RUN rm -rf /*,别人引用你的镜像来做他自己的镜像的时候就会在电脑上执行 删根!!!或者别的命令随你怎么写~~~~
本人就是打比喻~~~



总结:docker需要root的权限才能起来
检查容器的健康性
-fs的理解

在里面输入命令

重新启动查看 
把首页删了就报错了,然后没了,后期在K8S博客中会有用到,欢迎关注
官方文档: https://docs.docker.com/engine/reference/builder/#dockerignore-file
与.gitignore文件类似,生成构建上下文时Docker客户端应忽略的文件和文件夹指定模式
.dockerignore 使用 Go 的文件路径规则 filepath.Match
参考链接: https://golang.org/pkg/path/filepath/#Match
- # #以#开头的行为注释
- * #匹配任何非分隔符字符序列
- ? #匹配任何单个非分隔符
- \\ #表示 \
- ** #匹配任意数量的目录(包括零)例如,**/*.go将排除在所有目录中以.go结尾的所有文件,包括构
- 建上下文的根。
- ! #表示取反,可用于排除例外情况
范例:
#排除 test 目录下的所有文件
test/*
#排除 md 目录下的 xttblog.md 文件
md/xttblog.md
#排除 xttblog 目录下的所有 .md 的文件
xttblog/*.md
#排除以 xttblog 为前缀的文件和文件夹
xttblog?
#排除所有目录下的 .sql 文件夹
**/*.sql
#除了README的md不排外,排除所有md文件,但不排除README-secret.md
*.md
!README*.md
README-secret.md
#除了所有README的md文件以外的md都排除
*.md
README-secret.md
!README*.md
data 是指的镜像文件里面的,别绕就去

在当前页面创建文件
![]()
排除什么不考文件

卷里面的东西 ,有些已经排除,有些没有

docker build命令使用Dockerfile文件创建镜像
- docker build [OPTIONS] PATH | URL | -
- 说明:
- PATH | URL | - #可以使是本地路径,也可以是URL路径。若设置为 - ,则从标准输入获取
- Dockerfile的内容
- -f, --file string #Dockerfile文件名,默认为 PATH/Dockerfile
- --force-rm #总是删除中间层容器,创建镜像失败时,删除临时容器
- --no-cache #不使用之前构建中创建的缓存
- -q --quiet=false #不显示Dockerfile的RUN运行的输出结果
- --rm=true #创建镜像成功时,删除临时容器
- -t --tag list #设置注册名称、镜像名称、标签。格式为 <注册名称>/<镜像名称>:<标签>(标签
- 默认为latest)
docker history 镜像ID


有状态的协议
有状态协议就是就通信双方要记住双方,并且共享一些信息。而无状态协议的通信每次都是独立的,与上一次的通信没什么关系。
"状态”可以理解为“记忆”,有状态对应有记忆,无状态对应无记忆

数据卷简单来说就是一种挂在
据卷分类
启动容器时,可以指定使用数据卷实现容器数据的持久化,数据卷有三种
docker run 命令的以下格式可以实现数据卷
- -v, --volume=[host-src:]container-dest[:<options>]
- <options>
- ro 从容器内对此数据卷是只读,不写此项默认为可读可写
- rw 从容器内对此数据卷可读可写,此为默认值
方式1指定宿主机目录或文件格式 两个目录数据会同步 支持多个挂载
- #指定宿主机目录或文件格式:
- -v <宿主机绝对路径的目录或文件>:<容器目录或文件>[:ro] #将宿主机目录挂载容器目录,两个目录
- 都可自动创建

方式2匿名卷 挂在会生成匿名卷,几乎没啥用 谁闲着没事记这个
- #匿名卷,只指定容器内路径,没有指定宿主机路径信息,宿主机自动生成/var/lib/docker/volumes/<卷
- ID>/_data目录,并挂载至容器指定路径
- -v <容器内路径>
- #示例:
- docker run --name nginx -v /etc/nginx nginx

方式3 命名卷将固定 docker volume ls 查看所有 删除容器数据也不丢失 可以自己创
docker volume prune #用此命令清理会把卷也清了 docker system ptune #他不会清楚
- #命名卷将固定的存放在/var/lib/docker/volumes/<卷名>/_data
- -v <卷名>:<容器目录路径>
- #可以通过以下命令事先创建,如可没有事先创建卷名,docker run时也会自动创建卷
- docker volume create <卷名>
- #示例:
- docker volume create vol1 #也可以事先不创建
- docker run -d -p 80:80 --name nginx01 -v vol1:/usr/share/nginx/html nginx

docker rm 的 -v 选项可以删除容器时,同时删除相关联的匿名卷

ro给其权限让其不能写(容器里面不能i写,外边宿主机可以写)
两条命令一执行就好好了
- docker run -d -p 80:80 --name wordpress -v /data/wordpess:/var/www/html --restart=always wordpress:php7.4-apache
-
- 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

之前那种方法需要创建一次输入一遍,这次这种只需要输入一次,后续继承之前创建的就可以了
--volumes-from nginx01 继承nginx01创建的容器,他就是创建的时候依赖一下,创建之后就不依赖了,你把nginx01删了,对于之后创建完的没影响,都是共享内容
如果nginx01被你删了,你基于nginx02也是可以创建的 效果都是一样的
- docker run -d --name nginx01 -p 80:80 -v volume1:/apps/nginx/html/ -v /data1:/data1 -v /data2:/data2 nginx:v1.22.0-1
-
- docker run -d --name nginx02 -p 81:80 --volumes-from nginx01 nginx:v1.22.0-1
- docker run -d --name nginx03 -p 82:80 --volumes-from nginx01 nginx:v1.22.0-1
总结: 目前只支持固定IP,K8S不适用,在K8S章节会有跳转固定访问的办法
由于匿名数据卷在宿主机中的存储位置不确定,所以为了方便的备份匿名数据卷,可以利用数据卷容器实现数据卷的备份

A是匿名卷不知道路径,B复制用 --volumes-from继承关联一下,在B上创建另一个指定挂载文件
接着进去用备份命令在里面打个包,备份到B创建的挂载目录上,创建之前加上--rm,退出后直接删除,这样就完成了
- #在执行备份命令容器上执行备份方式
- docker run -it --rm --volumes-from [container name] -v $(pwd):/backup ubuntu
- root@ca5bb2c1f877:/#tar cvf /backup/backup.tar [container data volume]
-
- #说明
- [container name] #表示需要备份的容器
- [container data volume] #表示容器内的需要备份的数据卷对应的目录
-
- #还原方式
- docker run -it --rm --volumes-from [container name] -V $(pwd):/backup ubuntu
- root@ca5bb2c1f877:/#tar xvf /backup/backup.tar -C [container data volume]
- 创建需要备份的匿名数据卷容器
- [root@ubuntu1804 ~]#docker run -it -v /datavolume1 --name volume-server centos
- bash
-
- [root@88bbc22a3072 /]# ls
- bin dev home lib64 media opt root sbin sys usr
- datavolume1 etc lib lost+found mnt proc run srv tmp var
-
- [root@88bbc22a3072 /]# touch /datavolume1/centos.txt
- [root@88bbc22a3072 /]# exit
- exit
-
- [root@ubuntu1804 ~]#docker ps
- CONTAINER ID IMAGE COMMAND CREATED
- STATUS PORTS NAMES
-
- #可以看到数据卷对应的宿主机目录
- [root@ubuntu1804 ~]#docker inspect --format="{{.Mounts}}" volume-server
- [{volume 21199be9bff7ce98926f673d2250d64d75aaa00c5d375a2528b2b47f0ec4cb93
- /var/lib/docker/volumes/21199be9bff7ce98926f673d2250d64d75aaa00c5d375a2528b2b47f
- 0ec4cb93/_data /datavolume1 local true }]
-
- #基于前面的匿名数据卷容器创建执行备份操作的容器
- [root@ubuntu1804 ~]#docker run -it --rm --volumes-from volume-server -v
- ~/backup:/backup --name backup-server ubuntu
- root@9ad8be4b5810:/# ls
- backup boot dev home lib32 libx32 mnt proc run srv tmp var
- bin datavolume1 etc lib lib64 media opt root sbin sys usr
-
- root@9ad8be4b5810:/# ls /backup/
- root@9ad8be4b5810:/# ls /datavolume1/
- centos.txt
-
- root@9ad8be4b5810:/# cd /datavolume1/
- root@9ad8be4b5810:/datavolume1# tar cvf /backup/data.tar .
- ./
- ./centos.txt
- root@9ad8be4b5810:/datavolume1# exit
- exit
-
- [root@ubuntu1804 ~]#ls ~/backup/
- data.tar
-
- #删除容器的数据
- [root@ubuntu1804 ~]#docker start -i volume-server
- [root@88bbc22a3072 /]# rm -rf /datavolume1/*
- [root@88bbc22a3072 /]# ls /datavolume1/
- [root@88bbc22a3072 /]# exit
- exit
-
- #进行还原
- [root@ubuntu1804 ~]#docker run --rm --volumes-from volume-server -v
- ~/backup:/backup --name backup-server ubuntu tar xvf /backup/data.tar -C
- /datavolume1/
- ./
- ./centos.txt
-
- #验证是否还原
- [root@ubuntu1804 ~]#docker start -i volume-server
- [root@88bbc22a3072 /]# ls /datavolume1/
- centos.txt
范例: 利用数据卷容器备份MySQL数据库
- #MySQL容器默认使用了匿名卷
- [root@ubuntu1804 ~]#docker run -d --name mysql -p 3306:3306 -e
- MYSQL_ROOT_PASSWORD=123456 mysql:5.7.30
-
- [root@ubuntu1804 ~]#docker volume ls
- DRIVER VOLUME NAME
- local
- 897bd48c5c5e2067627d5c6d10dad17d4793132a638986c16f36820663728ee1
-
- #备份数据库
- [root@ubuntu1804 ~]#docker run -it --rm --volumes-from mysql -v $(pwd):/backup
- centos tar xvf /backup/mysql.tar -C /var/lib/mysql
-
- #删除数据库文件
- [root@ubuntu1804 ~]#rm -rf
- /var/lib/docker/volumes/897bd48c5c5e2067627d5c6d10dad17d4793132a638986c16f368206
- 63728ee1/_data/
-
- #还原数据库
- [root@ubuntu1804 ~]#docker run -it --rm --volumes-from mysql -v $(pwd):/backup
- centos tar xvf /backup/mysql.tar -C /
默认情况下
dockerd --icc Enable inter-container communication (default true)
--icc=false #此配置可以禁止同一个宿主机的容器之间通

daemon-reload: 重新加载某个服务的配置文件
因为更改了service文件所以要冲印加载一下,外加重启

ping别人就ping不通了,ping自己就可以server

默认docker后会自动生成一个docker0的网桥,使用的IP是172.17.0.1/16,可能和宿主机的网段发生冲突,可以将其修改为其它网段的地址,避免冲突
注释:在service文件里也可以改,两个地方改了会打架,所以最好改一个地方
删除修改那段后他不会重新恢复到172网段,而是修改后的网段
范例: 将docker0的IP修改为指定IP

重启后查看
因为docker重启了,所以容器也会默认关闭,起来之后会变成修改后的ip
注意:此做法无法保存,电脑重启后docker就会起不来,需要把加的去掉重启配置就可以了
新建容器默认使用docker0的网络配置,可以修改默认指向自定义的网桥网络
范例: 用自定义的网桥代替默认的docker1
创建网桥docker1 让docker桥接到docker1


加上-b docker1后 执行systectl daemon-reload ;systemctl restart docker

docker run 创建容器,可使用--link选项实现容器名称的引用,其本质就是在容器内的/etc/hosts中添加- -link后指定的容器的IP和主机名的对应关系,从而实现名称解析
- --link list #Add link to another container
- 格式:
- docker run --name <容器名称> #先创建指定名称的容器
- docker run --link <目标通信的容器ID或容器名称> #再创建容器时引用上面容器的名称
在启动的瞬间会在web02上会考到web01的 地址解析


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


Docker 的网络支持5种网络模式:
范例: 查看默认的网络模式有三个
- [root@ubuntu2004 ~]#docker network ls
- NETWORK ID NAME DRIVER SCOPE
- fe08e6d23c4c bridge bridge local
- cb64aa83626c host host local
- 10619d45dcd4 none null local
网络模式指定
默认新建的容器使用Bridge模式,创建容器时,docker run 命令使用以下选项指定网络模式
格式; 一共有五种,本质上有三种none bridge host哪两种就是桥接在默认网桥上
- docker run --network <mode>
- docker run --net=<mode>
- <mode>: 可是以下值
- none
- bridge
- host
- container:<容器名或容器ID>
- <自定义网络名称>
在docker上开启一个NAT转换,用docker容器访问外网的时候做了一个转换把172这个网段通过SNAT源地址装换成外网 他需要ip-forward 这个docker是自动打开的

上面有修改IP地址的那个
- 修改桥接地址
- [root@ubuntu1804 ~]#vim /lib/systemd/system/docker.service
- ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
- --bip=10.100.0.1/24
-
- [root@ubuntu1804 ~]#systemctl daemon-reload
- [root@ubuntu1804 ~]#systemctl restart docker
此模式由于直接使用宿主机的网络无需转换,网络性能最高,但是各容器内使用的端口不能相同,适用于运行容器端口比较固定的业务
简单来讲就是和你宿主机共享网络,宿主机的网络,网口等就是我的
Host 网络模式特点:
因为和端口共享网络所以哪怕映射端口也没用,都是默认80,第一个容器起得来第二个就起不来
因为80端口起冲突

在使用none 模式后,Docker 容器不会进行任何网络配置,没有网卡、没有IP也没有路由,因此默认无法与外界通信,需要手动添加网卡配置IP等,所以极少使用
none模式特点
使用参数 --network none 指定
默认无网络功能,无法和外部通信
无法实现端口映射
适用于测试环境


使用此模式创建的容器需指定和一个已经存在的容器共享一个网络,而不是和宿主机共享网络,
使用此模式创建的容器需指定和一个已经存在的容器共享一个网络,而不是和宿主机共享网络,新创建的容器不会创建自己的网卡也不会配置自己的IP,而是和一个被指定的已经存在的容器共享IP和端口范围,因此这个容器的端口不能和被指定容器的端口冲突,除了网络之外的文件系统、进程信息等仍然保持相互隔离,两个容器的进程可以通过lo网卡进行通信
Container 模式特点
因为web02和web01共享一个网络所以如果在一个程序的话会起冲突,需要在另一个不同的镜像里起来



你依附人家就不用做端口暴露了,没用,都是同一个网络
因为数据库授权账号问题(和权限没关)·你有localhost解析也没法子在里面用,只能写端口号
- docker run -d -p 80:80 --name wordpress -v /data/wordpess:/var/www/html --restart=always wordpress:php7.4-apache
-
- 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
%是不能写localhost,只能写ip

除了以上的网络模式,也可以自定义网络,使用自定义的网段地址,网关等信息
注意: 自定义网络内的容器可以直接通过容器名进行相互的访问,而无需使用 --link
可以使用自定义网络模式,实现不同集群应用的独立网络管理,而互不影响,而且在网一个网络内,可以直接利用容器名相互访问,非常便利
创建自定义网络:
docker network create -d
--subnet --gateway <网关> <自定义网络名称>
#注意mode不支持host和none,默认是bridge模式
查看自定义网络信息
docker network inspect <自定义网络名称或网络ID>
引用自定义网络
docker run --network <自定义网络名称> <镜像名称>
docker run --net <自定义网络名称> --ip <指定静态IP> <镜像名称>
#注意:静态IP只支持自定义网络模型
删除自定义网络 内置的三个网络无法删除
doccker network rm <自定义网络名称或网络ID>
范例:默认网络模式就不需要-d 指定了,可以连接外网的


同一样网络不需要加hosts解析就可以域名访问

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

把宿主机的nginx01加到专属网络中,这样Nginx01能ping通nginx02,2通不了1
这哥们很聪明的加了一个地址,这是我最无语的
双通

把他踢了

在后期K8S中会很容易解决。现在主要是还是说的方法理解
同一个宿主机之间的各个容器之间是可以直接通信的,但是如果访问到另外一台宿主机的容器呢?
两台不一样的主机和ip


在两边执行这条命令使他们做成网络桥接 #brctl addif docker0 eth0
执行完之后网络会断

把一个网换改掉
- [root@rocky8 ~]#vim /etc/docker/daemon.json
- {
- "registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"],
- "bip": "172.27.0.1/24"
- }

在两边创建镜像名字是否一样都可以
- [root@ubuntu2004 ~]#docker run -d -p 80:80 --name nginx02 nginx:1.0
- 8be7661a035007907bd6ee4199e215a2efe95078006376883ed2b55507cfbd41
两边地址错开不一样
有去有回
![]()
![]()
数据过来了,有来无回 
在两边加上这个命令
#修改iptables规则
[root@ubuntu 2004~]#iptables -A FORWARD -s 10.0.0.0/24 -j ACCEPT
