Docker 知识点总结

2023年 10月 11日 55.1k 0

1. Docker 简介

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

Dcoker 是基于 Go 语言开发的,是一个开源项目。

官网:www.docker.com/

仓库:hub.docker.com/,相当于 GitHub ,可以发布镜像

1.1 Docker 为什么会出现?

当开发一款产品的时候,需要有开发和上线两套环境,不同环境需要使用不同的配置。

公司中会有两个角色:开发和运维。

问题:当我开发人员开发好一款产品之后再自己的电脑上可以运行,如果版本更新的话会导致服务器不可用的,对于运维人员来说是非常麻烦的。

环境配置非常的麻烦,每一个机器都要部署环境(集群 Redis 、ES、Hadoop)等等非常的费时费力。

发布一个项目的时候是以 jar 的方式,但是需要依赖一些环境(Rdis、MySQL、JDK 等),项目不能都带上环境安装打包。

假设之前在服务器配置一个应用的环境 Redis、MySQL、JDK,配置非常的麻烦,不能够实现跨平台,开发系统 Windows ,发布到 Linux

传统的开发中:开发人员打 jar 包,运维人员来进行部署上线

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

假设开发一个 apk 应用

  • java -- apk -- 发布(应用商店)-- 用户使用 apk -- 安装使用就可以
  • java -- jar(环境)-- 打包项目带上环境(镜像)-- (Docker仓库)-- 下载发布的镜像 -- 直接运行就可以。

Docker 对于上面的问题提出解决方案。

Docker 的思想就来自于集装箱。

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

隔离:Docker 核心思想,打包装箱,每个箱子都是互相隔离的,Docker 通过隔离机制,可以将服务器利用到机制。

1.2 Docker 的历史

2010 年,几个做 IT 的年轻人,在美国成立了一家公司“dotCloud”

这个公司开始是做一些 pass 的云计算服务的,LXC 有关的容器技术,它们将自己的技术(容器化技术)命名就是 Docker,Docker 刚刚诞生的时候,没有引起行业的注意,公司坚持不下去。

所以就选择了开源,2013 年 Docker 开源,开源之后越来越多的人发现了 Docker 的优点,火了之后 Docker 每一个月都会更新一个版本。2014 年 4 月 9 日,Docker1.0 发布。

在容器技术出现之前,我们都是使用的虚拟机技术。

虚拟机:在 windows 中装一个 vmware,通过这个软件我们可以虚拟出来一台或者多台电脑,非常的笨重。

虚拟机也是属于虚拟化技术;Docker 容器技术,也是一种虚拟化技术。

1.3 Docker 能干什么

虚拟机技术

一个电脑,电脑中有一个内核,一个运行需要的库,然后所有开发的软件运行在这个电脑上。

虚拟机技术缺点:

  • 资源占用非常多
  • 冗余步骤多(每次使用都需要手动开启)
  • 开启的客户端多了启动很慢
  • 容器化技术

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

    • 比较不同

    虚拟机是虚拟出一套硬件,运行一个完整的操作系统,在这个系统上安装和运行软件。

    容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有虚拟硬件,所以非常的轻便,每个容器之间是相互隔离,每个容器内都有一个属于自己的文件系统,互不影响。

    2. Docker 安装

    2.1 Docker 的基本组成

    • 镜像(image):

    镜像就好比一个模板,可以通过这个模板来创建容器服务,假设有一个 tomcat 镜像,通过 run 方法运行,tomcat01 容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。

    • 容器(container):

    利用容器技术做到独立运行一个或者一组应用,通过镜像来创建,可以假设容器就是一个简易的 Linux 系统

    • 仓库(repository)

    用来存放镜像的地方,仓库分为公有仓库和私有仓库

    Docker Hub 默认的国外的,阿里云、腾讯云等都有容器服务器

    2.2 安装 Dcoker

    • 环境准备

    一台 Linux 系统的服务器,CentOS 7

    安装

    参考地址:docs.docker.com/engine/inst…

  • 卸载旧的版本
  • sudo yum remove docker 
                      docker-client 
                      docker-client-latest 
                      docker-common 
                      docker-latest 
                      docker-latest-logrotate 
                      docker-logrotate 
                      docker-engine
    
  • 安装需要的安装包
  • sudo yum install -y yum-utils
    
  • 设置镜像的仓库
  • # 国外的,非常慢
    sudo yum-config-manager 
        --add-repo 
        https://download.docker.com/linux/centos/docker-ce.repo
        
    # 阿里云镜像安装地址
    yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    ​
    # 更新 yum 软件包索引
    yum makecache fast
    
  • 安装 docker 相关
  • sudo yum install docker-ce docker-ce-cli containerd.io
    ​
    yum install docker-ce-18.06.1.ce-3.el7 docker-ce-selinux-18.06.1.ce-3.el7
    ​
    sudo yum install docker-ce-18.06.1.ce-3.el7 docker-ce-cli-18.06.1.ce-3.el7 containerd.io
    
  • 启动 docker
  • systemctl start docker
    
  • 使用 docker version 查看是否安装成功
  • 测试 Hello,World
  • docker run hello-world
    

  • 查看一下下载的 hello-world 镜像
  • docker images
    

  • 卸载 docker
  • # 卸载依赖
    yum remove docker-ce docker-ce-cli containerd.io
    # 删除运行环境
    rm -rf /var/lib/docker
    /var/lib/docker //docker 的默认工作路径
    

    2.3 Dcoker Run 的运行流程

    Docker 是怎么工作的?

    Docker 是一个 Client-Server 结构的系统,Docker 是守护进程运行在主机上,通过 Socket 从客户端访问,Docker Server 接收到 Docker-Client 的指令,就会执行这个命令。

    Dcoker 为什么比 VM 快?

  • Docker 有着比虚拟机更少的抽象层
  • Dcoker 利用的是宿主机的内核,vm 需要的是 GuestOS
  • 新建一个容器的时候,docker 不需要像虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载 GuestOS,是分钟级别的;docker 是利用宿主机的操作系统,省略了复杂的引导过程,是秒级的。

    3. Docker 常用命令

    3.1 帮助命令

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

    帮助文档地址:docs.docker.com/reference/

    3.2 镜像命令

    • docker images

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

    REPOSITORY          TAG                 IMAGE ID            CREATED      SIZE
    hello-world         latest              feb5d9fea6a5        4 weeks ago  13.3kB
    # 解释
    REPOSITORY	镜像的仓库源
    TAG			镜像的标签
    IMAGE ID	镜像的 id
    CREATED		镜像的创建时间
    SIZE		镜像的大小
    
    # 命令可选项
      -a, --all           	列出所有镜像
          --digests         Show digests
      -f, --filter filter   Filter output based on conditions provided
          --format string   Pretty-print images using a Go template
          --no-trunc        Don't truncate output
      -q, --quiet           只显示镜像 id
    
    • docker search

      搜索镜像

    docker search mysql
    
    NAME                   DESCRIPTION                                     STARS       OFFICIAL     AUTOMATED
    mysql                  MySQL is a widely used, open-source relation…   11587               [OK]
    mariadb                MariaDB Server is a high performing open sou…   4407                [OK]
    mysql/mysql-server     Optimized MySQL Server Docker images. Create…   857                 [OK]
    
    # 可选项 ,过滤
    	--filter=STARS=3000		搜索出来的镜像就是 STARS 大于 3000 的
    	
    
    • docker pull

      下载镜像

    docker pull mysql [:tags]  # 下载最新的  [:tags]指定下载
    
    Using default tag: latest # 如果不写 tag,默认就是 latest 最新版
    latest: Pulling from library/mysql
    b380bbd43752: Pull complete	# 分层下载,docker image 的核心,联合文件系统,这回下了这几个层,如果下面指定别的版本进行下载,如果有重复就不会下载
    f23cbf2ecc5d: Pull complete
    30cfc6c29c0a: Pull complete
    b38609286cbe: Pull complete
    8211d9e66cd6: Pull complete
    2313f9eeca4a: Pull complete
    7eb487d00da0: Pull complete
    4d7421c8152e: Pull complete
    77f3d8811a28: Pull complete
    cce755338cba: Pull complete
    69b753046b9f: Pull complete
    b2e64b0ab53c: Pull complete
    Digest: sha256:6d7d4524463fe6e2b893ffc2b89543c81dec7ef82fb2020a1b27606666464d87  # 签名
    Status: Downloaded newer image for mysql:latest
    
    • docker rmi

      删除镜像,可以通过镜像 id 删除或者镜像名

    docker rmi -f IMAGE ID # 删除指定的容器,也可以通过空格间隔删除多个
    docker rmi -f $(docker images -aq) # 删除全部的容器
    

    3.3 容器命令

    注意:我们有了镜像才可以创建容器

    测试使用,下载一个 CentOS 镜像

    docker pull docker  # 最新版的
    

    新建容器并启动

    docker run [可选参数] image
    
    # 参数说明
    --name="Name"   容器启动后的名字,用来区分容器
    -d				后台方式运行
    -it				使用交互方式运行,进入容器查看内容
    -p				指定容器的端口  -p 8080
    	-p	# ip:主机端口:容器端口
    	-p	# 主机端口:映射到容器端口(常用)
    	-p	# 容器端口
    -P				随机指定端口
    
    # 使用容器
    # 启动并进入容器
    docker run -it centos /bin/bash
    
    # 从容器中退回到主机
    exit	容器停止并退出
    Ctrl + P + Q   容器不停止退出
    
    # 列出所有运行中的容器
    docker ps  列出正在运行的容器
    docker ps -a  列出当前正在运行的容器 + 历史运行过的容器
    
    -n=?	显示最近创建的容器
    -q		只显示容器的编号
    

    删除容器

    docker rm 容器id		# 删除指定id 的容器
    docker rm -f $(docker ps -aq)		# 删除所有的容器
    

    启动和停止容器

    docker start 容器id
    docker restart 容	器id
    docker stop 容器id
    docker kill 容器id
    

    3.4 其他常用命令

    问题:当我们使用后台启动容器 centos 的时候docker run -d 镜像名,使用 docker ps 发现 centos 停止了。这里是常见的一个问题,容器使用后台运行,就必须要有一个前台进程,docker 发现没有应用就会自动停止;假设 nginx 容器启动后,发现自己没有提供服务,就会立刻停止,就没有程序了。

    • docker logs

      查看日志命令

    docker logs -f -t --tail 5 容器    查看某一个容器的日志信息
    

    • docker top

      查看容器中的进程信息

    docker top 容器id
    
    • docker inspect

      查看镜像的元数据

    docker inspect
    

    • docker exec -it 容器id bashShell

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

      进入当前正在运行的容器

      我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置

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

    • docker cp

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

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

    3.5 总结

    attach		# 当前 shell 下 attache 连接指定运行镜像
    build		# 通过 Dockerfile 定制镜像
    commit		# 提交当前容器为新的镜像
    cp			# 从容器中拷贝指定文件或者目录到宿主机上
    create		# 创建一个新的容器,同run,但不启动容器
    diff		#查看docker 容器变化
    events		# 从 docker 服务获取容器实时时间
    exec		# 在已存在的容器上运行命令
    export		# 导出容器的内容流作为一个 tar 归档文件[对应 import]
    history		# 展示一个镜像形成历史
    images		# 列出系统当前镜像
    import		# 从tar 包中的内容创建一个新的文件系统镜像[对应export]
    info		# 显示系统相关信息
    inspect		# 查看容器详细信息
    kill		# kill 指定 docker 容器
    load		# 从一个 tar 包中加载一个镜像[对应save]
    login		# 注册或者登录一个docker 源服务器
    logout		# 从当前Docker registry 退出
    logs		# 输出当前容器日志信息
    port		# 查看映射端口对应的容器内部源端口
    pause		# 暂定容器
    ps			# 列出容器列表
    pull		# 从docker 镜像源服务器拉取指定镜像或者库镜像
    push		# 推送指定镜像或者库镜像至docker 源服务器
    restart		# 重启运行的容器
    rm			# 移除一个或者多个容器
    rmi			# 移除一个或者多个镜像[无容器使用该镜像才可删除,否则需要删除相关容器才可以继续 或 -f 强制删除]
    run			# 创建一个新的容器并运行一个命令
    save		# 保存一个镜像为一个tar包[对应 load]
    search		# 在 docker hub 中搜索镜像
    start		# 启动容器
    stop		# 停止容器
    tag			# 给源中镜像打标签
    top			# 查看容器中运行的进程信息
    unpause		# 取消暂停容器
    version		# 查看docker 版本号
    wait		# 截取容器停止时间的退出状态值
    

    4. Docker 安装使用

    4.1 Docker 安装 Nginx

  • 搜索镜像
  • docker search
    

    也可以在 docker.hub 上搜索,可以看到帮助文档

  • 下载镜像
  • docker pull nginx
    

  • 运行测试
  • docker run -d --name nginx01 -p 3344:80 nginx
    
    -d		# 后台运行
    -name	# 容器名
    -p		# 宿主机端口:容器内部端口
    

    • 端口暴露的概念

    4.2 Docker 安装 Tomcat

  • 搜索镜像
  • docker search tomcat
    
  • 下载镜像
  • docker pull tomcat
    
  • 运行测试
  • docker run -d --name tomcat01 -p 8080:8080 tomcat
    
  • 外网访问测试

    通过外网我们访问可以看到,结果是 404,因为 docker 下载下来的这个 tomcat 不是一个完整版的

  • 我们使用命令进入容器查看

    docker exec -it tomcat01 /bin/bash
    
    whereis tomcat
    

    进入到 tomcat 的目录下,我们看到 webapps 目录下是空的,因为部署的项目是在这个目录下的,而看到这个文件夹是空的,所以表示并没有进行任何的项目部署,所以会出现 404 页面的情况,这个原因是阿里云镜像的原因,在下载的时候默认是找的最小的镜像,所以它会把不必要的都剔除掉,保证最小可运行的环境。我们在 webapps 的同级目录下可以 看到一个 webapps.dist 目录,将这个目录的内容全部复制到 webapps 里面,然后重新访问就可以看到 tomcat 的首页内容了。

    5. 可视化面板 portainer

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

    开启命令

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

    下载完成之后我们可以通过浏览器访问 ip地址:8088 端口号

    6. 镜像

    镜像是什么:镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件。

    所有的应用直接打包成 docker 镜像就可以直接运行。

    获得镜像的方式:1. 从远程下载 2. 别人拷贝 3. 自己制作一个镜像DockerFile

    6.1 UnionFS(联合文件系统)

    在我们下载镜像的时候可以看到一层层的下载

    UnionFS:Union 文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,Union 文件系统是 Dcoker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

    特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

    6.2 Docker 镜像加载原理

    docker 的镜像实际上由一层一层的文件系统组成,这种层级的文件系统 UnionFS。

    bootfs(boot file system) 主要包含 bootloader 和 kernel,bootloader 主要是引导加载 kernel,Linux 刚启动时会加载 bootfs 文件系统,在 Docker 镜像的最底层是 bootfs。这一层与我们典型的 Linux/Unix 系统是一样的,包含 boot 加载器和内核。当 boot 加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs 转交给内核,此时系统也会卸载 bootfs。

    rootfs(root file system),在 bootfs 之上。包含的就是典型 Linux 系统中的 /dev,/proc,/bin,/etc 等标准目录和文件。rootfs 就是各种不同的操作系统发行版,比如 Ubuntu,Centos 等

    平时我们安装的虚拟机 CentOS 都是好几个 G,为什么 Docker 只有几百M?

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

    6.3 镜像分层

    在我们下载一个镜像的时候,终端输出的日志中可以明显的看到是一层一层的进行下载。

    为什么 Docker 镜像要采用这种分层的结构呢?

    最大的好处,就是可以实现资源的共享,比如有多个镜像都从相同的 Base 镜像构建过来,那么宿主机只需要在磁盘上保留一份 base 镜像,同时内存中也只需要加载一份 base 镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

    查看镜像分层的方式可以通过命令:docker image inspect 镜像

    所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。

    假设基于 Unbuntu Linux 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python 包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。

    下图中镜像包含 3 个镜像层

    在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,下图中,每个镜像包含 3 个文件,而镜像包含了来自两个镜像层的 6 个文件

    下图中是一个稍微复杂的三层镜像,在外部看来整个镜像只有 6 个文件,因为最上层的文件 7 是文件 5 的更新版本。

    这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件,这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。

    Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。

    Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。每种存储引擎都是基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。

    Docker 在 Windows 上仅支持 windowsfilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和 CoW。

    下图中是系统显示相同的三层镜像,所有镜像层堆叠并合并,对外提供统一的视图。

    特点

    Docker 镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层就是我们通常说的容器层,容器层之下的都叫镜像层。

    6.4 Commit 镜像

    docker commit 提交容器成为一个新的副本
    
    docker commit -m="信息描述" -a="作者" 容器id 目标镜像名:[TAG]
    

    在我们平常是使用中,下载一个镜像使用时需要对其进行一些修改,扩充,如果我们想要保存当前容器的状态,可以通过 commit 来提交,获得一个镜像,就好比 VM 虚拟机的快照功能。

  • 在上面启动 tomcat 后 webapps 里面是没有东西的,所以访问 404
  • 自己拷贝内容进 webapps
  • 下面的命令进行提交为一个镜像,以后使用就可以通过我们修改过的镜像
  • docker commit -m="add webapps" -a="lss" xxxxxx tomcat001:1.0
    

    7. 容器数据卷

    7.1 什么是容器数据卷

    总的来说:容器的持久化和同步操作;容器间也是可以容器共享的

    docker 的理念就是将应用和环境打包成一个镜像,如果数据存储在容器中,那当我们的容器被删除了,数据也会丢失。我们需要对数据进行持久化,加入 MySQL 的容器中存储了数据,容器突然被误删除了,那数据就会丢失了,所以我们需要将数据存储在本地。

    容器之间可以有多个数据共享的技术,Docker 容器中产生的数据同步到本地,这就是卷技术,目录的挂载,将我们容器内的目录挂载到 Linux 上。

    7.2 通过命令挂载

    docker run -it -v 主机目录:容器内目录
    
    # 测试
    docker run -it -v /home/test:/home centos /bin/bash
    

    执行命令之后,无论是在镜像里面修改指定的目录还是在宿主机上修改指定的目录,另一方都能收到相应的变化信息,这种情况就是挂载成功了。

    启动之后我们可以通过 docker inspect 容器id 来查看

    Docker 知识点总结-1

    这里当我们停止运行容器之后,修改宿主机共享的文件的内容的,再次启动容器会发现数据也进行了相应的更新。双向的过程。

    使用容器卷好处:绑定之后,我们修改本地的文件,在容器中也会进行同步修改。

    7.3 安装 MySQL

  • 搜索镜像
  • docker search mysql
    
  • 拉取镜像
  • docker pull mysql:5.7
    
  • 启动容器

    这里应该注意,进入 mysql 需要有一个密码的配置

    详细信息官网地址:registry.hub.docker.com/_/mysql

  • -d		# 后台运行
    -p		# 端口映射   宿主机端口:容器端口
    -v		# 卷挂载
    -e		# 环境变量
    --name	# 容器名字
    
    docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name mysql01 mysql:5.7
    
  • 查看宿主机挂载的目录
  • 使用 SQL_yog 连接MySQL

    创建一个 test 数据库

  • 查看 /home/mysql/data 目录下的内容
  • 假设将容器删除,我们发现挂载在本地的数据卷依旧没有丢失,这就实现了容器的持久化功能
  • 7.4 具名挂载和匿名挂载

    7.4.1 匿名挂载
    -v 容器内路径
    docker run -d -p 80:80 -v /etc/nginx nginx
    
    查看所有的 volume 情况
    docker volume ls
    这里发现,这种就是匿名挂载,我们在 -v 只写了容器内的路径 ,没有写容器外的路径
    

    7.4.2 具名挂载
    -v 卷名:容器内路径
    
    docker run -d -p 80:80 -v nginx01:/var/nginx nginx
    

    7.4.3 卷挂载路径查看

    所有的 docker 容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data ,我们通过具名挂载可以方便的找到我们的一个卷,大多数情况使用 具名挂载

    7.4.4 确定挂载方式

    如何确定是具名挂载、匿名挂载、还是指定路径挂载?

    -v 容器内路径			# 匿名挂载
    -v 卷名:容器内路径		   # 具名挂载
    -v /宿主机路径:容器内路径		# 指定路径挂载
    
    • 读写权限
    docker run -d -p 80:80 -v nginx01:/var/nginx:ro nginx
    docker run -d -p 80:80 -v nginx01:/var/nginx:rw nginx
    
    #通过 -v 容器内路径:ro  rw  改变读写操作
    ro		readonly #只读		说明这个路径只能通过宿主机来操作,容器内部是无法操作的
    rw		readwrite	#可读可写
    #设置了这两个容器的权限,容器对我们挂载出来的内容就有限定了。
    

    7.5 简单使用 DockerFile

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

    在 /home/docker-test-volume 目录下创建一个 dockerfile01 脚本文件,这个脚本可以生成镜像,里面的每一个命令都是一层

    # 文件中的内容  这里面的每一个命令就是镜像的一层
    FROM centos
    VOLUME ["volume01","volume02"]
    CMD echo "---end---"
    CMD /bin/bash
    

    使用命令构建镜像

    在 dockerfile01文件同级目录下

    docker build -f dockerfile1 -t lss/centos .
    

    使用命令 docker images 查看我们刚才构建的镜像

    启动一下自己写的容器

    docker run -it a542aa955836 /bin/bash
    

    在容器中的 volume01 下创建一个 container.txt 文件

    这个卷和外部一定有一个同步的目录,这里的是匿名挂载

    使用命令 docker inspect 5c26b2ee40af 查看详细的信息

    7.6 数据卷容器

    多个容器实现数据的同步

    测试

  • 启动 centos 镜像
  • docker run -it --name centos01 lss/centos
    

  • 在启动一个 lss/centos 镜像

    通过 --volumes-from 挂载到上一个启动的容器上实现数据的同步

  • --volumes-from  # 相当于一个继承的关系
    docker run -it --name centos02 --volumes-from centos01 lss/centos
    

  • 在 centos01 的 volume01 文件夹下创建一个 test.java 文件

    进入 centos02 后在 volume02 文件夹下也可以看到这个文件,实现了容器之间的数据同步。

    因为这个镜像是自己创建的,在上面的 DockerFile 里面进行了设置,只设置了 volume01 和 volume02 文件夹是共享的卷,所以在别的文件夹中的内容是不能实现共享的。

  • 加入一个 centos03 也挂载到 centos01上,然后删除掉 centos01 之后,这些共享的文件在 centos02 和 centos03 上并不会丢失的,这个文件都是双向拷贝存在的。

    结论

    容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止,但是一旦将数据同步到本地,本地的数据是不会删除的。

    8. DockerFile

    Dockerfile 就是用来构建 docker 镜像的文件,通过它来生成一个镜像文件发布出去,可以理解为一个命令参数脚本。

    8.1 DockerFile 介绍

    查看官网:registry.hub.docker.com/

    这个文件里面就是一些构建的命令

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

    8.2 DockerFile 构建和指令

    构建时需要很多的指令

    8.2.1 基础
    • 每个关键字(指令)都是必须是大写字母
    • 执行从上到下顺序执行
    • ( # ) 表示注释
    • 每一个指令都会创建提交一个新的镜像层,并提交
  • 编写一个 dockerfile 文件
  • docker build 构建成为一个镜像
  • docker run 运行镜像
  • docker push 发布镜像(DockerHub、阿里云镜像仓库)
  • DockerFile 是面向开发的,以后要想发布项目,做镜像,就要编写 DockerFile 文件。

    步骤:开发、部署、运维

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

    DockerImages:通过 DockerFile 构建生成的镜像,最终发布和运行

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

    8.2.2 DockerFile 指令

    FROM		# 基础镜像,一切从这里开始
    MAINTAINER	# 镜像是谁写的  姓名 + 邮箱
    RUN			# 镜像构建的时候需要运行的命令
    ADD			# 步骤:tomcat 镜像,这个tomcat 压缩包,添加内容
    WORKDIR		# 镜像的工作目录
    VOLUME		# 挂载的目录
    EXPOSE		# 保留端口配置
    CMD			# 指定这个容器启动的时候需要运行的命令,只有最后一个会生效,可被替代
    ENTRYPOINT	# 指定这个容器启动的时候要运行的命令,可以追加命令
    ONBUILD		# 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的指令,触发指令
    COPY		# 类似 ADD ,将我们文件拷贝到镜像中
    ENV			# 构建的时候设置环境变量
    

    8.3 DockerFile 构建镜像

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

  • 编写 Dockerfile 的文件
  • FROM centos
    MAINTAINER lss
    
    ENV MYPATH /usr/local
    WORKDIR $MYPATH
    
    RUN yum -y install vim
    RUN yum -y install net-tools
    
    EXPOSE 80
    
    CMD echo $MYPATH
    CMD echo "---end---"
    CMD /bin/bash
    

  • 通过这个文件构建镜像
  • docker build -f 文件名 -t 镜像名:[tag] .
    
    docker build -f mydockerfile-centos -t centos:1.0 .   # 注意后面这个 . 不能少
    

  • 测试运行
  • docker run -it mycentos:1.0  # 进入我们自己创构建的镜像
    

    这里我们在 DockerFile 文件中有安装 net-tools 和 vim 的命令,所以在镜像中可以只用;官网的下载的原生的是不能使用的。

    8.4 CMD 和 ENTRYPOINT 区别

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

    测试 CMD

  • 创建一个文件 dockerfile-cmd-test
  • FROM centos
    CMD ["ls","-a"]
    
  • 构建镜像docker build -f dockerfile-cmd-test -t cmdtest .
  • 运行镜像 docker run 037860b45b64,在 run 的时候 ls -a 命令生效
  • 想要在这个镜像上追加一个命令 docker run 037860b45b64 -l 会出错
  • 因为 cmd 的情况下,-l 替换了 CMD ["ls","-a"] 命令,-l 不是命令所以报错

    这里可以使用 docker run 037860b45b64 ls -l 查看

    测试 ENTRYPOINT

  • 创建一个 dockerfile-entrypoint-test 文件
  • FROM centos
    # 与 CMD 区别之处
    ENTRYPOINT ["ls","-a"]
    
  • 构建镜像 docker build -f dockerfile-entrypoint-test -t entrytest .
  • 运行测试 docker run 368a821b1dcb
  • 在执行的时候追加一个参数 docker run 368a821b1dcb -l

    这里还是可以正常执行的,这里是直接拼接在 ENTRYPOINT 后面的

  • 8.5 构建一个 tomcat 镜像

  • 准备镜像文件 tomcat 压缩包,jdk 压缩包
  • 编写 dockerfile 文件,使用官网命名 Dockerfile,这样 build 的时候就会自动寻找这个文件,不需要使用 -f 指定了
  •  FROM centos
     MAINTAINER lss
     
     COPY README.txt /readme.txt
     ADD jdk-8u311-linux-x64.tar.gz /usr/local/
     ADD apache-tomcat-9.0.54.tar.gz /usr/local/
     
     RUN yum -y install vim
     
     ENV MYPATH /usr/local
     WORKDIR $MYPATH
     
     ENV JAVA_HOME /usr/local/jdk1.8.0_11
     ENV CLASSPATH $JAVA_HOME/bin/dt.jar:$JAVA_HOME/lib/tools.jar
     ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.54
     ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.54
     ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
     
     EXPOSE 8080
     
     CMD /usr/local/apache-tomcat-9.0.54/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.54/bin/logs/catalina.out
    
  • 构建
  • docker build -t dirtomcat .		# 由于文件名是 Dockerfile ,所以不需要用 -f 参数去找文件
    
  • 查看构建的镜像文件
  • docker images
    

  • 启动镜像测试
  • docker run -d -p 8080:8080 --name lss-tomcat -v /opt/build/tomcat/webapps:/usr/local/apache-tomcat-9.0.54/webapps/test -v /opt/build/tomcat/tomcat-logs/:/usr/local/apache-tomcat-9.0.54/logs diytomcat
    

  • 本地编写一个项目进行发布

    上面启动镜像的时候就已经做了卷的挂载,所以我们直接在本地编写项目就可以实现同步发布了

    /opt/build/tomcat/webapps/ 文件夹(上面 -v 挂载的)下创建一个 WEB-INF 文件夹,在这个文件夹下创建一个 web.xml 文件

  • 
    
    
    

    在 tomcat 目录下创建一个 index.jsp 文件

    
    
    
    Hello Tomcat Docker!
    
    
    
    

    至此已经实现了项目的发布

  • 测试
  • 查看日志文件输出信息

    9. 发布镜像

    9.1 发布到 DockerHub

  • 到 docker.hub 中注册一个账号登录进去

  • 在服务器上提交镜像

    登录

  • docker login -u lishisen -p ******
    

  • 登录完毕之后就可以提交镜像了
  • # 由于之间创建的镜像没有带版本号,所以提交的时候被拒绝了
    # 增加一个 tag
    docker tag 容器id lishisen/tomcat:1.0
    # 然后提交就成功了
    docker push lishisen/tomcat:1.0
    

    可以看到,提交的时候也是按照镜像的层级来进行提交的。

    9.2 发布到阿里云

  • 登录阿里云
  • 找到容器镜像服务
  • 创建一个命名空间

    这个命名空间可能就是一个很大的项目

  • 创建镜像仓库
  • Docker 知识点总结-1

    • 操作指南里面有详细的操作步骤

    根据操作指南操作

  • 登录
  • docker login --username=李时森111 registry.cn-beijing.aliyuncs.com
    

  • 为镜像生成一个版本号
  • docker tag [ImageId] registry.cn-beijing.aliyuncs.com/lishisen/lishisen-repo:[镜像版本号]
    

  • push 上传
  •  docker push registry.cn-beijing.aliyuncs.com/lishisen/lishisen-repo:[镜像版本号]
    

    10. Docker 网络

    10.1 Docker0

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

    有一个 tomcat 容器,一个 mysql 容器,那这两个容器之间是怎样通信的,是使用那个网络进行通信的?

    查看能够 ping 同容器内的 ip 地址

  • 运行一个容器
  • docker run -d -P --name tomcat01 tomcat
    
  • 查看容器内部 ip 地址

    在运行容器的时候加上 ip addr 命令

  • docker exec -it tomcat01 ip addr
    # 注意这里下载的镜像如果这个命令不能用可能是镜像中没有这一个功能,可以上面安装过 net-tools 的 Dcokerfile 文件来自己重新构建一个镜像文件
    

    启动后我们可以看到容器内部网络地址 ,容器启动的时候会得到一个 eth0@if33 的ip 地址,这是 docker 分配的。

    我们使用 ping 命令是可以 ping 通这个 ip 地址的

    原理

    当我们每启动一个 docker 容器的时候,docker 就会给 docker 容器分配一个 ip 地址;在宿主机上,只要我们安装了 docker ,就会有一个 docker0 的网卡,是使用的桥接模式,使用 veth-pair 技术。

    当我们上面的容器启动之后,在宿主机上使用 ip addr 查看,可以看到有刚才启动的容器的 ip 的相关信息。

    我们每启动一个容器就会多一个网卡,这个启动的容器带来的网卡都是一对一对出现,这就是 veth-pair 技术:就是一对虚拟设备接口,它们都是成对出现的,彼此相连的。

    也就是因为有了这个特性,veth-pair 充当作为一个桥梁,连接这各种的虚拟网络设备,实现宿主机和容器之间的互联。

    加入我们开启了两个容器 tomcat01、tomcat02 ,这两个容器之间也是可以通过ping 命令测试连通的,所以说容器之间也是可以相互通信的。

    两个容器之间的通信并不是直接通信的,当安装 Docker 后会有一个 docker0 的网卡,这个就相当于是一个路由器,当 tomcat01 与 tomcat02 建立连接时,以 veth-pair 技术实现两个网卡之间的互联,然后路由器通过广播的方式或注册IP地址的方式进行发送连接。

    tomcat01 和 tomcat02 是共用一个路由器 docker0。

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

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

    Docker 中的所有网络接口都是虚拟的,因为 虚拟的接口转发效率高。

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

    10.2 link

    场景:有一个微服务,database url = ip:,每一次用 docker 启动 MySQL 都会分配一个新的 ip ,如果 ip 变化了项目中的地址就会失效了,我们在项目不重启的情况下,数据库的 ip 地址换掉了,希望可以通过名字来访问这个容器,以此来解决这个问题。Docker 中使用 --link 来解决这个问题

  • 启动两个 tomcat:tomcat01、tomcat02
  • 分别查看两个 tomcat 的网卡 ip 地址

    ping 相互的 ip 地址是可以通的

    但是 ping 容器的名字是不能 ping 通的

  • 使用 --link 进行连接

    再启动一个 tomcat03 容器,使用 --link 连接

  • docker run -d -p 8083:8080 --name tomcat03 --link tomcat01 tomcat
    

    测试是否能通过容器名 ping 通

    启动 tomcat03 可以 ping 通 tomcat01 通过容器名

    注意: 相反 tomcat01 ping tomcat03 就会失败,正向连接可以,反向连接可能不可以

  • 查看网卡的详细信息
  • docker network ls
    
    docker inspect 上一条命令出来的id
    

    可以看到为每一个启动的容器分配一个 ip

  • 反向 ping 不同的原因
  • tomcat03 在本地配置了 tomcat02 的配置

    通过查看 tomcat03 容器的 hosts 文件可以看到

    docker exec -it tomcat03 vim /etc/hosts
    # 可以看到 tomcat03 的 hosts 中有 ip 地址和容器名的映射关系
    

    但是相反的是,在 tomcat01 的 hosts 文件中不能看到映射关系,所以 tomcat01 不能通过容器名 ping 通 tomcat03

    --link 的操作其实就是在 hosts 配置配置了一个 ip 地址和 容器名 的映射关系,这种方式已经不再使用了。

    docker0 问题:不支持容器名进行连接访问

    10.3 自定义网络

    通过命令 docker network ls 查看所有的 docker 网络

    网络模式:

    • bridge:桥接模式(默认)
    • none:不配置网络
    • host:主机模式,和服务器共享网络
    • container:容器内网络连通(局限性大)

    构建自定义网络

    # 直接启动的命令,默认是有一个 --net bridge,这个就是 docker0
    docker run -d -P --name tomcat01 [--net bridge] tomcat
    
    # docker0 特点:默认的,域名不能访问,使用 --link 可以实现互联
    
  • 自定义一个网络
  • # --driver bridge	网络模式,桥接,默认也是 bridge
    # --subnet 192.168.0.0/16	子网,可以包含 255*255 个子网
    # --gateway 192.168.0.1		网关
    # mynet		自定义网络的名字
    
    docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
    

    自己的网络就创建好了

  • 启动 tomcat 容器通过我们自己定义的网络
  • docker run -d -p 8081:8080 --name tomcat01 --net mynet tomcat
    docker run -d -p 8082:8080 --name tomcat02 --net mynet tomcat
    
    ## 使用 docker inspect mynet 查看详细信息
    

  • 测试是否能 ping 通

    经过测试,通过 ip 地址和通过 容器名 都可以 ping 通

    现在不适用 --link 也可以 ping 通了

  • 我们自定义的网络 docker 都已经帮我们维护好了对应的关系,推荐使用自定义的网络

    好处:

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

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

    10.4 网络连通

    在上面创建了一个自定义的网络,网段是 192.168.0.0,docker0 自带的网段上 172.18.0.0

    两个网段的是不能连通的

    在 docker0 上有两个 tomcat 容器,mynet 上有两个 tomcat 容器,这两个网段的容器也是不能 ping 通的,所以需要 docker0 上的容器连接到 mynet 上,实现两个不同网段的容器互联。

    测试

    tomcat01 容器连通 mynet 网络

    docker network connect mynet tomcat01
    
    docker inspect mynet	# 查看详细信息
    # 下图我们可以发现,连通之后直接把 tomcat01 放到了 mynet 下
    # 官网:一个容器两个ip地址 
    

    docker exec -it tomcat01 ping tomcat-net-01
    

    如果要跨网络操作别人,就需要使用 docker network connect 连通

    11. 部署 Redis 集群

  • 创建一个 redis 的网卡
  • docker network create redis --subnet 172.38.0.0/16
    

  • 通过脚本创建 6 个redis 配置
  • for port in $(seq 1 6);
    do
    mkdir -p /mydata/redis/node-${port}/conf
    touch /mydata/redis/node-${port}/conf/redis.conf
    cat >/mydata/redis/node-${port}/conf/redis.conf
    port 6379
    bind 0.0.0.0
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    cluster-announce-ip 172.38.0.1${port}
    cluster-announce-port 6379
    cluster-announce-bus-port 16379
    appendonly yes
    EOF
    done
    

  • 启动 6 个 redis 容器
  • for port in $(seq 1 6);
    do
    docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} -v /mydata/redis/node-${port}/data:/data -v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    done
    

  • 创建集群
  • docker exec -it redis-1 /bin/sh		# 进到 redis-1 节点里面
    
    # 执行命令创建集群
    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
    

  • 测试集群是否搭建成功
  • set a b 在集群中 set 一个值,显示的主机的 172.38.0.13 这个主机,然后使用命令 docker stop redis-3 停掉这个容器之后,在进入集群到 172.38.0.14 这个节点上,14 是 13 的从机,主机挂掉从机补上

    docker 搭建 redis 集群完成。

    12. Spring Boot 微服务打包 Docker 镜像

  • 创建 Spring Boot 项目

    Controller 请求返回 Hello,Docker

  • 打包应用

    把这个项目 package 打包成一个 jar 包,将这个 jar 包上传到 Linux 虚拟机上

  • 编写 Dockerfile
  • FROM java:8
    
    COPY *.jar /app.jar
    
    CMD ["--server.port=8080"]
    
    EXPOSE 8080
    
    ENTRYPOINT ["java","-jar","/app.jar"]
    
  • 构建镜像
  • docker build -t demo .
    

  • 发布运行
  • 13. Docker Compose

    13.1 介绍

    官网:docs.docker.com/compose/

    在上面的操作中,我们想要构建使用一个镜像的话需要进行:Dockerfile -- build -- run 手动操作,单个的容器。

    如果说一个大的微服务项目中有成百个服务,并且的这些服务之间有着依赖关系,上面这种操作实现就会非常的繁琐。Docker Compose 就是用来进行轻松高校的管理容器,可以定义和运行多个容器。

    Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. To learn more about all the features of Compose, see the list of features.

    Compose works in all environments: production, staging, development, testing, as well as CI workflows. You can learn more about each case in Common Use Cases.

    Using Compose is basically a three-step process:

  • Define your app’s environment with a Dockerfile so it can be reproduced anywhere.

    • 创建 Dockerfile 保证项目在任何地方可以运行
  • Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.

    • 通过 docker-compose.yml 配置文件来定义服务
    • 服务:容器、应用(web、mysql、redis ......)
  • Run docker compose up and the Docker compose command starts and runs your entire app. You can alternatively run docker-compose up using the docker-compose binary.

    • 启动项目
  • 作用:批量容器编排

    Compose 是 Docker 官方开源的项目,使用前需要进行安装。

    Dokcerfile 可以让程序在任何地方运行,简化了运维的部署,假设有一个 web 服务,这个服务需要 多个容器:redis、mysql、nginx...... 如果我们一个一个去 build 非常的麻烦。

    可以写一个 Compose 批量把这些服务打包进来

    version: "3.9"  # optional since v1.27.0
    services:
      web:
        build: .
        ports:
          - "5000:5000"
        volumes:
          - .:/code
          - logvolume01:/var/log
        links:
          - redis
      redis:
        image: redis
    volumes:
      logvolume01: {}
      
    # 在这个文件里面编排的容器,通过 docker-compose up 就可以一键启动
    # 这些所有的服务运行起来就是一个完整的项目(一组关联的容器)
    

    13.2 安装 Compose

    官网地址:docs.docker.com/compose/ins…

  • 下载
  • # 官网的下载地址,非常的慢
    sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    
    # 国内的镜像
    curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m`  > /usr/local/bin/docker-compose
    

  • 给文件授权
  • sudo chmod +x /usr/local/bin/docker-compose
    
  • 确认安装成功
  • docker-compose version
    

    13.3 使用

    官网:docs.docker.com/compose/get…

    官网案例:python应用,计数器,使用 redis 进行计数

  • 创建一个应用

    就是创建一个目录

  • mkdir composetest
    cd composetest
    
  • 创建 app.py 文件
  • import time
    
    import redis
    from flask import Flask
    
    app = Flask(__name__)
    cache = redis.Redis(host='redis', port=6379)
    
    def get_hit_count():
        retries = 5
        while True:
            try:
                return cache.incr('hits')
            except redis.exceptions.ConnectionError as exc:
                if retries == 0:
                    raise exc
                retries -= 1
                time.sleep(0.5)
    
    @app.route('/')
    def hello():
        count = get_hit_count()
        return 'Hello World! I have been seen {} times.n'.format(count)
    
    • 创建一个需要的依赖包 requirements.txt
    flask
    redis
    
  • 创建 Dockerfile 文件
  • # syntax=docker/dockerfile:1
    FROM python:3.7-alpine
    WORKDIR /code
    ENV FLASK_APP=app.py
    ENV FLASK_RUN_HOST=0.0.0.0
    RUN apk add --no-cache gcc musl-dev linux-headers
    COPY requirements.txt requirements.txt
    RUN pip install -r requirements.txt
    EXPOSE 5000
    COPY . .
    CMD ["flask", "run"]
    
    #######################################################
    # 上面的官网给出的例子,可能是版本的问题,执行失败,可以使用下面的内容
    FROM python:3.6-alpine
    ADD . /code
    WORKDIR /code
    RUN pip install -r requirements.txt
    CMD ["python","app.py"]
    # 从 python3.6 镜像开始构建镜像
    # 将当前目录添加到 . / code 镜像中的路径
    # 将工作目录设置为 /code
    # 安装 python 的依项
    # 将容器的默认命令设置为 python  app.py
    
  • 创建一个 docker-compose.yml 文件
  • version: "3.9"
    services:
      web:
        build: .
        ports:
          - "5000:5000"
      redis:
        image: "redis:alpine"
        
    #######################################################
    # 上面的官网给出的例子,可能是版本的问题,执行失败,可以使用下面的内容
    version: "3.8"
    services:
      web:
        build: .
        ports:
          - "5000:5000"
        volumes:
          - .:/code
      redis:
        image: "redis:alpine"
    # 从 Compose 文件定义了两个服务  web 和 redis
    # 使用 Dockerfile 当前目录中构建的镜像
    # 将容器上的公开端口  5000 转发到主机上的端口 5000.
    # redis 服务使用从 Docker Hub 注册表中提取的公共 redis 镜像
    

  • 运行测试

    在有 docker-compose.yml 的文件夹下执行下面的命令

  • docker-compose up
    

    启动成功,包括两个服务,web 和 redis

    流程:

  • 创建网络
  • 执行 Docker-compose.yml
  • 启动服务,启动服务后可以看到创建了两个服务
  • 在上面我们创建的文件名是 composetest,根据 docker-compose.yml 配置文件中的信息创建了两个服务

    Docker 知识点总结-2

    Docker 知识点总结-1

    这些启动的服务的名字都是自动生成的,是一些默认规则。

    启动之后是有两个服务的,可以使用 curl 访问得到返回值

    docker-compose 中的依赖全部帮我们下载了

    docker service ls
    # 这个命令是查看集群中的服务,因为上面的例子不是集群的,所以会报错
    

    默认的服务名: 文件名 _ 服务名 _ num

    假如有多个服务器,集群,我们的一个服务可能会在 A 服务器上运行,也可能在 B 服务器上运行

    _num 表示的是一个副本数量。

    假如我们需要运行 redis 服务,有 4 个副本

  • 网络的规则
  • 项目中的内容都在同一个网络下,所以可以通过域名进行访问。

    使用命令:docker network inspect composetest_default 可以查看网络信息的详情

  • 停止服务
  • 快捷键:Ctrl + C

    进入到 composetest 目录下执行命令:docker-compose down

    13.4 Compose 编写配置规则 yaml

    官网地址:docs.docker.com/compose/com…

    Compose 的核心就是 docker-compose.yaml 配置文件

    • docker-compose.yaml 配置文件有 3 层
    version: ''   # 版本 与 docker 引擎对应
    services: # 服务
    	服务1: web
    		# 服务配置
    		image
    		build
    		network
    		......
    	服务2: redis
    		......
    	......
    # 其他配置 网络/卷、全局配置
    volumes:
    network:
    configs:
    ......
    
  • version

    版本信息根据官网给出的信息

  • services
  • 注意依赖这个配置信息

    因为镜像的启动是有顺序的,假如上面的 web 需要先启动 redis

    13.5 使用 Compose 一键部署 WP bok

    官网案例:docs.docker.com/samples/wor…

  • 创建项目目录
  • 编写 docker-compose.yml 配置文件
  • version: "3.9"
        
    services:
      db:
        image: mysql:5.7
        volumes:
          - db_data:/var/lib/mysql
        restart: always
        environment:
          MYSQL_ROOT_PASSWORD: somewordpress
          MYSQL_DATABASE: wordpress
          MYSQL_USER: wordpress
          MYSQL_PASSWORD: wordpress
        
      wordpress:
        depends_on:
          - db
        image: wordpress:latest
        volumes:
          - wordpress_data:/var/www/html
        ports:
          - "8000:80"
        restart: always
        environment:
          WORDPRESS_DB_HOST: db:3306
          WORDPRESS_DB_USER: wordpress
          WORDPRESS_DB_PASSWORD: wordpress
          WORDPRESS_DB_NAME: wordpress
    volumes:
      db_data: {}
      wordpress_data: {}
    
  • 启动
  • docker-compose up -d
    
  • 查看
  • 13.6 实战--构建自己的微服务

  • 编写项目微服务
  • Dockerfile 构建镜像
  • FROM java:8
    
    COPY *.jar /app.jar
    
    CMD ["--server.port=8080--"]
    
    EXPOSE 8080
    
    ENTRYPOINT ["java","-jar","/app.jar"]
    
  • docker-compose.yaml编排项目
  • version: 3.9
    
    services:
      lssapp:
        build: .
        image: lssapp
        depends_on:
          - redis
        ports:
          - "8080:8080"
      redis:
        image: "redis:alpine"
    
  • 项目打包放到 linux 上
  • docker-compose up	# 启动
    

  • 启动测试
  • 如果项目需要重新构建可以使用这个命令 docker-compose up --build

    14. Docker Swarm

    14.1 环境搭建

    在阿里云购买 4 台服务器用于做集群操作,选择按量收费就行

    也可以在本地开 4 个虚拟机模拟集群操作

    在 4 台服务器上安装 docker

    14.2 介绍

    官网地址:docs.docker.com/engine/swar…

    工作模式:

    Docker Engine 1.12 introduces swarm mode that enables you to create a cluster of one or more Docker Engines called a swarm. A swarm consists of one or more nodes: physical or virtual machines running Docker Engine 1.12 or later in swarm mode.

    There are two types of nodes: managers and workers. 两个节点:管理节点、工作节点

    操作都在 管理节点

    14.3 操作

    # 配置一下集群,将 docker01 节点成为一个主节点
    # 初始化节点
    docker swarm init --advertise-addr 192.168.253.155
    
    # 初始完可以得到两个命令i
    # 加入一个节点
    docker swarm join
    # 获取令牌,可以通过令牌让别的节点加入进来
    docker swarm join-token manager
    docker swarm join-token worker
    

    # 在 docker02 节点上执行命令,将节点加入 docker01,加入过去的就是一个 worker
    docker swarm join --token SWMTKN-1-10kwelhmau8q2l45uqp8jep709ns2mlro1csndykeeigvkl0vx-873o4olo10103ctckdl2ppadh 192.168.253.155:2377
    

    # 在 docker01 主节点上执行命令,可以看到集群的节点信息
    docker node ls
    

    将 docker03 加入集群并初始化为 manage;将 docker04 加入集群并初始化为 worker;

    集群搭建完成!!!

    14.4 Raft 协议

    上面的集群中搭建的两个主节点两个从节点,假设一个节点挂了,其他节点是否可用?

    Raft 协议:保证大多数节点存活才可以用。

    加入 docker01 节点宕机了,那么其他节点也都是不能使用了,包括另一个管理节点

    docker01 节点再次启动之后,我们发现 Leader 变成了 docker03 的节点

    # 使用命令离开一个节点
    docker swarm leave
    
    # 结果:Node left the swarm.
    

    将 docker02 节点也加入到管理节点,再次停掉管理节点 docker01 其他管理节点还是可以操作的,剩余两个管理节点

    再次停掉一个管理节点,剩余一个管理节点,这种情况是没有办法使用的

    所以,为保证集群的可用性,有 3 个主节点,保证 > 1 台管理节点存活才能正常使用集群的操作(保证大多数节点存活才可以使用,高可用)

    14.5 Swarm 集群弹性创建服务

    弹性、扩缩容、集群

    之前使用 docker-compose up 启动的一个项目也是单机的。

    集群下面所有的东西都到了 swarm 里面,所有的东西都变成了 docker service。

    容器 变成了 服务

    假设 redis 需要启动三个,对于单体的来说就是启动了三个容器。

    集群状态下,为了保证高可用,web 应用连接 redis,redis 有 3 台分布在不同的机器上,这个机器上不可能通过 ip 地址去访问,因为 ip 因为 docker 的ip地址会变化的,所以需要通过服务名来进行访问,这个集群就屏蔽了低等的节点的差异,只需要通过服务名就可以访问到集群。一个 redis 服务可能是好多个副本开启,假设一个挂掉了,其他的仍然可以使用。

    操作

    # 启动一个 nginx 的服务
    docker service create  -p 8888:80 --name my-nginx nginx
    
    ################################
    docker run  容器启动,不具有扩缩容
    docker service 服务启动,具有扩缩容等
    

    查看服务,只启动一个容器,只有一个副本

    这一个的情况下,如果访问量特别大,一个服务可能扛不住,需要多开几个服务,所以要做到动态的扩容

    动态扩缩容

    # 为 my-nginx 服务创建 3 个副本(扩缩容)
    docker service update --replicas 3 my-nginx
    # 也可以用这个命令进行服务的扩缩容
    docker service scale my-nginx=10
    

    启动的多个副本分配到集群内的各个主机上,这些服务在集群中的任意的节点都可以进行访问。服务可以有多个副本,动态的扩缩容,实现高可用。

    14.6 概念的总结

    swarm:集群的管理和编排,docker 可以初始化一个 swarm 集群,其他节点可以加入。有管理和工作两个角色。

    Node:就是一个 docker 的节点,多个节点就组成了一个网络的集群。有管理和工作两个角色

    Service:就是一个任务,可以在管理节点或者工作节点来运行,是核心,用户可以访问。启动方式 docker service

    Task:容器内的命令的,是一个细节的任务。在创建容器的时候是一层一层的

    命令 --> 管理 --> api --> 调度 --> 工作节点(创建 Task 容器维护创建)

    服务副本与全局服务

    所有的节点都是分配的,管理节点和工作节点都可以跑项目

    项目可以分为全局运行和只能在副本上运行

    可以设置项目只在副本上运行和全局运行

    14.6.1 Docker Stack
    # docker-compose 单机部署项目
    docker-compose up -d wordpress.yml
    # Docker Stack 部署---集群部署项目
    docker stack deploy wordpress.yml
    
    # docker-compose.yml 使用 stack
    version: '3.4'
    services:
      mongo:
        image: mongo
        restart: always
        networks: 
          - mongo_network
        deploy:
          restart_policy:
            condition: on-failure
          replicas: 2
      mongo-express: 
        image: mongo-express
        restart: always
        networks: 
          - mongo_network
        ports:
          - target: 8081
            published: 80
            protocol: tcp
            mode: ingress
        environment:
          ME_CONFIG_MONGODB_SERVER: mongo
          ME_CONFIG_MONGODB_PORT: 27017
        deploy:
          restart_policy:
            condition: on-failure
          replicas: 1
    networks:
      mongo_network:
        external: true
    
    14.6.2 Docker Secret

    进行安全配置,配置密码、证书等......

    14.6.3 Docker Config

    对容器进行统一的一些配置

    学习参考视频:www.bilibili.com/video/BV1og…

    学习参考视频:www.bilibili.com/video/BV1kv…

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论