编辑
2022-06-05
docker
00

目录

docker
1、docker核心组件
2、docker优缺点
3、docker的安装
4、docke加速
5、导出所有镜像及导入
6、docker常用命令
7、指定容器dns
8、容器内和宿主机之间复制文件
9、传递环境变量 有些容器运行时,需要传递变量,可以使用 -e <参数> 或 --env-file <参数文件> 实现
10、docker镜像都是分层组成
11、dockerfile
12、docker镜像构建、打标签、上传及登录
13、数据持久化保存
14、引用同一个数据卷目录,开启多个容器,实现多个容器共享数据
14、数据卷容器实现容器数据共享
15、容器间的相互通信
16、docker网络连接模式
17、docker-compose 单机容器编排工具
18、docker资源限制
19、获取容器IP地址

docker

1、docker核心组件
  • Namespace:提供磁盘挂载和文件系统的隔离能力
  • Control groups:简称Cgroups。控制容器的资源限制,在2.6.24版本后的内核中已集成,所以docker在centos6中基本无法使用。在/boot/config-4.18.0-147.el8.x86_64文件中可查看到
2、docker优缺点

优点:

  • 快速部署: 短时间内可以部署成百上千个应用,更快速交付到线上
  • 高效虚拟化: 不需要额外hypervisor支持,基于linux内核实现应用虚拟化,相比虚拟机大幅提高性 能和效率
  • 节省开支: 提高服务器利用率,降低IT支出
  • 简化配置: 将运行环境打包保存至容器,使用时直接启动即可
  • 环境统一: 将开发,测试,生产的应用运行环境进行标准化和统一,减少环境不一样带来的各种问 题
  • 快速迁移和扩展: 可实现跨平台运行在物理机、虚拟机、公有云等环境,良好的兼容性可以方便将 应用从A宿主机迁移到B宿主机,甚至是A平台迁移到B平台
  • 更好的实现面向服务的架构,推荐一个容器只运行一个应用,实现分布的应用模型,可以方便的进行横 向扩展,符合开发中高内聚,低耦合的要求,减少不同服务之间的相互影响

缺点:

  • 多个容器共用宿主机的内核,各应用之间的隔离不如虚拟机彻底
  • 由于和宿主机之间的进程也是隔离的,需要进入容器查看和调试容器内进程等资源,变得比较困难和繁琐
  • 如果容器内进程需要查看和调试,需要在每个容器内都需要安装相应的工具,这也造成存储空间的重复浪费
3、docker的安装
#安装完docker源后,不指定版本,Ubuntu和centos默认安装的都是最新版,目前k8s支持到19.03 #Ubuntu查看源里包含的指定软件的版本:apt-cache madison docker-ce #Centos查看源里包含的指定软件版本: yum list docker --showduplicates #安装docker-ce和docker-ce-cli时最好加版本号,保持server和cli版本一致。
4、docke加速
sh
#默认去docker.io去下载镜像速度很慢。阿里云有docker仓库, mkdir -p /etc/docker tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://npud8xro.mirror.aliyuncs.com"] } EOF systemctl daemon-reload systemctl restart docker.service
5、导出所有镜像及导入
sh
#导出所有镜像 docker save `docker images | awk 'NR>1{print $1":"$2}' ` -o all.tar #或者 docker `docker image ls --format "{{.Repository}}:{{.Tag}}"` #导入所有镜像,发现已有镜像不再导入 docker load -i all.tar
6、docker常用命令
sh
docker pull nginx docker save image_name -o name1.tar docker load -i name1.tar docker port container_name #查看容器暴露 docker rm container #删除已停止的容器 docker rm -f container #强制删除容器,不论状态 docker rm -f `docker ps -a -q` #删除所有容器 docker ps -qa | xargs docker rm -f #删除所有容器 docker rm `docker ps -qf status=exited` #删除退出状态的容器 docker container prune -f #删除所有停止的容器 docker rmi images_name docker start $(docker ps -a -q) #批量正常启动或关闭所有容器 docker stop $(docker ps -a -q) docker -it container_name sh docker exec -it container_id sh #测试环境使用此方式,使用exit退出,但容器还在运行,此为推荐方式。 docker run -d --name nginx --restart=always -p 80:80 nginx #容器总是运行,开机随docker启动 docker inspect web01 #可用于查看容器详细信息 docker logs 容器名称 #不论容器是否开启都可看见日志 加-f为跟踪日志 docker run --name a1 ubuntu cat /etc/issue #命令为一次性则执行完退出命令为持续命令则容器不退出。比如:tail -f /var/log/message docker run -it --rm --name web01 --add-host www.zhangt.cc:6.6.6.6 nginx #加--rm会导致容器一旦退出就删除,--add-host往容器的host文件中添加域名和地址解析 docker run -d -v /data/nginx:/data/html --name n1 -P xiaowei200957079/nginx:v1.22-1 #运行一个随机映射端口的nginx容器,数据卷为/data/nginx,容器内挂载对象为/data/html,和nginx容器的nginx.conf对应 docker exec -it nginx tail -f /apps/nginx/logs/access.log #实时查看nginx容器的访问日志 docker volume rm container_name #删除容器临时挂载的数据卷,持久挂载的此操作不支持 #从容器内退出,且容器不停止 同时按三个键,ctrl+p+q
7、指定容器dns
sh
#默认容器的dns从宿主机获取 #指定容器的dns docker run -it --rm --dns 1.1.1.1 --dns 8.8.8.8 centos bash #指定domain名 docker run -it --rm --dns 1.1.1.1 --dns 8.8.8.8 --dns-search a.com --dns-search b.com busybox #修改所有容器的默认dns就是修改docker的配置文件,需重启服务 cat /etc/docker/daemon.json { "storage-driver": "overlay2", "registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"], "dns" : [ "114.114.114.114", "119.29.29.29"], "dns-search": [ "magedu.com", "wang.org"] }
8、容器内和宿主机之间复制文件
sh
#将容器内文件复制到宿主机 docker cp -a 容器名:/etc/centos-release /opt #将宿主机文件复制到容器内 docker cp /etc/issue 容器名:/root/
9、传递环境变量 有些容器运行时,需要传递变量,可以使用 -e <参数> 或 --env-file <参数文件> 实现
sh
docker run --name mysql-test1 -v /data/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wpuser -e MYSQL_PASSWORD=123456 -d -p 3306:3306 mysql:5.7.30 [root@ubuntu1804 ~]#docker run --name mysql-test2 -v /root/mysql/:/etc/mysql/conf.d -v /data/mysql2:/var/lib/mysql --env-file=env.list -d -p 3307:3306 mysql:5.7.30 [root@ubuntu1804 ~]#cat mysql/mysql-test.cnf [mysqld] server-id=100 log-bin=mysql-bin [root@ubuntu1804 ~]#cat env.list MYSQL_ROOT_PASSWORD=123456 MYSQL_DATABASE=wordpress MYSQL_USER=wpuser MYSQL_PASSWORD=wppass
10、docker镜像都是分层组成
sh
docker history rockylinux:8.5 IMAGE CREATED CREATED BY SIZE COMMENT 210996f98b85 13 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 13 months ago /bin/sh -c #(nop) ADD file:790b4c6a174560d47… 205MB #从下往上依次是从第一次到最后一次使用的命令或添加的文件,rocky操作系统就只有两个,从一个空镜像导入rocky的打包文件,然后运行即可 ---注意--- #所有的docker 镜像都没有/boot文件夹,因为和宿主机使用的是一个内核
11、dockerfile

Dockerfile 文件说明

  • 每一行以Dockerfile的指令开头,指令不区分大小写,但是惯例使用大写
  • 使用 # 开始作为注释
  • 每一行只支持一条指令,每条指令可以携带多个参数
  • 指令按文件的顺序从上至下进行执行
  • 每个指令的执行会生成一个新的镜像层,为了减少分层和镜像大小,尽可能将多条指令合并成一条指令
  • 制作镜像一般可能需要反复多次,每次执行dockfile都按顺序执行,从头开始,已经执行过的指令 已经缓存,不需要再执行,如果后续有一行新的指令没执行过,其往后的指令将会重新执行,所以 为加速镜像制作,将最常变化的内容放下dockerfile的文件的后面
  • 在dockerfile中如果同时出现ENTRYPOINT和CMD,CMD里的命令会变成ENTRYPOINT的参数
dockerfile
#常见指令 ADD #添加文件,往镜像肚子里放东西。会自动解压 RUN #你想让他干啥,Linux命令前加RUN,只是在构建镜像时使用,最后不能使用 COPY #复制宿主机的文件到容器内,不会自动解压,如果dest目标文件夹在镜像中不存在会自动创建,不用单独创建 ENV #设置环境变量,可以定义多个变量在下方使用, 例: ENV name=zhang RUN touch $name.txt EXPOSE #打开的端口 FROM #它的母亲是谁,基础信息,在dockerfile的第一行 LABEL #告诉别人,谁创造了他,镜像元数据,例如镜像作者版本等 STOPSIGNAL USER VOLUME #目录挂载,存文件的地方。文件持久化 WORKDIR #相当于cd,当前工作目录 CMD #执行命令,一般在最后使用,运行构建好的镜像执行的命令,保证容器运行后不退出 dockerfile常用文件目录 #按照业务类型或系统类型等方式划分创建目录环境,方便后期镜像比较多的时候进行分类 mkdir /data/dockerfile/{web/{nginx,apache,tomcat,jdk},system/{centos,rocky,ubuntu,alpine,debian}} -p

dockerfile 例子

dockerfile
vim Dockerfile FROM rockylinux:8.5.20220308 LABEL maintainer="zhangwei <www.ztunan.top>" LABEL version=v1.0 LABEL multi.description="test" multi.date="2023-01-29" ENV OS_VERSION=rockylinux:8.5 RUN rm -f /etc/yum.repo.d/* COPY base.repo /etc/yum.repo.d/ #这里需要提前准备好base.repo文件 RUN yum clean all && \ rm -f /etc/localtime && \ ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ yum -y install procps-ng bash-completion psmisc git tree net-tools vim lsof iproute && \ rm -rf /var/cache/dnf/* && \ groupadd -g 88 www && \ useradd -g www -u 88 -r -s /sbin/nologin -M -d /home/www www #CMD tail -f /etc/hosts CMD ["/bin/tail","-f","/etc/hosts"] #两种CMD均可使用,但是后面这种格式必须写命令的全部路径,且不支持调用变量

CMD命令说明

  • 一个容器中需要持续运行的进程一般只有一个,CMD 用来指定启动容器时默认执行的一个命令,且其运 行结束后,容器也会停止,所以一般CMD 指定的命令为持续运行且为前台命令.
  • 如果docker run没有指定任何的执行命令或者dockerfile里面也没有ENTRYPOINT命令,那么开启 容器时就会使用执行CMD指定的默认的命令
  • 前面介绍过的 RUN 命令是在构建镜像时执行的命令,注意二者的不同之处
  • 每个 Dockerfile 只能有一条 CMD 命令。如指定了多条,只有最后一条被执行
  • 如果用户启动容器时用 docker run xxx 指定运行的命令,则会覆盖 CMD 指定的命令
dockerfile
# 使用 exec 执行,推荐方式,第一个参数必须是命令的全路径,此种形式不支持环境变量 CMD ["executable","param1","param2"] # 在 /bin/sh 中执行,提供给需要交互的应用;此种形式支持环境变量 CMD command param1 param2 # 提供给 ENTRYPOINT 命令的默认参数 CMD ["param1","param2"] 例:nginx的dockerfile中 ENTRYPOINT [docker-entrypoint.sh] CMD ["nginx","-g","daemon off;"] #同时出现,结果变成 ./docker-entrypoint.sh nginx -g daemon off #docker-entrypoint.sh脚本中的最后有个exec "$@",调用CMD中的变量
12、docker镜像构建、打标签、上传及登录
  • 先使用dockerfile构建镜像,然后打标签,登录docker.io,上传镜像,退出登录
c
docker build rocky:v8.5-1 Dockerfile #构建镜像 docker tag rocky:v8.5-1 xiaowei200957079/rocky:v8.5-1 #打标签是要按特定的格式上传到docker.io,所以必须更改镜像标签才能上传,不然找不到路径 docker login #输入账号密码 docker push xiaowei200957079/rocky:v8.5-1 #上传镜像 docker logout #退出登录,这步必须做,因为登录成功会自动生生验证信息,一直在登录状态。不然所有的资源访问都会去docker官方仓库寻找,加速就失效了~退出还不生效就重启服务 docker info | tail #查看信息
  • 使用dockerfile构建镜像,标签直接打好,登录、上传、退出
c
docker build -t xiaowei200957079/alpine:3.17-v1 Dockerfile docker login docker push xiaowei200957079/alpine:3.17-v1 docker logout docker info | tail #查看信息
  • 将docker build构建镜像写成脚本,最后加变量版本即可
sh
cat build.sh #!/bin/bash tag=$1 docker build -t xiaowei200957079/nginx:$tag . #可根据具体项目和上传网站更改脚本
13、数据持久化保存
  • 使用docker run容器运行命令方式实现数据卷持久保存
http
-v, --volume=[host-src:]container-dest[:<options>] <options> ro 从容器内对此数据卷是只读,不写此项默认为可读可写 rw 从容器内对此数据卷可读可写,此为默认值

方式一

  • 在dockerfile说明的VOLUME在宿主机中的文件夹是乱码,不利于后期寻找使用,不建议
sh
#匿名卷,只指定容器内路径,没有指定宿主机路径信息,宿主机自动生成/var/lib/docker/volumes/<卷 ID>/_data目录,并挂载至容器指定路径 -v <容器内路径> #示例: docker run --name nginx -v /etc/nginx nginx

方式二

c
#指定宿主机目录和容器内对应的目录,目录不存在时会自动创建 docker -v 宿主机目录(绝对路径,文件或目录):容器目录(绝对路径,文件或目录) 例: docker run -d -P -v /data/nginx:/data/html -P --name n1 nginx:1.22-v1

方式三

c
#命名卷将固定的存放在/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 选项可以删除容器时,同时删除相关联的匿名卷

-v, --volumes Remove the volumes associated with the container

管理数据卷命令

docker volume COMMAND Commands: create Create a volume #创建 inspect Display detailed information on one or more volumes #查看信息 ls List volumes #列出所有的数据卷 prune Remove all unused local volumes #删除未使用的数据卷 rm Remove one or more volumes #删除所有的卷
14、引用同一个数据卷目录,开启多个容器,实现多个容器共享数据
sh
[root@ubuntu1804 ~]#docker run -d -v /data/testdir:/data/nginx/html/ -p 8001:80 nginx-alpine:1.16.1 56a5460f584bd2de56040c4a1dff86ad8a9723cfd6bf21ed8a538b9629b0874c [root@ubuntu1804 ~]#docker run -d -v /data/testdir:/data/nginx/html/ -p 8002:80 nginx-alpine:1.16.1 e7b5bff6ce56fa51ed6411175c9c9f1fb9bf8e7b1b9471080380b01692f89e58 [root@ubuntu1804 ~]#docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e7b5bff6ce56 nginx-alpine:1.16.1 "nginx" 6 seconds ago Up 5 seconds 443/tcp, 0.0.0.0:8002->80/tcp hungry_robinson 56a5460f584b nginx-alpine:1.16.1 "nginx" 33 seconds ago Up 31 seconds 443/tcp, 0.0.0.0:8001->80/tcp stupefied_dubinsky [root@ubuntu1804 ~]#curl 127.0.0.1:8001 Test page on host [root@ubuntu1804 ~]#curl 127.0.0.1:8002 Test page on host

删除容器后,宿主机的数据卷还存在,可继续给新的容器使用,对应mysql,即使旧容器删除了,再开一个新容器也可立即连接使用

c
[root@ubuntu1804 ~]#docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e7b5bff6ce56 nginx-alpine:1.16.1 "nginx" 9 minutes ago Up 9 minutes 443/tcp, 0.0.0.0:8002->80/tcp hungry_robinson 56a5460f584b nginx-alpine:1.16.1 "nginx" 9 minutes ago Up 9 minutes 443/tcp, 0.0.0.0:8001->80/tcp stupefied_dubinsky [root@ubuntu1804 ~]#docker rm -f `docker ps -aq` e7b5bff6ce56 56a5460f584b [root@ubuntu1804 ~]#cat /data/testdir/index.html Test page v3 on host #新建的容器还可以继续使用原有的数据卷 [root@ubuntu1804 ~]#docker run -d -v /data/testdir:/data/nginx/html/ -p 8003:80 nginx-alpine:1.16.1 ecd016506f6af3f4af61dbd869f8fce5f634ecdc0e3272f9e0402c981acd80a4 [root@ubuntu1804 ~]#curl 127.0.0.1:8003 Test page v3 on host
14、数据卷容器实现容器数据共享
http
在Dockerfile中创建的是匿名数据卷,无法直接实现多个容器之间共享数据 数据卷容器最大的功能是可以让数据在多个docker容器之间共享 两个或两个以上的容器实现容器之间的数据共享 ---相当于先要创建一个后台运行的容器作为 Server,用于提供数据卷,这个卷可以为其他容器提供数据存储服务,其他使用此卷的容器作为client端 ,但此方法并不常使用--- 缺点: 因为依赖一个 Server 的容器,所以此 Server 容器出了问题,其它 Client容器都会受影响
  • 使用数据容器
docker run 命令的以下选项可以实现数据卷容器,格式如下: --volumes-from <数据卷容器> Mount volumes from the specified container(s)
15、容器间的相互通信
  • 宿主机之间的容器可以相互通信,依靠IP和主机名,但是IP是随机的,依靠主机名通信才可持久互联
  • 容器名称实现互联
c
docker run 创建容器,可使用--link选项实现容器名称的引用,其本质就是在容器内的/etc/hosts中添加--link后指定的容器的IP和主机名的对应关系,从而实现名称解析 --link list #Add link to another container 格式: docker run --name <容器名称> #先创建指定名称的容器 docker run --link <目标通信的容器ID或容器名称> #再创建容器时引用上面容器的名称 docker run --name b1 -d busybox tail -f /etc/hosts #创建b1容器 docker run --link b1 -d --name a1 xiaowei200957079/alpine:3.17-v1 tail -f /etc/hosts #创建a1容器,指定链接b1容器,默认会把b1的容器名称、ID和IP写入a1的hosts文件中。 docker exec -it a1 sh #进入a1容器 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 172.17.0.2 b1 a1f1a11192f7 #这里发现已经写入 172.17.0.3 6a09104edec7 ping b1 #成功实现容器间互联 PING b1 (172.17.0.2): 56 data bytes 64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.164 ms 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.143 ms 64 bytes from 172.17.0.2: seq=2 ttl=64 time=0.125 ms
  • 实现mysql和wordpress容器间的互联
sh
[root@centos7 ~]#tree lamp_docker/ lamp_docker/ ├── env_mysql.list ├── env_wordpress.list └── mysql └── mysql_test.cnf 1 directory, 3 files [root@centos7 ~]#cat lamp_docker/env_mysql.list MYSQL_ROOT_PASSWORD=123456 MYSQL_DATABASE=wordpress MYSQL_USER=wpuser MYSQL_PASSWORD=wppass [root@centos7 ~]#cat lamp_docker/env_wordpress.list WORDPRESS_DB_HOST=mysql:3306 WORDPRESS_DB_NAME=wordpress WORDPRESS_DB_USER=wpuser WORDPRESS_DB_PASSWORD=wppass WORDPRESS_TABLE_PREFIX=wp_ [root@centos7 ~]#cat lamp_docker/mysql/mysql_test.cnf [mysqld] server-id=100 log-bin=mysql-bin [root@centos7 ~]#docker run --name mysql -v /root/lamp_docker/mysql/:/etc/mysql/conf.d -v /data/mysql:/var/lib/mysql --envfile=/root/lamp_docker/env_mysql.list -d -p 3306:3306 mysql:5.7.30 #这里mysql就不用映射3306到宿主机了,因为直接通过docker桥接网络直接连接,保证mysql的安全 [root@centos7 ~]#docker run -d --name wordpress --link mysql -v /data/wordpress:/var/www/html/wp-content --envfile=/root/lamp_docker/env_wordpress.list -p 80:80 wordpress #最后主机访问wordpress时,配置的数据库地址要写mysql的容器名称
  • 修改默认docker0网桥的网络配置

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

bash
#方法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服务
  • 容器别名简介和实现

自定义的容器名称可能后期会发生变化,那么一旦名称发生变化,容器内程序之间也必须要随之发生变 化,比如:程序通过固定的容器名称进行服务调用,但是容器名称发生变化之后再使用之前的名称肯定是 无法成功调用,每次都进行更改的话又比较麻烦,因此可以使用自定义别名的方式解决,即容器名称可 以随意更改,只要不更改别名即可

sh
命令格式: docker run --name <容器名称> #先创建指定名称的容器 docker run --name <容器名称> --link <目标容器名称>:"<容器别名1> <容器别名2> ..." #给上面创建的容器起别名,来创建新容器 实现: docker run --name b1 -d busybox tail -f /etc/hosts #创建b1容器 docker run --link b1:b1-alias -it --name a1 xiaowei200957079/alpine:3.17-v1 sh #创建a1容器,给b1规定别名为b1-alias并进入容器 / # env HOSTNAME=c3359ae93d4b SHLVL=1 HOME=/root TERM=xterm PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin B1_ALIAS_NAME=/a1/b1-alias PWD=/ / # ping b1 PING b1 (172.17.0.2): 56 data bytes 64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.134 ms 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.188 ms / # ping b1-alias PING b1-alias (172.17.0.2): 56 data bytes 64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.082 ms 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.107 ms #这里ping容器名和别名都能通,下面开始修改b1的容器名称 docker container rename b1 b2 docker exec -it a1 sh #进入a1容器 / # env HOSTNAME=c3359ae93d4b SHLVL=1 HOME=/root TERM=xterm PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin B1_ALIAS_NAME=/a1/b1-alias PWD=/ / # 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 172.17.0.2 b1-alias eaa55ae54ebb b1 172.17.0.3 c3359ae93d4b / # ping b1-alias PING b1-alias (172.17.0.2): 56 data bytes 64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.093 ms 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.116 ms
16、docker网络连接模式

Docker 的网络支持5种网络模式,默认的网络模式有三个 : host、bridge、none

  • none #没有网络,没有IP,单机版
  • bridge #桥接,可做NAT映射端口,与172段的容器互通
  • host #使用宿主机网络地址,容器内端口和宿主机端口共同对外发布
  • container
  • network-name

网络模式指定

  • 默认新建的容器使用Bridge模式,创建容器时,docker run 命令使用以下选项指定网络模式
sh
docker run --network <mode> docker run --net=<mode> <mode>: 可是以下值 none bridge host container:<容器名或容器ID> <自定义网络名称> docker run --network none -d --name web01 nginx

Host模式特点

  • 使用参数 --network host 指定
  • 共享宿主机网络
  • 网络性能无损耗
  • 网络故障排除相对简单
  • 各容器网络无隔离
  • 网络资源无法分别统计
  • 端口管理困难: 容易产生端口冲突
  • 不支持端口映射

Bridge网络模式特点

  • 网络资源隔离: 不同宿主机的容器无法直接通信,各自使用独立网络
  • 无需手动配置: 容器默认自动获取172.17.0.0/16的IP地址,此地址可以修改
  • 可访问外网: 利用宿主机的物理网卡,SNAT连接外网
  • 外部主机无法直接访问容器: 可以通过配置DNAT接受外网的访问
  • 低性能较低: 因为可通过NAT,网络转换带来更的损耗
  • 端口管理繁琐: 每个容器必须手动指定唯一的端口,容器产生端口冲容

None模式特点

  • 使用参数 --network none 指定
  • 默认无网络功能,无法和外部通信
  • 无法实现端口映射
  • 适用于测试环境

Container 模式特点

  • 使用参数 –-network container:名称或ID 指定
  • 与宿主机网络空间隔离
  • 空器间共享网络空间
  • 适合频繁的容器间的网络通信
  • 直接使用对方的网络,较少使用
c
#两个容器共用一个网络地址,第二个容器继承第一个容器的网络。两个容器之间可之间使用127.0.0.1通讯 #创建第一个容器 [root@ubuntu1804 ~]#docker run -it --name server1 -p 80:80 alpine:3.11 sh / # ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02 inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:9 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:766 (766.0 B) TX bytes:0 (0.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) / # netstat -ntl Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State / # #在另一个终端执行下面操作 [root@ubuntu1804 ~]#docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4d342fac169f alpine:3.11 "sh" 29 seconds ago Up 28 seconds 0.0.0.0:80->80/tcp server1 [root@ubuntu1804 ~]#docker port server1 80/tcp -> 0.0.0.0:80 #无法访问web服务 [root@ubuntu1804 ~]#curl 127.0.0.1/app/ curl: (52) Empty reply from server #创建第二个容器,基于第一个容器的container的网络模式 [root@ubuntu1804 ~]#docker run -d --name server2 --network container:server1 nginx-centos7-base:1.6.1 7db90f38590ade11e1c833a8b2175810c71b3f222753c5177bb8b05952f08a7b #可以访问web服务 [root@ubuntu1804 ~]#curl 127.0.0.1/app/ Test Page in app [root@ubuntu1804 ~]#docker exec -it server2 bash #和第一个容器共享相同的网络 [root@4d342fac169f /]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet) RX packets 29 bytes 2231 (2.1 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 12 bytes 1366 (1.3 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1000 (Local Loopback) RX packets 10 bytes 860 (860.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 10 bytes 860 (860.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 [root@4d342fac169f /]# netstat -ntl Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN #可访问外网 [root@4d342fac169f /]# ping www.baidu.com PING www.a.shifen.com (61.135.169.121) 56(84) bytes of data. 64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=1 ttl=127 time=3.99 ms 64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=2 ttl=127 time=5.03 ms ^C --- www.a.shifen.com ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 3.999/4.514/5.030/0.519 ms [root@4d342fac169f /]#

自定义网络

c
docker network --help Usage: docker network COMMAND Manage networks Commands: connect Connect a container to a network create Create a network disconnect Disconnect a container from a network inspect Display detailed information on one or more networks ls List networks prune Remove all unused networks rm Remove one or more networks #内置的三个网络无法删除 #创建网络命令 docker network create -d <mode> --subnet <CIDR> --gateway <网关> <自定义网络名称> #注意mode不支持host和none,默认是bridge模式 #范例 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 ~]#brctl show bridge name bridge id STP enabled interfaces br-00ab0f2d29e8 8000.024245e647ec no docker0 8000.0242cfd26f0a no #创建容器时指定网络即可 docker run -it --rm --network test-net alpine sh
17、docker-compose 单机容器编排工具
c
#下载地址:https://github.com/docker/compose/releases #直接下载二进制程序,复制到/usr/bin下,改名为docker-compose,添加执行权限即可使用 #命令格式 docker-compose --help Define and run multi-container applications with Docker. Usage: docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...] docker-compose -h|--help #选项说明: -f,–file FILE #指定Compose 模板文件,默认为docker-compose.yml -p,–project-name NAME #指定项目名称,默认将使用当前所在目录名称作为项目名。 --verbose #显示更多输出信息 --log-level LEVEL #定义日志级别 (DEBUG, INFO, WARNING, ERROR, CRITICAL) --no-ansi #不显示ANSI 控制字符 -v, --version #显示版本 #以下为命令选项,需要在docker-compose.yml|yaml 文件所在在目录里执行 config -q #查看当前配置,没有错误不输出任何信息 up #创建并启动容器 build #构建镜像 bundle #从当前docker compose 文件生成一个以<当前目录>为名称的json格式的Docker Bundle 备 份文件 create #创建服务 down #停止和删除所有容器、网络、镜像和卷 events #从容器接收实时事件,可以指定json 日志格式 exec #进入指定容器进行操作 help #显示帮助细信息 images #显示镜像信息 kill #强制终止运行中的容器 logs #查看容器的日志 pause #暂停服务 port #查看端口 ps #列出容器 pull #重新拉取镜像,镜像发生变化后,需要重新拉取镜像 push #上传镜像 restart #重启服务 rm #删除已经停止的服务 run #一次性运行容器 scale #设置指定服务运行的容器个数 ------已废弃----- start #启动服务 stop #停止服务 top #显示容器运行状态 unpause #取消暂停

创建docker-compose文件

c
docker compose 文件可在任意目录,创建文件名为docker-compose.yml 配置文件,要注意前后的缩进 mkdir /data/docker-compose cd /data/docker-compose [root@ubuntu1804 docker-compose]#cat docker-compose.yml service-nginx-web: image: 10.0.0.102/example/nginx-centos7-base:1.6.1 container_name: nginx-web expose: - 80 - 443 ports: - "80:80" - "443:443" #检查配置文件语法:docker-compose config -q #启动容器,必须在docker-compose所在的目录下 docker-compose up #默认容器前台执行,加-d即可在后台执行 #启动多个容器,---注意: 同一个文件 ,数据卷的优先级比镜像内的文件优先级高- cat docker-compose.yml service-nginx-web: image: 10.0.0.102/example/nginx-centos7-base:1.6.1 container_name: nginx-web volumes: - /data/nginx:/apps/nginx/html/#指定数据卷,将宿主机/data/nginx挂载到容 器/apps/nginx/html expose: - 80 - 443 ports: - "80:80" - "443:443" service-tomcat-app1: image: 10.0.0.102/example/tomcat-web:app1 container_name: tomcat-app1 expose: - 8080 ports: - "8081:8080" service-tomcat-app2: image: 10.0.0.102/example/tomcat-web:app2 container_name: tomcat-app2 expose: - 8080 ports: - "8082:8080"
18、docker资源限制

对于 Linux 主机,如果没有足够的内存来执行其他重要的系统任务,将会抛出OOM (Out of Memory Exception,内存溢出、内存泄漏、内存异常 ),随后系统会开始杀死进程以释放内存, 凡是运行在宿主机 的进程都有可能被 kill ,包括 Dockerd和其它的应用程序, 如果重要的系统进程被 Kill,会导致和该进 程相关的服务全部宕机。通常越消耗内存比较大的应用越容易被kill,比如: MySQL数据库,Java程序等

产生 OOM 异常时, Dockerd尝试通过调整 Docker 守护程序上的 OOM 优先级来减轻这些风险,以便 它比系统上的其他进程更不可能被杀死但是每个容器 的 OOM 优先级并未调整, 这使得单个容器被杀死 的可能性比 Docker守护程序或其他系统进程被杀死的可能性更大,不推荐通过在守护程序或容器上手动 设置-- oom -score-adj为极端负数,或通过在容器上设置 -- oom-kill-disable来绕过这些安全措施

OOM 优先级机制: linux会为每个进程算一个分数,最终将分数最高的kill

c
/proc/PID/oom_score_adj #范围为 -10001000,值越高容易被宿主机 kill掉,如果将该值设置为 -1000 ,则进程永远不会被 宿主机 kernel kill /proc/PID/oom_adj #范围为 -17 到+15 ,取值越高越容易被干掉,如果是 -17 , 则表示不能被 kill ,该设置参数的存在 是为了和旧版本的 Linux 内核兼容。 /proc/PID/oom_score #这个值是系统综合进程的内存消耗量、 CPU 时间 (utime + 、存活时间 (uptime - start time) 和 oom_adj 计算出的进程得分 ,消耗内存越多得分越高,容易被宿主机 kernel 强制杀死

内存限制选项

-m , --memory= 容器可以使用的最大物理内存量,硬限制,此选项最小允许值为 4m (4MB),此项较常用 --memory-swap 允许此容器交换到磁盘的内存量,必须先用-m 对内存限制才可以使用,详细说明如下 --memory-swappiness 设置容器使用交换分区的倾向性,值越高表示越倾向于使用swap分区,范围为0-100,0为能不用就不用,100为能用就用,N表示内存使用率达到N%时,就会使用swap空间 --memoryreservation 允许指定小于 --memory 的软限制 ,当 Docker 检测到主机上的争用或内存不足时会激活该限制,如果使-- memory-reservation,则必须将其设置为低于 --memory 才能使其优先生效。 因为它是软限制,所以不能保证容器不超过限制 --kernel-memory 容器可以使用的最大内核内存量,最小为 4m,由于内核内存与用户空间内存隔离,因此无法与用户空间内存直接交换,因此内核内存不足的容器可能会阻塞宿主机资源,这会对主机和其他容器或者其他服务进程产生影响,因此不建议设置内核内存大小 --oom-kill-disable 默认情况下,如果发生内存不足(OOM)错误,则内核将终止容器中的进程。要更改此行为,请使用该 --oom-kill-disable 选项。建议仅在设置了该 -m/--memory 选项的容器上禁用OOM。如果 -m 未设置该标 志,则主机可能会用完内存,内核可能需要终止主机系统的进程以释放内存 docker run -e MYSQL_ROOT_PASSWORD=123456 -it --rm -m 1g --oom-kill-disable mysql:5.7.30 #运行myql数据库,最大内存为1G,且禁止删除,也就是关闭OOM机制,--oom-kill-disable

CPU限制选项

sh
--cpus= 指定一个容器可以使用多少个可用的CPU核心资源。例如,如果主机有两个CPU,如果设置了 --cpus="1.5" ,则可以保证容器最多使用1.5个的CPU(如果是4核CPU,那么还可以是4核心上每核用一点,但是总计是1.5核心的CPU)。这相当于设置 --cpu-period="100000" 和 --cpu-quota="150000" 。此设置可在Docker 1.13及更高版本中可用,目的是替代--cpu-period和--cpu-quota两个参数,从而使配置更简单,但是最大不能超出宿主机的CPU总核心数(在操作系统看到的CPU超线程后的数值),此项较常用 --cpuperiod= 过时选项,指定CPU CFS调度程序周期,必须与 --cpu-quota 一起使用 。默认为100微秒。大多数用户不会更改默认设置。如果使用Docker 1.13或更高版本,请改用 --cpus --cpu-quota= 过时选项,在容器上添加 CPU CFS 配额,计算方式为 cpu-quota / cpu-period的结果值,docker1.13 及以上版本通常使用--cpus 设置此值 --cpusetcpus 用于指定容器运行的 CPU 编号,也就是所谓的CPU绑定。如果一个或多个CPU,则容器可以使用逗号分隔的列表或用连字符分隔的CPU范围。第一个CPU的编号为0。有效值可能是 0-3 (使用第一,第二,第三和第四CPU)或1,3 (使用第二和第四CPU) --cpu-shares 用于设置 cfs 中调度的相对最大比例权重,cpu-share 的值越高的容器,将会分得更多的时间片(宿主机多核 CPU 总数为 100%,假如容器 A 为1024,容器 B 为2048,那么容器 B 将最大是容器 A 的可用 CPU 的两倍 ),默认的时间片1024,最大 262144。这是一个软限制。注意:进程数要多个CPU的核数才能看 到效果,此值不能设置太小 docker run -it --rm --cpus 1.5 lorel/docker-stress-ng --cpu 4 #工作在4个CPU上,使用总容量cpu为1.5,将会均匀的分散在4个cpu
19、获取容器IP地址
c
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container-name
如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:笑一个吧~

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 本文为博主「笑一个吧~」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 许可协议。转载请注明出处!