• Docker(狂神)


    Docker概述

    Docker为什么出现?

    一款产品:开发,上线,两套环境,应用环境,应用配置

    开发,运维

    环境配置十分麻烦,每一个机器都要部署环境,费时费力。

    发布一个项目,(jar+Redis,MySQL,jdk,ES),项目能不能都带上环境安装打包

    在服务器配置一个应用的环境,配置超麻烦,不能够跨平台

    Window,最后发布到Linux,环境有天壤之别

    传统:开发jar,运维来做

    现在:开发打包部署上线,一套流程做完


    Docker给以上的问题,提出了解决方案

    java --- jar(环境)--- 打包项目带上环境(镜像)--- (Docker仓库:商店)--- 下载发布的镜像 --- 直接运行即可!

    Docker的思想就来自于集装箱

    JRE --- 多个应用(端口冲突)--- 原来都是交叉的

    隔离:Docker核心思想!打包装箱!每个箱子是互相隔离的。

    Docker通过隔离机制,可以将服务器利用到极致

    本质:所有的技术都是因为出现了一些问题,我们需要去解决,才去学习。


    Docker的历史

    Docker为什么这么火?十分轻巧!

    容器技术出来之前,我们都是使用虚拟机技术

    虚拟机是虚拟化技术,Docker容器技术,也是一种虚拟化技术

    虚拟机:在window中装一个Vmware,通过这个软件我们可以虚拟出来一台或者多台电脑,笨重

    Vmware:Linux centos原生镜像(一个电脑),隔离需要开启多个虚拟机,几个G,几分钟

    Docker:隔离,镜像(最核心的环境 jdk,mysqll)十分小巧,运行镜像就可以了,几个M,秒级启动


    聊聊Docker

    Docker是基于Go语言开发的!开源项目!

    官网:Docker: Accelerated, Containerized Application Development

    文档地址:Docker Documentation | Docker Documentation

     仓库地址:Docker Hub


     Docker能干嘛

    之前的虚拟机技术

    虚拟机技术缺点:

    1.资源占用十分多

    2.冗余步骤多

    3.启动很慢 

     容器化技术

    容器化技术不是模拟的一个完整的操作系统

     比较Docker和虚拟机技术的不同:

    • 传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
    • 容器内的应用直接运行在宿主机的内核,容器是没有自己的内核的,也没有虚拟硬件,所以轻便
    • 每个容器间互相隔离,每个容器内都有一个属于自己的文件系统,互不影响。

    DevOps(开发,运维)

    应用更快速的交付和部署

    传统:一堆帮助文档,安装程序

    Docker:打包镜像发布测试,一件运行

    更便捷的升级和扩缩容

    使用了Docker之后,部署应用和搭积木一样

    项目打包为一个镜像,扩展服务器A ,服务器B

    更简单的系统运维

    在容器之后,我们的开发,测试环境都是高度一致的

    更高效的计算资源利用

    Docker是内核级别的虚拟化,在一个物理机上可以运行很多容器实例,服务器的性能可以被压榨到极致


    Docker基本组成

    镜像(image):

    docker镜像就好比是一个模板,可以通过这个模板来创建容器服务

    tomcat镜像 ==> run ==> tomcat01容器(提供服务器),

    通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。

    容器(container):

    Docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。

    启动,停止,删除,基本命令!

    目前就可以把这个容器理解为就是一个简易的linux系统

    仓库(repository): 

    仓库就是存放镜像的地方!

    仓库分为公有仓库和私有仓库!

    Docker Hub(默认是国外的)

    阿里云...都有容器服务器(配置镜像加速)


    安装Docker

    环境准备

     1.需要一点点的Linux的基础

    2.CentOS

    3.shell远程连接服务器进行操作

    环境查看

    1. #系统内核时3.10以上的
    2. [root@localhost /]# uname -r
    3. 3.10.0-957.el7.x86_64
    1. #系统版本
    2. [root@localhost /]# cat /etc/os-release
    3. NAME="CentOS Linux"
    4. VERSION="7 (Core)"
    5. ID="centos"
    6. ID_LIKE="rhel fedora"
    7. VERSION_ID="7"
    8. PRETTY_NAME="CentOS Linux 7 (Core)"
    9. ANSI_COLOR="0;31"
    10. CPE_NAME="cpe:/o:centos:centos:7"
    11. HOME_URL="https://www.centos.org/"
    12. BUG_REPORT_URL="https://bugs.centos.org/"
    13. CENTOS_MANTISBT_PROJECT="CentOS-7"
    14. CENTOS_MANTISBT_PROJECT_VERSION="7"
    15. REDHAT_SUPPORT_PRODUCT="centos"
    16. REDHAT_SUPPORT_PRODUCT_VERSION="7"

    安装

    帮助文档:

    1. #1.卸载旧的版本
    2. yum remove docker \
    3. docker-client \
    4. docker-client-latest \
    5. docker-common \
    6. docker-latest \
    7. docker-latest-logrotate \
    8. docker-logrotate \
    9. docker-engine
    10. #2.需要的安装包
    11. yum install -y yum-utils
    12. #3.设置镜像的仓库
    13. yum-config-manager \
    14. --add-repo \
    15. https://download.docker.com/linux/centos/docker-ce.repo #默认是从国外的!
    16. yum-config-manager \
    17. --add-repo \
    18. http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo#推荐使用阿里云的,十分的快
    19. #更新yum软件包索引
    20. yum makecache fast
    21. #4.安装docker docker-ce社区版 ee企业版
    22. yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
    23. #5.启动docker
    24. systemctl start docker
    25. #6.查看docker版本,是否启动成功
    26. docker version
    27. #7.启动hello-world镜像
    28. docker run hello-world
    29. #8.查看hello-world镜像
    30. docker images
    31. #9.docker run hello-world
    32. docker run hello-world
    33. #卸载docker
    34. #1.卸载依赖
    35. yum remove docker-ce docker-ce-cli containerd.io docker-compose-plugin
    36. #2.删除资源
    37. #/var/lib/docker docker的默认工作路径
    38. rm -rf /var/lib/docker

    阿里云镜像加速

    1.登录阿里云找到容器服务

    2.找到镜像加速地址

     3.配置使用

    1. sudo mkdir -p /etc/docker
    2. sudo tee /etc/docker/daemon.json <<-'EOF'
    3. {
    4. "registry-mirrors": ["https://6a7n8bhy.mirror.aliyuncs.com"]
    5. }
    6. EOF
    7. sudo systemctl daemon-reload
    8. sudo systemctl restart docker

     回顾HelloWorld流程

     


    底层原理

    Docker是怎么工作的?

    Docker是一个Client - Server结构的系统,Docker的守护进程在主机上,通过Socke从客户端访问!

    DockerServer接收到Docker-Client的指令,就会执行这个命令

     Docker为什么比VM快?

    1.Docker有着比虚拟机更少的抽象层。

    2.Docker利用的是宿主机的内核,vm需要是Guest OS。

    所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统,避免引导操作。虚拟机是加载GuestOS,分钟级别的,而docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级。


    Docker的常用命令

    帮助命令

    1. docker version #显示docker的版本信息
    2. docker info #显示docker的系统信息,包括镜像和容器的数量
    3. docker 命令 --help #帮助命令

    帮助文档地址:Reference documentation | Docker Documentation

    镜像命令

    docker images 查看所有本地的主机上的镜像

    1. [root@localhost /]# docker images
    2. REPOSITORY TAG IMAGE ID CREATED SIZE
    3. hello-world latest feb5d9fea6a5 13 months ago 13.3kB
    4. #解释
    5. REPOSITORY 镜像的仓库源
    6. TAG 镜像的标签
    7. CREATED 镜像的创建时间
    8. SIZE 镜像的大小
    9. #可选项
    10. Options:
    11. -a, --all # 列出所有镜像
    12. -q, --quiet # 只显示镜像的id

    docker search 镜像名 搜索镜像

    1. [root@localhost ~]# docker search mysql
    2. NAME DESCRIPTION STARS OFFICIAL AUTOMATED
    3. mysql MySQL is a widely used, open-source relation… 13472 [OK]
    4. mariadb MariaDB Server is a high performing open sou… 5142 [OK]
    5. phpmyadmin phpMyAdmin - A web interface for MySQL and M… 689 [OK]
    6. percona Percona Server is a fork of the MySQL relati… 593 [OK]
    7. bitnami/mysql Bitnami MySQL Docker Image 79 [OK]
    8. #可选项,通过搜索来过滤
    9. --filter=STARS=3000 #搜索出来的镜像就是STARS大于3000的
    10. [root@localhost ~]# docker search mysql --filter=STARS=3000
    11. NAME DESCRIPTION STARS OFFICIAL AUTOMATED
    12. mysql MySQL is a widely used, open-source relation… 13472 [OK]
    13. mariadb MariaDB Server is a high performing open sou… 5142 [OK]

    docker pull 镜像名[:tag]下载镜像

    1. #下载镜像 docker pull 镜像名[:tag]
    2. [root@localhost ~]# docker pull mysql
    3. Using default tag: latest #如果不写 tag,默认就是latest
    4. latest: Pulling from library/mysql
    5. 72a69066d2fe: Pull complete #分层下载,docker image的核心,联合文件系统
    6. 93619dbc5b36: Pull complete
    7. 99da31dd6142: Pull complete
    8. 626033c43d70: Pull complete
    9. 37d5d7efb64e: Pull complete
    10. ac563158d721: Pull complete
    11. d2ba16033dad: Pull complete
    12. 688ba7d5c01a: Pull complete
    13. 00e060b6d11d: Pull complete
    14. 1c04857f594f: Pull complete
    15. 4d7cfa90e6ea: Pull complete
    16. e0431212d27d: Pull complete
    17. Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 #签名
    18. Status: Downloaded newer image for mysql:latest
    19. docker.io/library/mysql:latest #真实地址
    20. #等价命令
    21. docker pull mysql
    22. docker pull docker.io/library/mysql:latest
    23. #指定版本下载
    24. [root@localhost ~]# docker pull mysql:5.7
    25. 5.7: Pulling from library/mysql
    26. 72a69066d2fe: Already exists
    27. 93619dbc5b36: Already exists
    28. 99da31dd6142: Already exists
    29. 626033c43d70: Already exists
    30. 37d5d7efb64e: Already exists
    31. ac563158d721: Already exists
    32. d2ba16033dad: Already exists
    33. 0ceb82207cd7: Pull complete
    34. 37f2405cae96: Pull complete
    35. e2482e017e53: Pull complete
    36. 70deed891d42: Pull complete
    37. Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
    38. Status: Downloaded newer image for mysql:5.7
    39. docker.io/library/mysql:5.7

     docker rmi  -f  镜像id/镜像名  删除镜像

    1. [root@localhost ~]# docker rmi -f 镜像id #删除指定的镜像
    2. [root@localhost ~]# docker rmi -f 镜像id 镜像id 镜像id #删除多个镜像
    3. [root@localhost ~]# docker rmi -f $(docker images -aq) #删除全部的容器

    容器命令

    说明:有了镜像才可以创建容器,linux,下载一个centos镜像测试学习

    docker pull centos

    新建容器并启动

    docker run [可选参数] image

    #参数说明
    --name="Name" 容器名字 tomcat01 tomcat02,用来区分容i去
    -d  后台方式运行
    -it 使用交互方式运行,进入容器查看内容
    -p  指定容器的端口 -p 8080:8080
      -p ip:主机端口:容器端口
      -p 主机端口:容器端口(常用)
      -p 容器端口
    -p 随机指定端口

    1. #测试,启动并进入容器
    2. [root@localhost ~]# docker run -it centos /bin/bash
    3. [root@8bfe65458325 /]# ls #查看容器内的centos,基础版本,
    4. bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
    5. # 从容器中退回主机
    6. [root@a84b2702bfe0 /]# exit
    7. exit
    8. [root@localhost /]# ls
    9. bin dev home lib64 mnt proc run srv tmp var
    10. boot etc lib media opt root sbin sys usr

    列出所有运行的容器

    docker ps 命令
         #列出当前正在运行的容器
    -a   #列出当前正在运行的容器+历史运行过的容器
    -n=? #显示最近创建的容器
    -q   #只显示容器的编号 

    1. [root@localhost /]# docker ps
    2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    3. [root@localhost /]# docker ps -a
    4. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    5. a84b2702bfe0 centos "/bin/bash" 8 minutes ago Exited (0) 8 minutes ago great_elgamal

    退出容器

    exit #直接容器停止并退出
    ctrl + p + q #容器不停止退出

    删除容器

    docker rm 容器id #删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm -f
    docker rm -f $(docker ps -aq) #删除所有的容器
    docker ps -a -q|xargs docker rm #删除所有的容器

    启动和停止容器的操作

    docker start 容器id #启动容器
    docker restart 容器id #重启容器
    docker stop 容器id #停止当前正在运行的容器
    docker kill 容器id #强制停止当前容器

    常用其他命令

    后台启动容器

    docker run -d 镜像名

    1. docker run -d centos
    2. #问题docker ps,发现centos停止了
    3. #常见的坑,docker容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
    4. #容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了

    查看日志

    docker logs -tf --tail 容器id

    1. #自己编写一段shell脚本
    2. [root@localhost bin]# docker run -d centos /bin/sh -c "while true;do echo kuangshen;sleep 1;done"
    3. #docker ps
    4. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    5. 8d2913187b91 centos "/bin/sh -c 'while t…" 14 seconds ago Up 14 seconds eloquent_shamir
    6. #显示日志
    7. -tf #显示日志
    8. --tail number #显示日志条数
    9. [root@localhost bin]# docker logs -tf --tail 10 8d2913187b91

    查看容器中进程信息 ps

    docker top 容器id

    1. #命令docker top 容器id
    2. [root@localhost /]# docker top 8d2913187b91
    3. UID PID PPID C STIME TTY TIME CMD
    4. root 32058 32037 0 01:14 ? 00:00:00 /bin/sh -c while true;do echo kuangshen;sleep 1;done
    5. root 40447 32058 0 01:23 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1

    查看镜像的元数据

    docker inspect 镜像id

    1. [root@localhost /]# docker inspect 5d0da3dc9764
    2. [
    3. {
    4. "Id": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
    5. "RepoTags": [
    6. "centos:latest"
    7. ],
    8. "RepoDigests": [
    9. "centos@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177"
    10. ],
    11. "Parent": "",
    12. "Comment": "",
    13. "Created": "2021-09-15T18:20:05.184694267Z",
    14. "Container": "9bf8a9e2ddff4c0d76a587c40239679f29c863a967f23abf7a5babb6c2121bf1",
    15. "ContainerConfig": {
    16. "Hostname": "9bf8a9e2ddff",
    17. "Domainname": "",
    18. "User": "",
    19. "AttachStdin": false,
    20. "AttachStdout": false,
    21. "AttachStderr": false,
    22. "Tty": false,
    23. "OpenStdin": false,
    24. "StdinOnce": false,
    25. "Env": [
    26. "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
    27. ],
    28. "Cmd": [
    29. "/bin/sh",
    30. "-c",
    31. "#(nop) ",
    32. "CMD [\"/bin/bash\"]"
    33. ],
    34. "Image": "sha256:f5b050f177fd426be8fe998a8ecf3fb1858d7e26dff4080b29a327d1bd5ba422",
    35. "Volumes": null,
    36. "WorkingDir": "",
    37. "Entrypoint": null,
    38. "OnBuild": null,
    39. "Labels": {
    40. "org.label-schema.build-date": "20210915",
    41. "org.label-schema.license": "GPLv2",
    42. "org.label-schema.name": "CentOS Base Image",
    43. "org.label-schema.schema-version": "1.0",
    44. "org.label-schema.vendor": "CentOS"
    45. }
    46. },
    47. "DockerVersion": "20.10.7",
    48. "Author": "",
    49. "Config": {
    50. "Hostname": "",
    51. "Domainname": "",
    52. "User": "",
    53. "AttachStdin": false,
    54. "AttachStdout": false,
    55. "AttachStderr": false,
    56. "Tty": false,
    57. "OpenStdin": false,
    58. "StdinOnce": false,
    59. "Env": [
    60. "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
    61. ],
    62. "Cmd": [
    63. "/bin/bash"
    64. ],
    65. "Image": "sha256:f5b050f177fd426be8fe998a8ecf3fb1858d7e26dff4080b29a327d1bd5ba422",
    66. "Volumes": null,
    67. "WorkingDir": "",
    68. "Entrypoint": null,
    69. "OnBuild": null,
    70. "Labels": {
    71. "org.label-schema.build-date": "20210915",
    72. "org.label-schema.license": "GPLv2",
    73. "org.label-schema.name": "CentOS Base Image",
    74. "org.label-schema.schema-version": "1.0",
    75. "org.label-schema.vendor": "CentOS"
    76. }
    77. },
    78. "Architecture": "amd64",
    79. "Os": "linux",
    80. "Size": 231268856,
    81. "VirtualSize": 231268856,
    82. "GraphDriver": {
    83. "Data": {
    84. "MergedDir": "/var/lib/docker/overlay2/9372640e37b7350657b835f7866b3ca75df7ea4caabb33ea88194e057e899bd9/merged",
    85. "UpperDir": "/var/lib/docker/overlay2/9372640e37b7350657b835f7866b3ca75df7ea4caabb33ea88194e057e899bd9/diff",
    86. "WorkDir": "/var/lib/docker/overlay2/9372640e37b7350657b835f7866b3ca75df7ea4caabb33ea88194e057e899bd9/work"
    87. },
    88. "Name": "overlay2"
    89. },
    90. "RootFS": {
    91. "Type": "layers",
    92. "Layers": [
    93. "sha256:74ddd0ec08fa43d09f32636ba91a0a3053b02cb4627c35051aff89f853606b59"
    94. ]
    95. },
    96. "Metadata": {
    97. "LastTagTime": "0001-01-01T00:00:00Z"
    98. }
    99. }
    100. ]

     进入当前正在运行的容器

    docker exec -it 容器id bashShell

    1. [root@localhost /]# docker ps
    2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    3. 8d2913187b91 centos "/bin/sh -c 'while t…" 30 minutes ago Up 30 minutes eloquent_shamir
    4. [root@localhost /]# docker exec -it 8d2913187b91 /bin/bash
    5. [root@8d2913187b91 /]# ls
    6. bin etc lib lost+found mnt proc run srv tmp var
    7. dev home lib64 media opt root sbin sys usr
    8. [root@8d2913187b91 /]# ps -ef
    9. UID PID PPID C STIME TTY TIME CMD
    10. root 1 0 0 06:14 ? 00:00:00 /bin/sh -c while true;do echo kuangshen;sleep 1;don
    11. root 1877 0 0 06:45 pts/0 00:00:00 /bin/bash
    12. root 1922 1 0 06:46 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /
    13. root 1923 1877 0 06:46 pts/0 00:00:00 ps -ef

    docker attach 容器id

    1. [root@localhost /]# docker ps
    2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    3. 8d2913187b91 centos "/bin/sh -c 'while t…" 40 minutes ago Up 40 minutes eloquent_shamir
    4. [root@localhost /]# docker attach 8d2913187b91
    5. kuangshen
    6. kuangshen
    7. kuangshen

    docker exec 进入容器后开启一个新的终端,可以在里面操作(常用)

    docker attach 进入容器正在执行的终端,不不会启动新的进程

    从容器内拷贝文件到主机上

    docker cp 容器id:容器内路径 目的主机路径

    拷贝是一个手动过程,未来使用-v数据卷的技术,可以实现同步

    小结


    作业练习

    Docker 安装nginx

    1. 1.搜索镜像 search 建议去搜索dockerhub,可以看到帮助文档
    2. 2.下载镜像 pull
    3. 3.运行测试
    4. [root@localhost /]# docker images
    5. REPOSITORY TAG IMAGE ID CREATED SIZE
    6. nginx latest 605c77e624dd 10 months ago 141MB
    7. centos latest 5d0da3dc9764 14 months ago 231MB
    8. -d 后台运行
    9. --name 给容器命名
    10. -p 宿主机端口,容器内部端口
    11. [root@localhost /]# docker run -d --name nginx01 -p 3344:80 nginx
    12. 772aae3684a42353aa0542614d76b58e096130f5f7a675bec0e6a23abe172217
    13. [root@localhost /]# docker ps
    14. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    15. 772aae3684a4 nginx "/docker-entrypoint.…" 6 seconds ago Up 5 seconds 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01
    16. [root@localhost /]# curl localhost:3344
    17. #进入容器
    18. [root@localhost /]# docker exec -it nginx01 /bin/bash
    19. root@772aae3684a4:/# whereis nginx
    20. nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
    21. root@772aae3684a4:/# cd /etc/nginx
    22. root@772aae3684a4:/etc/nginx# ls
    23. conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params

     思考问题:每次改动nginx配置文件,都需要进入容器内部,十分的麻烦,要是可以在容器外部提供一个映射路径,达到在容器修改文件名,容器内部就可以自动修改了:数据卷 -v

     Docker 安装 Tomcat

    1. #官方使用,用完即删
    2. docker run -it --rm tomcat:9.0
    3. #下载
    4. docker pull tomcat:9.0
    5. #启动运行
    6. docker run -d -p 3355:8080 --name tomcat01 tomcat
    7. #测试访问没有问题
    8. #进入容器
    9. docker exec -it tomcat01 /bin/bash
    10. #发现问题:1.linux命令少了,2.没有webapps,阿里云镜像的原因,默认是最小的镜像,所有不必要的都剔除掉。
    11. #保证最小可运行的环境

    Docker 部署ES+Kibana

    后期学习......


    可视化

    • portainer(先用这个)
    • Ranche(CI/CD再用)

    什么是portainer?

    Docker图像化界面管理工具,提供一个后台面板供我们操作

    1. docker run -d -p 8088:9000 \
    2. --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

    访问测试:外网:http://ip:8088

     

     可视化面板平时不会使用,玩玩即可

    Docker镜像讲解

    镜像是什么

    镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
    所有的应用,直接打包docker镜像,就可以直接跑起来!如何得到镜像︰

    • 从远程仓库下载·
    • 拷贝
    • 自己制作一个镜像DockerFile

    Docker镜像加载原理

    UnionFS(联合文件系统)

     UnionFS ( 联合文件系统): Union文件系统(UnionFS )是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtualfilesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
    特性∶一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

    Docker镜像加载原理

    docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
    bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的LinuxUnix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs
    rootfs (root file system),在bootis之上。包含的就是典型Linux系统中的/dev,/proc, /bin, /etc等标准目录和文件rootfs就是各种不同的操作系统发行版,比如Ubuntu , Centos等等。
     

     平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M ?

     对于一个精简的OS , rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel ,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别,因此不同的发行版可以公用bootfs。

    分层理解

    分层的镜像

    我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载

     

     

     

     

     特点

    Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!

    这一层就是我们通常说的容器层,容器之下的都叫镜像层!

     如何提交一个自己的镜像

    commit镜像

    docker commit 提交容器成为一个新的副本

    docker commit  -m="提交的秒速信息" -a "作者" 容器id  目标镜像名:[TAG]

    实战测试

    1. 1.启动一个默认的tomcat
    2. 2.发现这个默认的tomcat是没有webapps应用,镜像的原因,官方的镜像默认webapps下面是没有文件的!
    3. 3.自己拷贝进去了基本的文件
    4. 4.将我们操作过的容器通过commit提交为一个镜像!以后就使用修改过的镜像即可

    入门Docker

    容器数据卷

    什么是容器数据卷

    docker的理念回顾

    将一个应用和环境打包成一个镜像

    数据,如果数据都在容器中,那么容器删除,数据就会丢失!需求:数据可以持久化

    Mysql,容器删了,删库跑路!需求:MySQL数据可以村粗在本地!

    容器之间可以有一个数据共享的技术Docker容器中产生的数据,同步到本地

    这就是卷技术!目录的挂载,将容器内的目录,挂载到Linux上面

     总结一句话,容器的持久化和同步操作,容器间也是可以数据共享的

    使用数据卷

    方式一:直接使用命令来挂载 -v

    docker run -it -v 主机目录:容器内目录

    1. #测试
    2. docker run -it -v /home/ceshi:/home centos /bin/bash
    3. #启动起来时候可以通过 docker inspect 容器id

     测试文件同步

    再来测试

    1.停止容器

    2.宿主机修改文件

    3.启动容器

    4.容器内的数据依旧是同步的

    好处:我们以后修改只需要在本地修改即可,容器内自动同步

    实战:安装MySQL

    思考:MySQL的数据持久化的问题!

    1. 获取镜像
    2. docker pull mysql
    3. 运行容器,需要做数据卷挂载
    4. 安装启动mysql,需要配置密码的,这是需要注意的点!
    5. 官方测试:docker run --name some-mysql -v /my/custom:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
    6. 启动
    7. -d 后台运行
    8. -p 端口映射
    9. -v 卷挂载
    10. -e 环境配置
    11. --name 容器名字
    12. docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql
    13. 启动成功之后,本地使用sqlyog测试一下
    14. sqlyog-连接到服务器的3310 --- 3310 和容器内的3306映射,这个时候我们就可以连接上了
    15. 在本地测试创建一个数据库,查看一下映射的路径是否ok

    假设我们将容器删除

     发现,挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能!

    具名和匿名挂载

    1. 匿名挂载
    2. -v 容器内路径
    3. docker run -d -p --name nginx01 -v /etc/nginx nginx
    4. 查看所有的volumn的情况
    5. docker volumn ls
    6. DRIVER VOLUME NAME
    7. local c5939a06fb07fe0a061b947a4689b8719922d31e1e724ea6111bfec991038089
    8. 这里发现,这就是匿名挂载,在-v只写了容器内的路径,没有写容器外的路径!
    9. 具名挂载
    10. docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
    11. 74268afa67eabdc938599073798d4ae4a6aab105df564df9be0ef11fa9f61636
    12. docker volume ls
    13. DRIVER VOLUME NAME
    14. local juming-nginx
    15. 通过-v 卷名:容器内路径
    16. 查看一下这个卷
    17. docker volume inspect 卷名

     所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxxx/_data

    通过具名挂载可以方便的找到一个卷,大多数情况下使用的具名挂载

    1. 如何确定是具名挂载还是匿名挂载,还是指定路径挂载
    2. -v 容器内路径 匿名挂载
    3. -v 卷名:容器内路径 具名挂载
    4. -v /宿主机路径::容器内路径 指定路径挂载

    扩展:

    1. 通过-v容器内路径:ro rw 改变读写权限
    2. ro readonly 只读
    3. rw readwrite 可读可写
    4. 一旦设置了容器权限,容器挂载出来的内同就有限定了
    5. docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
    6. ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内都是无法操作

    初识DockerFile

    DockerFile就是用来构建docker镜像的构建文件,命令脚本

    通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每个命令构建一层镜像

    1. 创建一个dockerfile文件,名字可以随机,建议Dockerfile
    2. 文件中的内容 指令(大写) 参数
    3. FROM centos
    4. VOLUME ["volume01","volume02"]
    5. CMD echo "----end----"
    6. CMD /bin/bash
    7. 这里的每个命令,就是镜像的一层

    启动自己的容器

     这个卷和外部一定有一个同步的目录

    查看一下 卷挂载的路径

    测试一下刚才的文件是否同步出去了

    这种方式未来使用的十分多,因为我们通常会构建自己的镜像

    假设构建镜像的时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径

    数据卷容器

    多个mysql同步数据

     

    1. 测试,可以删除docker01,查看一下docker02和docker03是否还可以访问这个文件
    2. 测试依旧可以访问

     多个mysql实现数据共享

    1. docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql
    2. docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql

    结论:

    容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止

    但是一旦持久化到了本地,这个时候,本地的数据是不会删除的

    DockerFile介绍

    dockerfile是用来构建docker镜像的文件,命令参数脚本

    构建步骤:

    1.编写一个dockerfile文件

    2.docker build构建成为一个镜像

    3.docker run 运行镜像

    4.docker push发布镜像(DockerHub,阿里云镜像仓库)

     很多官方镜像都是基础包,很多功能没有,通常会自己搭建自己的镜像

    官方既然可以制作镜像,那我们也可以

    DockerFile构建过程

     基础知识:

    1.每个保留关键字(指令)都是必须是大写字母

    2.执行从上到下顺序执行

    3.#表示注释

    4.每一个指令都会创建提交一个新的镜像层,并提交!

    dockerfile是面向开发的,以后要发布项目,做镜像,就是要编写dockerfile文件,这个文件十分简单

    Docker镜像逐渐成为企业交付的标准,必须要掌握

    步骤:开发,部署,运维,缺一不可

    DockerFile:构建文件,定义了一切的步骤,源代码

    DockerImage:通过DockerFile构建生成的镜像,最终发布和运行的产品,原来是jar war

    Docker容器:容器就是镜像运行起来提供服务的,

    DockerFile的指令

    以前都是使用别人的,现在知道这些指令后,来练习自己写一个镜像

    1. FROM 基础镜像 一切从这里开始构建
    2. MAINTAINER 镜像是谁写的 姓名+邮箱
    3. RUN 镜像构建的时候需要运行的命令
    4. ADD 步骤,tomcat镜像,这个tomcat压缩包,添加内容
    5. WORKDIR 镜像的工作目录
    6. VOLUME 挂载的目录
    7. EXPOSE 暴露端口配置
    8. CMD 指定这个容器启动的时候要运行的命令
    9. ENTRYPOINT 指定这个容器启动的时候要运行的命令,可以追加命令
    10. ONBUILD 当构建一个被继承 DockerFile这个时候就会运行ONBUILD的指令,触发指令
    11. COPY 类似ADD,将我们文件拷贝到镜像中
    12. ENV 构建的时候这是环境变量

    实战测试

    Docker Hub 中镜像都是从这个基础镜像过来的FROM scratch,然后配置需要的软件和配置来进行的构建

     创建一个自己的centos

    1. 1.编写dockerfile文件
    2. [root@localhost dockerfile]# cat mydockerfile-centos
    3. FROM centos:7
    4. MAINTAINER kuangshen<24736743@qq.com>
    5. ENV MYPATH /usr/local
    6. WORKDIR $MYPATH
    7. RUN yum -y install vim
    8. RUN yum -y install net-tools
    9. EXPOSE 80
    10. CMD echo $MYPATH
    11. CMD echo "----end----"
    12. CMD /bin/bash
    13. 2.通过这个文件构建镜像
    14. 命令 docker build -f dockerfile文件路径 -t 镜像名:[tag] .
    15. 3.测试运行

    对比:之前的原生的centos

     我们增加之后的镜像

     我们可以列出本地进行的变更历史

     我们平时拿到一个镜像,可以研究一下它是怎么做的了

    CMD

    1. CMD 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
    2. ENTRYPOINT 指定这个容器启动的时候要运行的命令,可以追加命令

    测试cmd

    1. 编写dockerfile文件
    2. vim dockerfile-cmd-test
    3. FROM centos
    4. CMD ["ls","-a"]
    5. 构建镜像
    6. docker build -f dockerfile-cmd-test -t cmdtest
    7. run运行,发现我们的ls -a命令生效
    8. docker run cmdtest
    9. .
    10. ..
    11. .dockerenv
    12. bin
    13. dev
    14. etc
    15. home
    16. lib
    17. lib64
    18. 想追加一个命令 -l ls -al
    19. docker run cmdtest -l
    20. docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.
    21. cmd的清理下 -l替换了CMD["ls","-a"]命令,-l不是命令所以报错

    测试ENTRYPOINT

    1. 编写dockerfile文件
    2. docker vim dockerfile-cmd-test
    3. FROM centos
    4. ENTRYPOINT ["ls","-a"]
    5. 构建镜像
    6. docker build -f dockerfile-cmd-entrypoint -t entrypoint-test .
    7. run运行,发现ls -a命令生效
    8. docker run entrypoint-test
    9. .
    10. ..
    11. .dockerenv
    12. bin
    13. dev
    14. etc
    15. home
    16. lib
    17. lib64
    18. 追加命令,是直接拼接在我们的ENTRYPOINT命令的后面
    19. docker run entrypoint-test -l
    20. total 0
    21. drwxr-xr-x. 1 root root 6 Nov 19 02:37 .
    22. drwxr-xr-x. 1 root root 6 Nov 19 02:37 ..
    23. -rwxr-xr-x. 1 root root 0 Nov 19 02:37 .dockerenv
    24. lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
    25. drwxr-xr-x. 5 root root 340 Nov 19 02:37 dev
    26. drwxr-xr-x. 1 root root 66 Nov 19 02:37 etc
    27. drwxr-xr-x. 2 root root 6 Nov 3 2020 home
    28. lrwxrwxrwx. 1 root root 7 Nov 3 2020 lib -> usr/lib
    29. lrwxrwxrwx. 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
    30. drwx------. 2 root root 6 Sep 15 2021 lost+found
    31. drwxr-xr-x. 2 root root 6 Nov 3 2020 media
    32. drwxr-xr-x. 2 root root 6 Nov 3 2020 mnt
    33. drwxr-xr-x. 2 root root 6 Nov 3 2020 opt
    34. dr-xr-xr-x. 132 root root 0 Nov 19 02:37 proc
    35. dr-xr-x---. 2 root root 162 Sep 15 2021 root
    36. drwxr-xr-x. 11 root root 163 Sep 15 2021 run
    37. lrwxrwxrwx. 1 root root 8 Nov 3 2020 sbin -> usr/sbin
    38. drwxr-xr-x. 2 root root 6 Nov 3 2020 srv
    39. dr-xr-xr-x. 13 root root 0 Nov 19 02:15 sys
    40. drwxrwxrwt. 7 root root 171 Sep 15 2021 tmp
    41. drwxr-xr-x. 12 root root 144 Sep 15 2021 usr
    42. drwxr-xr-x. 20 root root 262 Sep 15 2021 var

    实战Tomcat镜像

    1.准备镜像文件tomcat压缩包,jdk压缩包

    2.编写dockerfile文件,官方命名Dockerfile,build会自动寻找这个文件,就不需要-f指定了

    1. FROM centos:7
    2. MAINTAINER kuangshen<24736743@qq.com>
    3. COPY readme.txt /usr/local/readme.txt
    4. ADD jdk-11.0.17_linux-x64_bin.tar.gz /usr/local/
    5. ADD apache-tomcat-8.5.83.tar.gz /usr/local/
    6. RUN yum -y install vim
    7. ENV MYPATH /usr/local
    8. WORKDIR $MYPATH
    9. ENV JAVA_HOME /usr/local/jdk-11.0.17
    10. ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.83
    11. ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
    12. EXPOSE 8080
    13. CMD /usr/local/apache-tomcat-8.5.83/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.83/bin/logs/catalina.out

    3.构建镜像

    docker build -t divtomcat .
    

    4.启动镜像

    docker run -d -p 9090:8080 --name divtomcat -v /home/tomcat/test:/usr/local/apache-tomcat-8.5.83/webapps/test -v /home/tomcat/tomcatlogs/:/usr/local/apache-tomcat-8.5.83/logs divtomcat
    

     5.访问测试

    6.发布项目(由于做了卷挂载,我们直接在本地编写项目,)

    1. "1.0" encoding="UTF-8"?>
    2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xmlns="http://java.sun.com/xml/ns/javaee"
    4. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    5. id="WebApp_ID" version="3.0">
    6. web-app>
    1. <html>
    2. <head><title>Hello Worldtitle>head>
    3. <body>
    4. Hello World!<br/>
    5. <%
    6. System.out.println("---my test web logs------")
    7. %>
    8. body>
    9. html>

    发布自己的镜像

    DockerHub

    1.地址Docker Hub注册自己的账号

    2.确定这个账号可以登录

    3.在我们服务器上提交自己的镜像

    1. docker login --help
    2. Usage: docker login [OPTIONS] [SERVER]
    3. Log in to a Docker registry.
    4. If no server is specified, the default is defined by the daemon.
    5. Options:
    6. -p, --password string Password
    7. --password-stdin Take the password from stdin
    8. -u, --username string Username
    9. docker login -u slinamse
    10. Password:
    11. WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
    12. Configure a credential helper to remove this warning. See
    13. https://docs.docker.com/engine/reference/commandline/login/#credentials-store
    14. Login Succeeded

    4.登录完毕后就可以提交镜像了,就是一步docker push

    1. push自己的镜像到服务器上
    2. docker push divtomcat
    3. Using default tag: latest
    4. The push refers to repository [docker.io/library/divtomcat]
    5. 25184881c443: Preparing
    6. 46346a40c9c8: Preparing
    7. c80475c3dd48: Preparing
    8. bb4c74d38c89: Preparing
    9. 174f56854903: Preparing
    10. denied: requested access to the resource is denied 拒绝上传
    11. push镜像的问题
    12. docker push slinamse/divtomcat:1.0
    13. Using default tag: latest
    14. The push refers to repository [docker.io/slinamse/divtomcat]
    15. An image does not exist locally with the tag: slinamse/divtomcat
    16. 解决:增加一个tag
    17. 修改docker镜像为自己的tag,再push
    18. docker tag 773e23d296b1 slinamse/divtomcat:1.0
    19. docker push上传即可,自己发布的镜像尽量带上版本号
    20. docker push slinamse/divtomcat:1.0
    21. The push refers to repository [docker.io/slinamse/divtomcat]
    22. 25184881c443: Layer already exists
    23. 46346a40c9c8: Pushed
    24. c80475c3dd48: Pushed
    25. bb4c74d38c89: Pushed
    26. 174f56854903: Pushing 211.7MB

     提交的时候也是按照镜像的层级来进行提交的

    但是一般发布不上去,因为外网翻墙,网速很慢

    阿里云镜像服务上

    1.登录阿里云

    2.找到容器镜像服务,镜像仓库

    3.创建命名空间

     4.创建容器镜像

     5.浏览阿里云镜像

    1. docker login --username=aliyun1466620592 registry.cn-hangzhou.aliyuncs.com
    2. docker tag 773e23d296b1 registry.cn-hangzhou.aliyuncs.com/slinamse-test/slinamse-test:0.1
    3. docker push registry.cn-hangzhou.aliyuncs.com/slinamse-test/slinamse-test:0.1
    4. The push refers to repository [registry.cn-hangzhou.aliyuncs.com/slinamse-test/slinamse-test]
    5. 25184881c443: Layer already exists
    6. 46346a40c9c8: Layer already exists
    7. c80475c3dd48: Pushed
    8. bb4c74d38c89: Layer already exists
    9. 174f56854903: Layer already exists
    10. 0.1: digest: sha256:43404c5857d569450fabe0c5face46a3f171a336af4be9fc570c8080a46451d8 size: 1373

    小结:

    Docker网络

    理解Docker0

    1. ip addr
    2. 本地回环地址
    3. 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    4. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    5. inet 127.0.0.1/8 scope host lo
    6. valid_lft forever preferred_lft forever
    7. inet6 ::1/128 scope host
    8. valid_lft forever preferred_lft forever
    9. 本地网卡地址
    10. 2: ens33: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    11. link/ether 00:0c:29:da:2f:01 brd ff:ff:ff:ff:ff:ff
    12. inet 192.168.136.143/24 brd 192.168.136.255 scope global noprefixroute ens33
    13. valid_lft forever preferred_lft forever
    14. inet6 fe80::64ec:f766:8f82:e9df/64 scope link noprefixroute
    15. valid_lft forever preferred_lft forever
    16. docker0地址
    17. 3: docker0: mtu 1500 qdisc noqueue state UP group default
    18. link/ether 02:42:95:86:c6:94 brd ff:ff:ff:ff:ff:ff
    19. inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
    20. valid_lft forever preferred_lft forever
    21. inet6 fe80::42:95ff:fe86:c694/64 scope link
    22. valid_lft forever preferred_lft forever

    三个网络

    问题:docker是如何处理容器网络访问的?

    测试

    1. docker run -d -P --name tomcat01 tomcat
    2. 下载ip addr相关命令
    3. apt update && apt install -y iproute2 && apt install -y iputils-ping
    4. 查看容器的内部网络地址 ip addr,发现容器启动的时候会遇到一个eth0@if5 ip地址
    5. docker exec -it tomcat01 ip addr
    6. 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    7. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    8. inet 127.0.0.1/8 scope host lo
    9. valid_lft forever preferred_lft forever
    10. 4: eth0@if5: mtu 1500 qdisc noqueue state UP group default
    11. link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    12. inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
    13. valid_lft forever preferred_lft forever
    14. 思考,linux 能不能ping通容器内部
    15. ping 172.17.0.2
    16. PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
    17. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.032 ms
    18. 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.085 ms
    19. linux 可以ping通docker容器内部

    原理

    192.168.0.1路由器

    192.168.0.3用户

    同一个网段之间可以互相ping通

    1.我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0桥接模式,使用的技术是evth-pair技术!

     再次测试ip addr

    1. 再次测试ip addr
    2. 3: docker0: mtu 1500 qdisc noqueue state UP group default
    3. link/ether 02:42:95:86:c6:94 brd ff:ff:ff:ff:ff:ff
    4. inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
    5. valid_lft forever preferred_lft forever
    6. inet6 fe80::42:95ff:fe86:c694/64 scope link
    7. valid_lft forever preferred_lft forever
    8. 发现又多了一个网卡veth9cc68c7@if4,发现与容器内eth0@if5 ip地址具有疑似
    9. 5: veth9cc68c7@if4: mtu 1500 qdisc noqueue master docker0 state UP group default
    10. link/ether f2:c4:18:ab:3c:13 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    11. inet6 fe80::f0c4:18ff:feab:3c13/64 scope link
    12. valid_lft forever preferred_lft forever

    2.再启动一个容器测试,发现又多了一对网卡 

    1. docker run -d -P --name tomcat02 tomcat
    2. 再次测试ip addr
    3. 3: docker0: mtu 1500 qdisc noqueue state UP group default
    4. link/ether 02:42:a6:de:30:fd brd ff:ff:ff:ff:ff:ff
    5. inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
    6. valid_lft forever preferred_lft forever
    7. inet6 fe80::42:a6ff:fede:30fd/64 scope link
    8. valid_lft forever preferred_lft forever
    9. 5: veth38feead@if4: mtu 1500 qdisc noqueue master docker0 state UP group default
    10. link/ether f6:1a:6b:54:a8:cb brd ff:ff:ff:ff:ff:ff link-netnsid 0
    11. inet6 fe80::f41a:6bff:fe54:a8cb/64 scope link
    12. valid_lft forever preferred_lft forever
    13. 发现又多了一个网卡veth6e748f2@if6
    14. 7: veth6e748f2@if6: mtu 1500 qdisc noqueue master docker0 state UP group default
    15. link/ether da:ca:00:aa:47:e7 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    16. inet6 fe80::d8ca:ff:feaa:47e7/64 scope link
    17. valid_lft forever preferred_lft forever
    18. docker exec -it tomcat02 ip addr
    19. 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    20. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    21. inet 127.0.0.1/8 scope host lo
    22. valid_lft forever preferred_lft forever
    23. 6: eth0@if7: mtu 1500 qdisc noqueue state UP group default
    24. link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    25. inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
    26. valid_lft forever preferred_lft forever

    evth-pair

    我们发现这个容器带来网卡,都是一对对的
    evth-pair就是一对的虚拟设备接口,它们都是成对出现的,一端连着协议,一端彼此相连
    正因为有这个特性,evth-pair充当一个桥梁,连接各种虚拟网络设备的
    OpenStac,Docker容器之间的连接,OVS的连接,都是使用evth-pair技术

    3.测试下tomcat01和tomcat02是否可以ping通

    1. docker exec -it tomcat02 ping 172.17.0.3
    2. PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
    3. 64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.095 ms
    4. 64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.053 ms
    5. 64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.057 ms
    6. 64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.068 ms
    7. 64 bytes from 172.17.0.3: icmp_seq=5 ttl=64 time=0.082 ms
    8. 结论:容器和容器之间是可以互相ping通的

    绘制一个网络模型图

    结论:tomcat01和tomcat02是共用的一个路由器,docker0

    所有的容器不指定网络的情况下,都是docker0路由的,docker会给容器分配一个默认的可用ip

    小结

    Docker使用的是Linux的桥接,宿主机中是一个Docker容器的网桥docker01

    Docker中的所有的网络接口都是虚拟的、虚拟的转发效率高!(内网传递文件!)

    只要容器删除,对应网桥一对就没了

     --link

    思考一个场景,我们编写了一个微服务,database url=ip,项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以通过名字来进行访问容器

    1. docker exec -it tomcat02 ping tomcat01
    2. ping: tomcat01: Name or service not known
    3. 如何解决呢?
    4. docker run -d -P --name tomcat03 --link tomcat02 tomcat
    5. 通过--link就可以解决网络连通问题
    6. ping tomcat02
    7. PING tomcat02 (172.17.0.3) 56(84) bytes of data.
    8. 64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.055 ms
    9. 64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.053 ms
    10. 反向可以ping通吗
    11. docker exec -it tomcat02 ping tomcat03
    12. ping: tomcat03: Name or service not known

    探究:inspect  

    其实这个tomcat03就是本地配置了tomcat02的配置

    1. 查看hosts配置,在这里发现
    2. docker exec -it tomcat03 cat /etc/hosts
    3. 127.0.0.1 localhost
    4. ::1 localhost ip6-localhost ip6-loopback
    5. fe00::0 ip6-localnet
    6. ff00::0 ip6-mcastprefix
    7. ff02::1 ip6-allnodes
    8. ff02::2 ip6-allrouters
    9. 172.17.0.3 tomcat02 5effbeeb4b7c
    10. 172.17.0.4 4cee822592d1

    本质:--link就是在hosts配置中增加了一个172.17.0.3      tomcat02 5effbeeb4b7c

    现在Docker已经不建议使用--link了

    自定义网络,不使用docker0

    dockero问题:不支持容器名连接访问

    自定义网络

     查看所有的docker网络

    网络模式

    bridge:桥接docker ,默认,自己创建也使用bridge模式

    none:不配置网络

    host:和宿主机共享网络

    container:容器网络连通,用得少,局限很大

    测试

    1. 我们直接启动的命令 --net bridge,而这个就是我们的docker0
    2. docker run -d -P --name tomcat01 tomcat
    3. docker run -d -P --name tomcat01 --net bridge tomcat
    4. #docker0特点,默认,域名不能访问,--link可以大同连接
    5. 自定义一个网络
    6. --driver bridge 桥接模式
    7. --subnet 192.168.0.0/16 子网 192.168.0.2---192.168.255.255
    8. --gateway 192.168.0.1 网关
    9. docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
    10. docker network ls
    11. NETWORK ID NAME DRIVER SCOPE
    12. 57eac89ecd8a bridge bridge local
    13. 0905a85eac40 host host local
    14. 639be0d6bdc9 mynet bridge local
    15. bce6a2d97172 none null local

    自定义网络就创建好了

    1. docker run -d -P --name tomcat-net-01 --net mynet tomcat
    2. docker run -d -P --name tomcat-net-02 --net mynet tomcat
    3. docker network inspect mynet
    4. [
    5. {
    6. "Name": "mynet",
    7. "Id": "639be0d6bdc9d4d06aba226a2898ea02e888ed9b2a4cc976d4e2b3f5cf5abdfb",
    8. "Created": "2022-11-20T07:13:56.791006317-05:00",
    9. "Scope": "local",
    10. "Driver": "bridge",
    11. "EnableIPv6": false,
    12. "IPAM": {
    13. "Driver": "default",
    14. "Options": {},
    15. "Config": [
    16. {
    17. "Subnet": "192.168.0.0/16",
    18. "Gateway": "192.168.0.1"
    19. }
    20. ]
    21. },
    22. "Internal": false,
    23. "Attachable": false,
    24. "Ingress": false,
    25. "ConfigFrom": {
    26. "Network": ""
    27. },
    28. "ConfigOnly": false,
    29. "Containers": {
    30. "03dbf2422997905cd6b7f0f9b77a51386ba3d36dbe26e236ac71b4b8a0c225cf": {
    31. "Name": "tomcat-net-01",
    32. "EndpointID": "5c0f411e5c72ee18be8876b8765879cf189dc055389c39af29c90ad916e3ea35",
    33. "MacAddress": "02:42:c0:a8:00:02",
    34. "IPv4Address": "192.168.0.2/16",
    35. "IPv6Address": ""
    36. },
    37. "488f48b7b61205d8347d6fa60723a352b8c54d94576c924d66ca11e9f9f9f9b1": {
    38. "Name": "tomcat-net-02",
    39. "EndpointID": "42ca9197374959c971d3b225ca51e5fa0135555098ba14d2ab3b19875df31528",
    40. "MacAddress": "02:42:c0:a8:00:03",
    41. "IPv4Address": "192.168.0.3/16",
    42. "IPv6Address": ""
    43. }
    44. },
    45. "Options": {},
    46. "Labels": {}
    47. }
    48. ]
    49. 再次测试ping连接,不使用--link也可以ping名字了
    50. docker exec -it tomcat-net-01 ping tomcat-net-02
    51. PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
    52. 64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.118 ms
    53. 64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.098 ms
    54. 64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.072 ms
    55. 64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=4 ttl=64 time=0.074 ms
    56. 自定义网络docker都已经维护好了对应的关系,推荐平时这样使用网络

    好处:不同的集群使用不同的网络,保证集群是安全和健康的

    网络连通

    1. docker exec -it tomcat01 ping tomcat-net-01
    2. ping: tomcat-net-01: Name or service not known

    1. 测试打通tomcat01 - mynet
    2. 连通之后就是将tomcat01 放到了 mynet网络下
    3. 一个容器两个ip地址,
    4. 阿里云服务,公网ip,私网ip

    1. tomcat01已经打通
    2. docker exec -it tomcat01 ping tomcat-net-01
    3. PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
    4. 64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.077 ms
    5. 64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.072 ms
    6. 64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.064 ms
    7. 64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=4 ttl=64 time=0.042 ms
    8. tomcat02依旧打不通
    9. docker exec -it tomcat02 ping tomcat-net-01
    10. ping: tomcat-net-01: Name or service not known

    结论:假设要跨网络去操作别的容器,就需要使用docker network connect 连通

    实战:部署Redis集群

     shell脚本

    1. 创建网卡
    2. docker network create redis --subnet 172.38.0.0/16
    3. 通过脚本创建6个redis配置
    4. for port in $(seq 1 6); \
    5. do \
    6. mkdir -p /mydata/redis/node-${port}/conf
    7. touch /mydata/redis/node-${port}/conf/redis.conf
    8. cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
    9. port 6379
    10. bind 0.0.0.0
    11. cluster-enabled yes
    12. cluster-config-file nodes.conf
    13. cluster-node-timeout 5000
    14. cluster-announce-ip 172.38.0.1${port}
    15. cluster-announce-bus-port 16379
    16. appendonly yes
    17. EOF
    18. done
    19. 拉去镜像,启动6个容器,绑定相应配置
    20. docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
    21. -v /mydata/redis/node-1/data:/data \
    22. -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
    23. -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    24. docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
    25. -v /mydata/redis/node-2/data:/data \
    26. -v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
    27. -d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    28. docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
    29. -v /mydata/redis/node-3/data:/data \
    30. -v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
    31. -d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    32. docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
    33. -v /mydata/redis/node-4/data:/data \
    34. -v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
    35. -d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    36. docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
    37. -v /mydata/redis/node-5/data:/data \
    38. -v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
    39. -d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    40. docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
    41. -v /mydata/redis/node-6/data:/data \
    42. -v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
    43. -d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    44. 创建集群
    45. redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
    46. >>> Performing hash slots allocation on 6 nodes...
    47. Master[0] -> Slots 0 - 5460
    48. Master[1] -> Slots 5461 - 10922
    49. Master[2] -> Slots 10923 - 16383
    50. Adding replica 172.38.0.15:6379 to 172.38.0.11:6379
    51. Adding replica 172.38.0.16:6379 to 172.38.0.12:6379
    52. Adding replica 172.38.0.14:6379 to 172.38.0.13:6379
    53. M: 3c808269dcb3b53e1a6d14e399d78528d0a6decf 172.38.0.11:6379
    54. slots:[0-5460] (5461 slots) master
    55. M: 6fa354a2468f360a49db05b99dce672159054408 172.38.0.12:6379
    56. slots:[5461-10922] (5462 slots) master
    57. M: 0c342772509ab1f7f02af36af30818bd17f649ef 172.38.0.13:6379
    58. slots:[10923-16383] (5461 slots) master
    59. S: d8afaf32b9f0a5b0b0f12c3828c05ef51963aeb4 172.38.0.14:6379
    60. replicates 0c342772509ab1f7f02af36af30818bd17f649ef
    61. S: 5df846d03e0b228e414dab9a8346876c60db58c6 172.38.0.15:6379
    62. replicates 3c808269dcb3b53e1a6d14e399d78528d0a6decf
    63. S: 9eac1da9122fa14992f4b3eb8e03d8b4886f5a4b 172.38.0.16:6379
    64. replicates 6fa354a2468f360a49db05b99dce672159054408
    65. Can I set the above configuration? (type 'yes' to accept): yes
    66. 测试
    67. redis-cli -c
    68. 127.0.0.1:6379> cluster info
    69. cluster_state:ok
    70. cluster_slots_assigned:16384
    71. cluster_slots_ok:16384
    72. cluster_slots_pfail:0
    73. cluster_slots_fail:0
    74. cluster_known_nodes:6
    75. cluster_size:3
    76. cluster_current_epoch:6
    77. cluster_my_epoch:1
    78. cluster_stats_messages_ping_sent:315
    79. cluster_stats_messages_pong_sent:320
    80. cluster_stats_messages_sent:635
    81. cluster_stats_messages_ping_received:315
    82. cluster_stats_messages_pong_received:315
    83. cluster_stats_messages_meet_received:5
    84. cluster_stats_messages_received:635
    85. cluster nodes
    86. 5df846d03e0b228e414dab9a8346876c60db58c6 172.38.0.15:6379@16379 slave 3c808269dcb3b53e1a6d14e399d78528d0a6decf 0 1668993478529 5 connected
    87. d8afaf32b9f0a5b0b0f12c3828c05ef51963aeb4 172.38.0.14:6379@16379 slave 0c342772509ab1f7f02af36af30818bd17f649ef 0 1668993477553 4 connected
    88. 0c342772509ab1f7f02af36af30818bd17f649ef 172.38.0.13:6379@16379 master - 0 1668993478000 3 connected 10923-16383
    89. 3c808269dcb3b53e1a6d14e399d78528d0a6decf 172.38.0.11:6379@16379 myself,master - 0 1668993477000 1 connected 0-5460
    90. 9eac1da9122fa14992f4b3eb8e03d8b4886f5a4b 172.38.0.16:6379@16379 slave 6fa354a2468f360a49db05b99dce672159054408 0 1668993478637 6 connected
    91. 6fa354a2468f360a49db05b99dce672159054408 172.38.0.12:6379@16379 master - 0 1668993477553 2 connected 5461-10922
    92. 主机redis-3缓存
    93. set a b
    94. -> Redirected to slot [15495] located at 172.38.0.13:6379
    95. OK
    96. 停止主机redis-3
    97. docker stop redis-3
    98. 从机redis-4代替redis-3
    99. get a
    100. -> Redirected to slot [15495] located at 172.38.0.14:6379
    101. "b"

    SpringBoot微服务打包Docker镜像

    1.构建springboot项目

    2.打包应用

    docker-0.0.1-SNAPSHOT.jar

     3.编写dockersFile

    1. FROM java:8
    2. COPY *.jar /app.jar
    3. CMD ["--server.port=8080"]
    4. EXPOSE 8080
    5. ENTRYPOINT ["java","-jar","/app.jar"]

    4.构建镜像

    docker build -f /home/idea/DockerFile -t dockeridea .

    5.发布运行

    docker run -d -P --name springboot-web dockeridea
    

     以后我们使用Docker之后,给别人的就是一个镜像即可!

    到了这里已经完全够用Docker了

    Docker Compose

    如果有很多镜像需要发布维护怎么办呢?

    在阿里云买4台服务器

    4台服务器安装docker

    技巧:命令编辑器全部共享

    工作模式

    管理节点,工作节点,操作都在管理节点上

     搭建集群

     

     私网,公网,走私网不耗流量

     初始化节点docker swarm init

    docker swarm join 加入一个节点

    1. 获取令牌
    2. docker swarm join-token manager
    3. docker swarm join-token worker

     把后面的节点都搭建进去

     1.生产主节点init

    2.加入(Manager、Worker)

    目标:双主双从

    扩展到K8S

    云原生时代

    Go语言!必须掌握!Java、Go

    Docker是Go开发的

    K8S也是Go语言

    大趋势

    Docker Swarm k8s

    CI/CD之Jenkins

  • 相关阅读:
    python 实现银行卡号查询银行名称和简称
    Flink 任务Checkpoint 过短引起集群IO瓶颈问题
    SpringIoc依赖查找-5
    Socket网络编程练习题五:客户端多用户上传文件(多线程版)并使用线程池管理线程
    操作系统的知识点总结
    以创新抵御经济环境压力:自动化测试ReadyAPI帮助企业平衡软件质量与成本控制
    uart_printf自定义串口printf输出
    [C++ 从入门到精通] 8.构造函数详解、explicit、初始化列表
    英语音标中难发的音汇总
    Mybatis 知识点大总结
  • 原文地址:https://blog.csdn.net/qq_57216731/article/details/127885233