docker 手册

docker

学习大纲

2022//8/26

  • Docker 概述
  • Docker 安装
  • Docker 命令
    • 镜像命令
    • 容器命令
    • 操作命令
    • ... ...
  • Docker 镜像
  • DockerFile
  • Docker网络原理
  • IDEA整合Docker
  • Docker Compose
  • Docker Swarm (简化版 k8s)
  • CI \ CD Jenkins

1. Docker概述

1.1 出现的场景

一套产品:开发 ——> 上线, 两套环境(开发环境, 生产环境) --> 应用环境, 应用配置

开发->运维

问题: 在开发环境可以正常运行, 但是在其他环境下有可能出现问题, 导致服务不可用

环境配置比较费时费力, 可以通过Docker进行环境配置

发布一个项目: (jar/war + (各种环境配置)) ,项目上线时携带环境配置

传统: 开发jar, 运维上线

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

类比:

开发起点 打包 发布 使用
java apk 应用商店 安装即可用
java jar(带上环境) Docker仓库 下载镜像运行即可用
image-20220826125049901

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

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

Docker --> 隔离! --> 打包装箱, 每个箱子都是相互隔离的

1.2 Docker历史

  • 2010年, 几个搞IT的年轻人, 在美国成立了一家公司 -- dotCloud 做一些pass的云计算服务(Linux 虚拟机有关的容器技术 --- LXC)

参考:云计算

他们将自己的技术(容器化技术)命名就是Docker,这时他们想到了开源,越来越多的人发现了Docker的优点,火了!

  • 2014年4月9日,Docker1.0 发布

在容器化技术出来之前,我们都是使用虚拟机技术,二者比较:

img

虚拟机 容器技术
定义 虚拟机是基于硬件的多个客户操作系统,由虚拟机监视器实现 容器是应用程序级构造,并模拟共享单个内核的多个虚拟环境
性能 分钟 对于使用虚拟机的传统虚拟化,每个虚拟机都有自己的完整操作系统,因此在运行内置于虚拟机的应用程序时,内存使用量可能会高于必要值,虚拟机可能会开始耗尽主机所需的资源 与传统的容器化应用程序不同,共享操作系统环境(内核),因此它们比完整虚拟机使用更少的资源,并减轻主机内存的压力
重量 GB:传统虚拟机可占用大量磁盘空间:除了虚拟机托管的任何应用程序外,它们还包含完整的操作系统和相关工具。 MB容器相对较轻:它们仅包含使容器化应用程序运行所需的库和工具,因此它们比虚拟机更紧凑,并且启动速度更快。
维护与更新 在更新或修补操作系统时,必须逐个更新传统计算机:必须单独修补每个客户操作系统。 对于容器,只需更新容器主机(托管容器的机器)的操作系统。这显著简化了维护。
  • 重量
容器vs虚拟机
  • 维护和更新
容器vs虚拟机

小结:

虚拟机技术缺点:

  • 资源占用十分多
  • 冗余步骤多
  • 启动很慢

1.3 Docker闲谈

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

1.4 Docker用处

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

Docker与虚拟机技术的不同:

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

DevOps(开发、运维)

应用更快速的交付和部署

传统:一堆帮助文档,按住程序

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

更便捷的升级和扩缩容

使用了Docker后,我们部署应用就和搭积木一样

项目打包为一个镜像,可以方便地拓展服务器

更简单的系统运维

开发和测试环境是高度一致的

更高效的计算资源利用

Docker是内核级别的虚拟化,可以在一个物理机上运行很多的容器实例

1.5 Docker术语

Docker的基本组成

  • 镜像(Image)

    docker镜像类似于一个模板,可以通过这个模板来创建多个容器服务(最终服务运行或者项目运行就是在容器里的)

  • 容器(container)

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

    • 启动、停止、删除等基本命令
    • 理解为:简易的Linux系统
  • 仓库(repository)

    仓库就是存放镜像的地方

    仓库分为公有仓库(Docker Hub、Aliyun、TencentCloud)和私有仓库:

2. Docker安装

环境准备

Linux 服务器

  • 环境查看

    • 系统内核版本: uname -rimage-20220830090254785

    • 系统环境:cat /etc/os-releasc

      NAME="CentOS Linux"
      VERSION="7 (Core)"
      ID="centos"
      ID_LIKE="rhel fedora"
      VERSION_ID="7"
      PRETTY_NAME="CentOS Linux 7 (Core)"
      ANSI_COLOR="0;31"
      CPE_NAME="cpe:/o:centos:centos:7"
      HOME_URL="https://www.centos.org/"
      BUG_REPORT_URL="https://bugs.centos.org/"
      
      CENTOS_MANTISBT_PROJECT="CentOS-7"
      CENTOS_MANTISBT_PROJECT_VERSION="7"
      REDHAT_SUPPORT_PRODUCT="centos"
      REDHAT_SUPPORT_PRODUCT_VERSION="7"
      

2.1 Docker Engine(官网手册)

https://docs.docker.com/engine/install/centos/#prerequisites

2.1.1 卸载旧版本

旧版本的Docker可以被称为docker或者docker-engine, 使用下面的命令进行卸载

sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

如果成功, yum会返回这些没有安装.

image-20220830092405770

2.1.2 安装方法

你可以根据你的需要,以不同的方式安装Docker Engine:

  • 大多数用户设置Docker的存储库并从其中进行安装,以简化安装和升级任务。这是推荐的方法。

  • 部分用户下载并手动安装RPM包,完全通过手动方式进行升级管理。这在一些情况下很有用,比如在没有互联网接入的系统上安装Docker。

  • 在测试和开发环境中,一些用户选择使用自动化脚本来安装Docker。

方法 适合场景 适合人群
设置Docker的存储库
下载并手动安装RPM包
自动化脚本

2.1.3 安装 (推荐方法)

​ 在新机器上首次安装Docker Engine之前, 首先需要设置Docker 仓库, 之后就可以在存储库中进行Docker的安装以及更新了!

2.1.4 更新方法

先卸载再安装

2.1.5 卸载方法

  1. 卸载Docker Engine, CLI, Containerd 和Docker Compose 包:

    sudo yum remove docker-ce docker-ce-cli containerd.io docker-compose-plugin
    
  2. 删除所有的映像、容器、卷或自定义配置文件

    sudo rm -rf /var/lib/docker
    sudo rm -rf /var/lib/containerd
    

    docker的默认工作路径 /var/lib/docker

2.2 aliyun镜像加速

  • 开启镜像加速器

image-20220830102810223

免费使用!不要看错了

image-20220830110528059

  • 配置使用
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://pg7rwnnq.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

3. Docker基本原理(实践前后学习)

3.1 前置

Docker是如何工作的?

image-20220830111702634

Docker 为什么比VM快 ?

  • Docker有更少的抽象层
  • 利用了宿主机的内核, VM需要Guest OS
image-20220830111843229
image-20220830112103151

3.2 Docker镜像原理

镜像是什么?

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

所有的应用,直接打包docker镜像,就可以直接跑起来

镜像的获得方式

  • 远程
  • 复制
  • 自己制作一个镜像DockerFile

3.2.1 Docker镜像加载

UnionFS(联合文件系统)

UnionFS是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)

UnionFS是Docker镜像的基础,镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

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

Docker镜像加载

Docker的镜像实际上是由一层一层的文件系统(UnionFS)组成的。

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

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

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

Docker分层举例

image-20220901202230375

可以看到有些层是已经存在了的~

理解:

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

eg. 基于Ubuntu 16.04创建一个新的镜像,这就是新镜像的第一层; 如果在该镜像中添加python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁就会创建第三个镜像层.

如下图,该镜像就包含三个镜像层,

image-20220902090017793

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

image-20220902090855669

上图中的镜像层跟之前图中的略有区别, 主要目的是便于展示文件.

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

image-20220902091048422

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

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

Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应

文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。

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

下图展示了与系统西安市相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。

image-20220902092036608

Docker 镜像特点

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

image-20220901205857446

3.2.2 Commit镜像

docker commit 容器id 目标镜像名[:TAG] # 提交容器成为一个新的副本

-m="xxx" 	# 提交的描述信息
-a="aaa"	# 容器的作者
  • 启动最新默认tomcat

    root@su-codeink: ~ # docker run -d --name tomcatTest -p 7001:8080 tomcat
    Unable to find image 'tomcat:latest' locally
    latest: Pulling from library/tomcat
    0e29546d541c: Already exists 
    9b829c73b52b: Already exists 
    cb5b7ae36172: Already exists 
    6494e4811622: Already exists 
    668f6fcc5fa5: Already exists 
    dc120c3e0290: Already exists 
    8f7c0eebb7b1: Already exists 
    77b694f83996: Already exists 
    0f611256ec3a: Pull complete 
    4f25def12f23: Pull complete 
    Digest: sha256:9dee185c3b161cdfede1f5e35e8b56ebc9de88ed3a79526939701f3537a52324
    Status: Downloaded newer image for tomcat:latest
    456270e5ef5f6afc06f128fc3fa71df9ccac0b322bb4d2e33940bafcb8540f13
    
    root@su-codeink: ~ # docker ps
    CONTAINER ID  IMAGE   CREATED         STATUS         PORTS                                     NAMES
    456270e5ef5f  tomcat  21 seconds ago  Up 20 seconds  0.0.0.0:7001->8080/tcp, :::7001->8080/tcp tomcatTest
    
  • 进入tomcat做一些修改后, 可用commit命令来提交, 获得一个镜像

    root@su-codeink: ~ # docker commit -a="codeink" -m="copy webapps.dict/* to webapps" 456270e5ef5f tomcat-codeink:1.0.0.SNAP
    sha256:57b50f32fde37a5407101559a1f04f51913c7f467d6c706c3b5a51d3f065bf85
    

    image-20220902094957621

4. Docker使用

4.1 Docker常用命令

4.1.1 帮助命令

docker version		# 显示Docker的版本信息
docker info			# 显示Docker的系统信息
docker --help		# 查看使用说明

4.1.2 镜像命令

运行docker需要root权限

  • docker images

    image-20220830121915847

    Repository --> 镜像的仓库

    tag --> 镜像的标签

    image id --> 镜像的id

    created --> 镜像的创建时间

    size --> 镜像的大小

  • docker search xxx --> 搜索镜像

    image-20220830121130210

    docker search xxx [--fiter=STARS=3000] 		# 对搜索结果进行过滤
    

    image-20220830124348135

  • docker pull --> 下载镜像

    # docker pull xxx[:tag]
    
  • docker rmi --> 删除镜像

    docker rmi -f 镜像id
    docker rmi -f 镜像id 镜像id 镜像id		# 根据镜像id 删除多个镜像
    docker rmi -f $(docker images -aq) 		# 删除全部镜像
    

4.1.3 容器命令

镜像才能创建容器

docker pull ubuntu

image-20220830125441942

  • 新建并启动容器 docker run [参数] xxx

    -name=""	容器名字 tomcat-1 tomcat-2, 用以区分容器
    -d:			后台方式运行
    -it:		使用交互方式运行, 进入容器查看内容
    -p:			指定容器的端口
    # 使用方式
    # -p ip:主机端口:容器端口
    # -p 主机端口:容器端口(常用)
    # -p 端口
    
    -P:			随机指定端口
    

    启动并进入容器 -it

    image-20220830141019221

    后台启动容器 -d

    image-20220830143814520

    发现容器停止了!

    原因: 必须要有一个前台进程, 如果没有前台进程就会自动停止

  • 启动容器 start

    docker start 容器id
    docker restart 容器id
    
  • 停止容器

    docker stop 容器id	# 停止容器
    docker stop 容器名	   
    docker kill 容器id 	# 强制停止容器
    
  • 查看正在运行的容器

    docker ps	# 列出全部运行中的容器
    -a 			# 列出全部容器(包括已经结束了的)
    -n=?		# 列出最近创建n的容器(排序输出+limit)
    

    image-20220830141500772

    image-20220830141807507

    技巧:(格式化输出)

    .ID - Container ID
    .Image - Image ID
    .Command - Quoted command
    .CreatedAt - Time when the container was created.
    .RunningFor - Elapsed time since the container was started.
    .Ports - Exposed ports.
    .Status - Container status.
    .Size - Container disk size.
    .Names - Container names.
    .Labels - All labels assigned to the container.
    .Label - Value of a specific label for this container. For example {{.Label "com.docker.swarm.cpu"}}
    .Mounts - Names of the volumes mounted in this container.
    
    
    docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Status}}"
    
  • 退出容器

    exit 	# 退出容器并结束容器运行
    Ctrl+P+Q# 仅退出容器
    

    image-20220830142502160

  • 删除容器

    运行中的容器无法直接删除, 但可以强制删除

    docker rm 容器id
    docker rm $(docker ps -aq)
    docker rm -f $(docker ps -aq)		# 强制删除所有容器 
    docker ps -a -q | xargs docker rm 	# 强制删除所有容器(管道方式)
    

4.1.4 其他命令

1) 日志命令
  • 日志的帮助命令

    docker logs --help
    
    输出:
    Usage:  docker logs [OPTIONS] CONTAINER
    
    Fetch the logs of a container
    
    Options:
          --details        Show extra details provided to logs
      -f, --follow         Follow log output
          --since string   Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
      -n, --tail string    Number of lines to show from the end of the logs (default "all")
      -t, --timestamps     Show timestamps
          --until string   Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
    
  • 查看日志

    docker logs -tf 容器id
    # 根据提示信息可知
    -t:			# 显示时间戳
    -f:			# 流式输出, 一直输出
    -tail n 	# 选择开始时输出的日志条数
    
image-20220830185411595

-tf 条件输出

image-20220830185354467

-f 条件输出

2) 查看容器进程
root@su-codeink: ~ # docker top 5f694cc63f51
UID    PID   PPID  C  STIME   TIME    CMD
root   2320  2301  0  19:19   00x3     /bin/sh -c while true;do echo 111;sleep 1;done
root   4267  2320  0  19:28   00x3   sleep 1
3) 查看容器的元数据
root@su-codeink: ~ # docker inspect --help

Usage:  docker inspect [OPTIONS] NAME|ID [NAME|ID...]

Return low-level information on Docker objects

Options:
  -f, --format string   Format the output using the given Go template
  -s, --size            Display total file sizes if the type is container
      --type string     Return JSON for specified type
      
      
root@su-codeink: ~ # docker ps -a
CONTAINER ID  IMAGE   COMMAND            CREATED         STATUS          NAMES
5f694cc63f51  ubuntu  "/bin/sh -c 'wh…"  16 minutes ago  Up 16 minutes   kind_euclid
  • 查看指定容器的元数据
root@su-codeink: ~ # docker inspect 5f694cc63f51
[
    {
        "Id": "5f694cc63f51526219864f72f15b03a67baa65236c1ad979bb7f44b70216e3e5",
        "Created": "2022-08-30T11:19:23.191647333Z",
        "Path": "/bin/sh",
        "Args": [
            "-c",
            "while true;do echo 111;sleep 1;done "
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 2320,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2022-08-30T11:19:23.540286636Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:ba6acccedd2923aee4c2acc6a23780b14ed4b8a5fa4e14e252a23b846df9b6c1",
        "ResolvConfPath": "/var/lib/docker/containers/5f694cc63f51526219864f72f15b03a67baa65236c1ad979bb7f44b70216e3e5/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/5f694cc63f51526219864f72f15b03a67baa65236c1ad979bb7f44b70216e3e5/hostname",
        "HostsPath": "/var/lib/docker/containers/5f694cc63f51526219864f72f15b03a67baa65236c1ad979bb7f44b70216e3e5/hosts",
        "LogPath": "/var/lib/docker/containers/5f694cc63f51526219864f72f15b03a67baa65236c1ad979bb7f44b70216e3e5/5f694cc63f51526219864f72f15b03a67baa65236c1ad979bb7f44b70216e3e5-json.log",
        "Name": "/kind_euclid",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {},
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "CgroupnsMode": "host",
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/f8f3805a835bd4e3cd3e558d34eb72871db03525c7324120e5c3c0608b9c6b68-init/diff:/var/lib/docker/overlay2/fbda1c5d5272b0dbfda0973b21d0a8586e519542fe50c0b485068992a8857673/diff",
                "MergedDir": "/var/lib/docker/overlay2/f8f3805a835bd4e3cd3e558d34eb72871db03525c7324120e5c3c0608b9c6b68/merged",
                "UpperDir": "/var/lib/docker/overlay2/f8f3805a835bd4e3cd3e558d34eb72871db03525c7324120e5c3c0608b9c6b68/diff",
                "WorkDir": "/var/lib/docker/overlay2/f8f3805a835bd4e3cd3e558d34eb72871db03525c7324120e5c3c0608b9c6b68/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "5f694cc63f51",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "while true;do echo 111;sleep 1;done "
            ],
            "Image": "ubuntu",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "1b2e76d053114e1777c37b9cdbfa37891adc81c8eaadab59f6d881affb1835ae",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/1b2e76d05311",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "c2530f6d8f6da5e8c0fc7d0cc4edf323401a272da146f18484208d0bc2bb14c4",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "8f746dac50cd1aed398b87909d5b9ba7a943e1e0ec72a5f98f96485a7bc580c8",
                    "EndpointID": "c2530f6d8f6da5e8c0fc7d0cc4edf323401a272da146f18484208d0bc2bb14c4",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]
4) 进入正在运行的容器
  • docker exec

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

    root@su-codeink: ~ # docker exec -it 5f694cc63f51 /bin/bash
    
    root@5f694cc63f51:/# ps -ef
    UID        PID  PPID  C STIME TTY          TIME CMD
    root         1     0  0 11:19 ?        00:00:00 /bin/sh -c while true;do echo 111;sleep 1;done 
    root      1335     0  0 11:41 pts/0    00:00:00 /bin/bash
    root      1354     1  0 11:41 ?        00:00:00 sleep 1
    root      1355  1335  0 11:41 pts/0    00:00:00 ps -ef
    
    root@5f694cc63f51:/# ls
    bin  boot  dev  etc  home  lib  lib32  lib64  libx32  ...
    
    
  • docker attach

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

image-20220830194814075

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

docker cp

# 进入容器环境
root@su-codeink: ~ # docker attach b416aebb6a3c
root@b416aebb6a3c:/# ls
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@b416aebb6a3c:/# cd home
root@b416aebb6a3c:/home# ls

# 在容器内新建一个文件
root@b416aebb6a3c:/home# touch 111.txt

# 向该文件输入111 
root@b416aebb6a3c:/home# echo 111 >111.txt

# 查看写入是否成功
root@b416aebb6a3c:/home# cat 111.txt
111

# 退出容器环境
root@b416aebb6a3c:/home# read escape sequence
root@su-codeink: ~ # docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS              PORTS     NAMES
b416aebb6a3c   ubuntu    "/bin/bash"   About a minute ago   Up About a minute             cool_borg

以上命令在容器内创建了一个文件, 之后需要将该文件复制出来:

root@su-codeink: ~ # docker cp b416aebb6a3c:/home/111.txt /root/test
# 本命令的格式为:
# docker cp 容器id:容器内文件 主机目录

如下图所示, 文件成功拷贝出来了!

image-20220830195920738

可以使用 -v 卷的技术, 实现将容器内目录与主机的目录进行绑定

4.2 安装常用容器

4.2.1 安装Nginx

  • 安装稳定版的Nginx docker pull nginx:stable

    root@su-codeink: ~ # docker pull nginx:stable
    stable: Pulling from library/nginx
    a2abf6c4d29d: Pull complete 
    da03644a1293: Pull complete 
    dcbfc6badd70: Pull complete 
    3f7ccff97047: Pull complete 
    49e31097680b: Pull complete 
    c423e1dacb26: Pull complete 
    Digest: sha256:03f3cb0afb7bd5c76e01bfec0ce08803c495348dccce37bcb82c347b4853c00b
    Status: Downloaded newer image for nginx:stable
    docker.io/library/nginx:stable
    
  • 查看镜像

    root@su-codeink: ~ # docker images
    REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
    nginx         stable    50fe74b50e0d   8 months ago    141MB
    ubuntu        latest    ba6acccedd29   10 months ago   72.8MB
    hello-world   latest    feb5d9fea6a5   11 months ago   13.3kB
    
  • 启动容器并指定端口

    root@su-codeink: ~ # docker run -d --name nginx01 -p 7001:80 nginx:stable
    efe325c93ba4c90ba3cd5f49b6709626bf24e1dc8f65e26fd88ed67791c5a395
    

    端口暴露: 主机的7001端口关联到容器里的80端口

  • 显示!

    image-20220901103835614

  • 进入容器

    root@su-codeink: ~ # docker exec -it nginx01 /bin/bash
    root@efe325c93ba4:/# whereis nginx 
    nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
    root@efe325c93ba4:/# cd etc/nginx/
    root@efe325c93ba4:/etc/nginx# ls
    conf.d	fastcgi_params	mime.types  modules  nginx.conf  scgi_params  uwsgi_params
    
  • 在外部修改容器配置文件

    每次修改容器都要进入容器内部?

    - v 数据卷技术: 提供外部映射

4.2.2 安装tomcat

  • 使用tomcat

    docker run -it --rm -p 7002:8080 tomcat:9.0
    # --rm: 用完即删
    
    docker run -it -p 7002:8080 tomcat:9.0
    
  • 查看

    image-20220901123943022

  • 进入容器

    root@su-codeink: ~ # docker exec -it a023804512d5 /bin/bash
    # -it 以交互方式进入容器
    
    root@a023804512d5:/usr/local/tomcat# ls
    BUILDING.txt	 LICENSE  README.md	 RUNNING.txt  conf  logs	    temp     webapps.dist
    CONTRIBUTING.md  NOTICE   RELEASE-NOTES  bin	      lib   native-jni-lib  webapps  work
    root@a023804512d5:/usr/local/tomcat# ls -al
    total 172
    drwxr-xr-x 1 root root  4096 Dec 22  2021 .
    drwxr-xr-x 1 root root  4096 Dec 22  2021 ..
    -rw-r--r-- 1 root root 18970 Dec  2  2021 BUILDING.txt
    -rw-r--r-- 1 root root  6210 Dec  2  2021 CONTRIBUTING.md
    -rw-r--r-- 1 root root 57092 Dec  2  2021 LICENSE
    -rw-r--r-- 1 root root  2333 Dec  2  2021 NOTICE
    -rw-r--r-- 1 root root  3378 Dec  2  2021 README.md
    -rw-r--r-- 1 root root  6898 Dec  2  2021 RELEASE-NOTES
    -rw-r--r-- 1 root root 16507 Dec  2  2021 RUNNING.txt
    drwxr-xr-x 2 root root  4096 Dec 22  2021 bin
    drwxr-xr-x 1 root root  4096 Sep  1 04:38 conf
    drwxr-xr-x 2 root root  4096 Dec 22  2021 lib
    drwxrwxrwx 1 root root  4096 Sep  1 04:38 logs
    drwxr-xr-x 2 root root  4096 Dec 22  2021 native-jni-lib
    drwxrwxrwx 2 root root  4096 Dec 22  2021 temp
    drwxr-xr-x 2 root root  4096 Dec 22  2021 webapps
    drwxr-xr-x 7 root root  4096 Dec  2  2021 webapps.dist
    drwxrwxrwx 2 root root  4096 Dec  2  2021 work
    
  • tomcat中webapps文件夹为空, aliyun镜像默认选择最小的镜像, 保证可用即可;可以将webapps.dist中的文件复制到webapps中!

    root@a023804512d5:/usr/local/tomcat/webapps# ls
    root@a023804512d5:/usr/local/tomcat/webapps# cp -r ../webapps.dist/* .
    root@a023804512d5:/usr/local/tomcat/webapps# ls
    ROOT  docs  examples  host-manager  managerroot@a023804512d5:/usr/local/tomcat/webapps# ls -al
    total 32
    drwxr-xr-x  1 root root 4096 Sep  1 04:48 .
    drwxr-xr-x  1 root root 4096 Dec 22  2021 ..
    drwxr-xr-x  3 root root 4096 Sep  1 04:48 ROOT
    drwxr-xr-x 15 root root 4096 Sep  1 04:48 docs
    drwxr-xr-x  7 root root 4096 Sep  1 04:48 examples
    drwxr-xr-x  6 root root 4096 Sep  1 04:48 host-manager
    drwxr-xr-x  6 root root 4096 Sep  1 04:48 manager
    

4.2.3 安装ES+kibana

1) s安装 ES
  • 启动容器, 直接run

    docker run -d --name elasticsearch -p 7003:9200 -p 7004:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
    
    # --net somenetwork: 网络配置
    # es 的数据一般需要选择安全目录进行挂载
    
  • es比较耗内存,可以用过docker status 查看CPU状态

    CONTAINER ID   NAME           CPU %   MEM USAGE / LIMIT   MEM %   NET   I/O     BLOCK I/O    PIDS
    7bcd4d1f4666   elasticsearch  0.24%   1.261GiB / 7.545GiB 16.71%  656B / 0B   0B / 696kB   45
    
  • 浏览器打开:

    image-20220901130827218

    {
    "name": "7bcd4d1f4666",
    "cluster_name": "docker-cluster",
    "cluster_uuid": "8Kv987NsTrO-JKZKkhyiow",
    "version": {
    "number": "7.6.2",
    "build_flavor": "default",
    "build_type": "docker",
    "build_hash": "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
    "build_date": "2020-03-26T06:34:37.794943Z",
    "build_snapshot": false,
    "lucene_version": "8.4.0",
    "minimum_wire_compatibility_version": "6.8.0",
    "minimum_index_compatibility_version": "6.0.0-beta1"
    },
    "tagline": "You Know, for Search"
    }
    
  • 停止elastic search容器

    root@su-codeink: ~ # docker stop elasticsearch
    elasticsearch
    root@su-codeink: ~ # docker ps
    CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
    
  • 增加对内存的限制

    docker run -d --name es01 -p 7003:9200 -p 7004:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms128m -Xmx512m"  elasticsearch:7.6.2
    

    image-20220901141151423

2) 安装 Kibana
3) Kibana连接ES

4.3 可视化

  • portainer

    docker run -d -p 7009:8000 -p 7010:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
    
    docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ee:latest
    

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

    
    
    
  • Rancher( CI / CD 使用)

image-20220901160953409

4.4 容器数据卷

是什么?

问题: 删除容器,那容器中的数据也会随之删除!

解决:

docker数据卷:使得docker容器中的数据不仅可以在容器中, 还可以存储在主机中!即:容器数据共享, 将容器中产生的数据同步到本地.

实际上就等于, 将容器内的目录挂载到Linux上面.

image-20220902095735247

有三种食用方式:

  • 指定路径挂载
  • 匿名挂载
  • 具名挂载
  • 镜像内部自己挂载的(可以通过dockerfile在创建自己的镜像时进行挂载配置)

第二种,第三种方式均使用docker默认的挂载地址/var/lib/docker/volume/xxx

4.4.1 指定路径挂载

-v命令

命令解释

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

  • 运行Ubuntu

    root@su-codeink: /home # docker run -it -v /home/docker-test-v:/home ubuntu /bin/bash
    root@8fb553b6145c:/# ls
    bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  ...
    
  • 查看运行信息

    root@su-codeink: /home/docker-test-v # docker ps
    CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS                   
    8fb553b6145c   ubuntu    "/bin/bash"   About a minute ago   Up About a minute     
    
    root@su-codeink: /home/docker-test-v # docker inspect 8fb553b6145c
    
    ...
    "Mounts": [
        {
            "Type": "bind",
            "Source": "/home/docker-test-v",
            "Destination": "/home",
            "Mode": "",
            "RW": true,
            "Propagation": "rprivate"
        }
    ],
    ...
    

    其中的Source是主机内的目录地址, Destination则是docker容器内的目录地址

  • 修改容器内文件

    root@8fb553b6145c:/home# touch 111
    root@8fb553b6145c:/home# echo 111 >> 111
    root@8fb553b6145c:/home# echo hello-v >> 111
    root@8fb553b6145c:/home# cat 111
    111
    hello-v
    
  • 主机内的被挂载目录查看

    root@su-codeink: /home/docker-test-v # ls
    111
    root@su-codeink: /home/docker-test-v # cat 111
    111
    hello-v
    

    同样,在主机内被挂载的目录修改, 容器内也会得到修改(不管是否重启)

    root@su-codeink: /home/docker-test-v # vi 111
    root@su-codeink: /home/docker-test-v # cat 111
    111
    hello-v
    this updated by host machine!
    

    关闭容器后重新打开再看一下!

    # 关闭容器后显示
    root@su-codeink: /home # docker ps
    CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
    root@su-codeink: /home # docker ps -a
    CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS                    
    8fb553b6145c   ubuntu    "/bin/bash"   28 minutes ago   Exited (0) 11 seconds ago   
    
    # 启动容器
    root@su-codeink: /home # docker start 8fb553b6145c
    8fb553b6145c
    
    root@su-codeink: /home # docker ps 
    CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          
    8fb553b6145c   ubuntu    "/bin/bash"   28 minutes ago   Up 15 seconds             
    
    # 进入容器
    root@su-codeink: /home # docker attach 8fb553b6145c
    root@8fb553b6145c:/# cd home
    root@8fb553b6145c:/home# ls
    111
    root@8fb553b6145c:/home# cat 111
    111
    hello-v
    this updated by host machine!
    
  • 优点

    以后只需要在本地修改就好,容器会自动同步

4.4.2 实战MySQL

思考MySQL数据持久化的问题

  • 启动MySQL, 查看官方(hub.docker.com)

    docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
    
    -e:	# mysql 的环境配置
    root@su-codeink: /home # docker run -d -p 7001:3306 -v /home/docker-share/mysql/conf:/etc/mysql/conf.d -v /home/share/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=wqbssy1314. --name mysql01 mysql:5.7
    8f6d99dd227b16eac230ed64bb96b52e0797b14f69482df2a990d2ee9add3be4
    
    -v: 	# 可以挂载多个
    

    image-20220902112122210

  • 即使容器删掉数据也不会丢失!

    在MySQL中新建数据库、表,向表里插入数据。

    image-20220902113126164

    将容器停掉并删除

    docker stop 容器id可以发现MySQL已经打不开了.

    image-20220902114326706

    删除容器后重新运行命令

    # 
    root@su-codeink: /home/docker-share/mysql/data # docker ps
    CONTAINER ID   IMAGE      COMMAND                 CREATED          STATUS         NAMES
    2887ec5c2a89   mysql:5.7  "docker-entrypoint.s…"  16 minutes ago   Up 16 minutes  mysql01
    
    # 停止并删除容器
    root@su-codeink: /home/docker-share/mysql/data # docker stop 2887ec5c2a89
    2887ec5c2a89
    root@su-codeink: /home/docker-share/mysql/data # docker rm 2887ec5c2a89
    2887ec5c2a89
    
    # 重新运行
    root@su-codeink: /home/share/mysql # docker run -d -p 7001:3306 -v /home/docker-share/mysql/conf:/etc/mysql/conf.d -v /home/docker-share/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=wqbssy1314. --name mysql01 mysql:5.7
    cc45bffba7fb09f1d2f0765babc284057c5202c63830a516385d2be33f30e882
    

    可以发现数据未丢失

    image-20220902114818706

4.4.3 (具名/匿名)挂载

匿名挂载

匿名就是不写主机目录

eg. docker run -d -P --name nginx01 -v /etc/nginx nginx

  • 匿名挂载

    root@su-codeink: /home/share/mysql # docker run -d -p 7001:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=wqbssy1314. --name mysql02 mysql:5.7
    f8da431d1802bf54fc9125f56e909d38adede387f08e24230c3da5464154e620
    
    root@su-codeink: /home/share/mysql # docker ps -a
    CONTAINER ID   IMAGE       COMMAND      CREATED          STATUS         			NAMES
    f8da431d1802   mysql:5.7   "docker-…"   4 seconds ago    Up 4 seconds        		mysql02
    cc45bffba7fb   mysql:5.7   "docker-…"   27 minutes ago   Exited (0) 9 minutes ago   mysql01
    
  • 使用volume命令

    root@su-codeink: /home/share/mysql # docker volume list
    DRIVER    VOLUME NAME
    local     da43abb536cb441b2b9b634206b6828c83a5201469490c61daf79fc430c43030
    local     e2e7c8f67d401ec74ae7b4229d14965354f9649896b8168ba8b6ce541a9646da
    local     f59fcf0a5e11ffca782555f993160b5bd509fbff6ad80f668d169bbd2976836b
    local     fe841c8b25f5f1676a9790d8b4f3112236cf078bfad679d7c7ae6e7ded951efa
    local     portainer_data
    local     varrundocker.sock
    
    
  • 使用inspect命令

    "Mounts": [
            {
                "Type": "volume",
                "Name": "e2e7c8f67d401ec74ae7b4229d14965354f9649896b8168ba8b6ce541a9646da",
                "Source": "/var/lib/docker/volumes/e2e7c8f67d401ec74ae7b4229d14965354f9649896b8168ba8b6ce541a9646da/_data",
                "Destination": "/etc/mysql/conf.d",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "f59fcf0a5e11ffca782555f993160b5bd509fbff6ad80f668d169bbd2976836b",
                "Source": "/var/lib/docker/volumes/f59fcf0a5e11ffca782555f993160b5bd509fbff6ad80f668d169bbd2976836b/_data",
                "Destination": "/var/lib/mysql",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ]
    
##### 具名挂载

> `-v vname 容器内需要挂载的目录地址 `

- 具名挂载运行

  ```shell
  root@su-codeink: /home/share/mysql # docker run -d -p 7002:3306 -v mysql03-conf:/etc/mysql/conf.d -v mysql03.data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=wqbssy1314. --name mysql03 mysql:5.7
  87d3524c75281259bddd59412b0e929c3702b57d3a460768643339bb230ccfb5
  
  -v mysql03.conf:xxx: 就是具名挂载
  
  root@su-codeink: /home/share/mysql # docker volume list
  DRIVER    VOLUME NAME
  local     14d827baaa98e8491f5085a4562ea55b5d2b8465acf3d0a80509206e6daae34a
  local     bc1bf4578166c5aabf5134e29ceb48fc79c3537dfcc8ac5b532098d35ae85465
  local     da43abb536cb441b2b9b634206b6828c83a5201469490c61daf79fc430c43030
  local     e2e7c8f67d401ec74ae7b4229d14965354f9649896b8168ba8b6ce541a9646da
  local     f59fcf0a5e11ffca782555f993160b5bd509fbff6ad80f668d169bbd2976836b
  local     fe841c8b25f5f1676a9790d8b4f3112236cf078bfad679d7c7ae6e7ded951efa
  local     mysql03-conf
  local     mysql03.data
  local     portainer_data
  local     varrundocker.sock
  
  root@su-codeink: /home/share/mysql # docker volume inspect mysql03.data
  [
      {
          "CreatedAt": "2022-09-02T12:32:08+08:00",
          "Driver": "local",
          "Labels": null,
          "Mountpoint": "/var/lib/docker/volumes/mysql03.data/_data",
          "Name": "mysql03.data",
          "Options": null,
          "Scope": "local"
      }
  ]

在docker里, 所有的数据卷在没有指定目录的情况下都是在/var/lib/docker/volumes/xxx

4.4.4 容器数据共享

可以用于多个容器同步数据

image-20220902141726831

比较不同:

docker run -it --name u01 -v /home/docker-share/u01:/u01  ubuntu
docker run -it --name u02 -v u02-v:/u01 --volumes-from u01  ubuntu
# 这样做不对!, 因为容器内挂载的重名了, 会以u02-v为数据卷名字在docker的volumes目录生成一个新的volume
docker run -it --name u03  --volumes-from u01  ubuntu

u01中 Mounts

"Mounts": [
    {
        "Type": "bind",
        "Source": "/home/docker-share/u01",
        "Destination": "/u01",
        "Mode": "",
        "RW": true,
        "Propagation": "rprivate"
    }
],

u02中 Mounts

"Mounts": [
    {
        "Type": "volume",
        "Name": "u02-v",
        "Source": "/var/lib/docker/volumes/u02-v/_data",
        "Destination": "/u01",
        "Driver": "local",
        "Mode": "z",
        "RW": true,
        "Propagation": ""
    }
]

u03中 Mounts

"Mounts": [
    {
        "Type": "bind",
        "Source": "/home/docker-share/u01",
        "Destination": "/u01",
        "Mode": "",
        "RW": true,
        "Propagation": "rprivate"
    }
],

通过 --volumes-from进行挂载时, 不需要用- v指定共享目录, 如果使用-v指定的路径与 --volumes-from中挂载的相同,则会以 -v为准

image-20220902160136784

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

但是一旦持久化到本地,本地的数据是不会(因停止容器或者删除容器)删除的

4.5 DockerFile

DockerFile 就是用来构建docker镜像的构建文件

镜像是一层层的, 脚本中就用一个个命令来对应, 每个命令都是一层

4.5.1 基本知识

步骤:

  1. 编写一个dockerfile文件
  2. docker build 构建成为镜像
  3. docker run 运行镜像
  4. docker push 发布镜像(DockerHub, 阿里云镜像仓库)

了解Ubuntudockerfile

FROM scratch
ADD ubuntu-bionic-oci-amd64-root.tar.gz /
CMD ["bash"]

了解CentOSdockerfile

FROM scratch
ADD centos-7-x86_64-docker.tar.xz /

LABEL \
    org.label-schema.schema-version="1.0" \
    org.label-schema.name="CentOS Base Image" \
    org.label-schema.vendor="CentOS" \
    org.label-schema.license="GPLv2" \
    org.label-schema.build-date="20201113" \
    org.opencontainers.image.title="CentOS Base Image" \
    org.opencontainers.image.vendor="CentOS" \
    org.opencontainers.image.licenses="GPL-2.0-only" \
    org.opencontainers.image.created="2020-11-13 00:00:00+00:00"

CMD ["/bin/bash"]
  • FROM: 最基本的镜像,docker hub中99%的镜像都是从scrach过来的.

  • 每个指令(关键字) 都必须是大写字母

  • 顺序执行

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

很多官方镜像都是基础包, 很多功能没有, 我们通常会写自己的镜像!

dockerfile是面向开发的, 我们以后要发布项目, 做镜像就需要编写dockerfile文件

4.5.2 Dockerfile 指令

部分 命令
基础镜像信息 FROM
维护者信息 MAINTAINER
镜像操作指令 RUN、COPY、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等
容器启动时执行指令 CMD、ENTRYPOINT
  • FROM:指定base镜像,Dockerfile中第一条指令必须是FROM指令,其格式如下:
  • MAINTAINER(弃用):指明作者信息,格式为:
  • RUN:在镜像的构建过程中执行特定的命令,并生成一个中间镜像。比如安装一些软件、配置一些基础环境,可使用\来换行
  • COPY: 将主机内的文件复制到镜像内, 如果目的位置不存在, Docker为自动创建所有需要的目录结构, 但是它只是简单的复制, 并不会去做文件提取和解压工作
  • ADD: 构建镜像时, 复制上下文中的文件到镜像内
  • EXPOSE: 为构建的镜像设置监听端口
  • ENV: 在构建的镜像中设置环境变量
  • LABEL: 给构建的镜像打标签
  • VOLUME: 指定镜像内的目录为数据卷
  • USER: 为接下来的Dockerfile指令指定用户. 受影响的指令有:RUN,CMD、ENTRYPOINT
  • WORKDIR: 为接下来的Dockerfile指令指定当前工作目录,可多次使用,如果使用的是相对路径,则相对的是上一个工作目录,类似于shell中的cd命令
  • ARG: 指定用户在docker build --build-arg=时可以使用的参数
  • ONBUILD: 向镜像中添加一个触发器, 当以该镜像为基础镜像再次构建新的镜像时, 会触发执行其中的指令
  • STOPSIGNAL: 触发系统信号
  • ENTRYPOINT: 指定镜像的执行程序
  • CMD: 指定容器运行时的默认参数
CMD vs ENTRYPOINT
  • CMD: 指定这个容器启动时需要运行的命令, 只有最后一个会(在启动容器时)生效, 可被替代
  • ENTRYPOINT: 指定这个容器时需要运行的命令, 可以追加命令

CMD

root@su-codeink: /home/dockerfile $ vim dockerfile-cmd-test
root@su-codeink: /home/dockerfile $ cat dockerfile-cmd-test 
FROM centos
CMD ["ls","-al"]
root@su-codeink: /home/dockerfile $ docker build -f dockerfile-cmd-test -t cmd-test .
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM centos
 ---> 5d0da3dc9764
Step 2/2 : CMD ["ls","-al"]
 ---> Running in 15d29b17608a
Removing intermediate container 15d29b17608a
 ---> 8715c287b7f6
Successfully built 8715c287b7f6
Successfully tagged cmd-test:latest

可以看到镜像已经成功创建

root@su-codeink: /home/dockerfile $ docker run -it cmd-test
total 56
drwxr-xr-x   1 root root 4096 Sep  2 10:49 .
drwxr-xr-x   1 root root 4096 Sep  2 10:49 ..
-rwxr-xr-x   1 root root    0 Sep  2 10:49 .dockerenv
lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x   5 root root  360 Sep  2 10:49 dev
drwxr-xr-x   1 root root 4096 Sep  2 10:49 etc
drwxr-xr-x   2 root root 4096 Nov  3  2020 home
lrwxrwxrwx   1 root root    7 Nov  3  2020 lib -> usr/lib
lrwxrwxrwx   1 root root    9 Nov  3  2020 lib64 -> usr/lib64
drwx------   2 root root 4096 Sep 15  2021 lost+found
drwxr-xr-x   2 root root 4096 Nov  3  2020 media
drwxr-xr-x   2 root root 4096 Nov  3  2020 mnt
drwxr-xr-x   2 root root 4096 Nov  3  2020 opt
dr-xr-xr-x 131 root root    0 Sep  2 10:49 proc
dr-xr-x---   2 root root 4096 Sep 15  2021 root
drwxr-xr-x  11 root root 4096 Sep 15  2021 run
lrwxrwxrwx   1 root root    8 Nov  3  2020 sbin -> usr/sbin
drwxr-xr-x   2 root root 4096 Nov  3  2020 srv
dr-xr-xr-x  13 root root    0 Aug 27 02:25 sys
drwxrwxrwt   7 root root 4096 Sep 15  2021 tmp
drwxr-xr-x  12 root root 4096 Sep 15  2021 usr
drwxr-xr-x  20 root root 4096 Sep 15  2021 var
root@su-codeink: /home/dockerfile $ docker run -it cmd-test -l
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.
ERRO[0000] error waiting for container: context canceled 
root@su-codeink: /home/dockerfile $ docker run -it cmd-test ls -a
.   .dockerenv	dev  home  lib64       media  opt   root  sbin	sys  usr
..  bin		etc  lib   lost+found  mnt    proc  run   srv	tmp  var

ENTRYPOINT

$ cat dockerfile-entrypoint-test 
FROM centos
ENTRYPOINT ["ls","-a"]

 $ docker build -f dockerfile-entrypoint-test -t entrypoint-test .
Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM centos
 ---> 5d0da3dc9764
Step 2/2 : ENTRYPOINT ["ls","-a"]
 ---> Running in ce3cb4b0eafe
Removing intermediate container ce3cb4b0eafe
 ---> af63a086f9c2
Successfully built af63a086f9c2
Successfully tagged entrypoint-test:latest
root@su-codeink: /home/dockerfile $ docker run -it entrypoint-test
.   .dockerenv	dev  home  lib64       media  opt   root  sbin	sys  usr
..  bin		etc  lib   lost+found  mnt    proc  run   srv	tmp  var
root@su-codeink: /home/dockerfile $ docker run -it entrypoint-test -al
total 56
drwxr-xr-x   1 root root 4096 Sep  2 10:53 .
drwxr-xr-x   1 root root 4096 Sep  2 10:53 ..
-rwxr-xr-x   1 root root    0 Sep  2 10:53 .dockerenv
lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x   5 root root  360 Sep  2 10:53 dev
drwxr-xr-x   1 root root 4096 Sep  2 10:53 etc
drwxr-xr-x   2 root root 4096 Nov  3  2020 home
lrwxrwxrwx   1 root root    7 Nov  3  2020 lib -> usr/lib
lrwxrwxrwx   1 root root    9 Nov  3  2020 lib64 -> usr/lib64
drwx------   2 root root 4096 Sep 15  2021 lost+found
drwxr-xr-x   2 root root 4096 Nov  3  2020 media
drwxr-xr-x   2 root root 4096 Nov  3  2020 mnt
drwxr-xr-x   2 root root 4096 Nov  3  2020 opt
dr-xr-xr-x 135 root root    0 Sep  2 10:53 proc
dr-xr-x---   2 root root 4096 Sep 15  2021 root
drwxr-xr-x  11 root root 4096 Sep 15  2021 run
lrwxrwxrwx   1 root root    8 Nov  3  2020 sbin -> usr/sbin
drwxr-xr-x   2 root root 4096 Nov  3  2020 srv
dr-xr-xr-x  13 root root    0 Aug 27 02:25 sys
drwxrwxrwt   7 root root 4096 Sep 15  2021 tmp
drwxr-xr-x  12 root root 4096 Sep 15  2021 usr
drwxr-xr-x  20 root root 4096 Sep 15  2021 var

4.5.3 实战 创建Linux镜像

  • 编写DockerFile文件

    root@su-codeink: /home/dockerfile $ vim codeink-ubuntu
    root@su-codeink: /home/dockerfile $ cat codeink-ubuntu 
    FROM ubuntu
    MAINTAINER codeink<111>
    
    ENV MYPATH /home
    WORKDIR $MYPATH
    
    RUN apt-get update
    RUN apt-get install -y apt-utils
    RUN apt-get install -y vim
    RUN apt-get install -y net-tools
    
    EXPOSE 80
    
    CMD echo $MYPATH
    CMD echo "-----end-----"
    CMD /bin/bash
    
    $ docker build -f codeink-ubuntu -t codeink-ubuntu .
    
    
  • 查看已经创建好的镜像

    root@su-codeink: ~ $ docker images
    REPOSITORY               TAG       IMAGE ID       CREATED          SIZE
    codeink-ubuntu           latest    bea813b92920   53 minutes ago   184MB
    tomcat                   9.0       b8e65a4d736d   8 months ago     680MB
    tomcat                   latest    fb5657adc892   8 months ago     680MB
    redis                    latest    7614ae9453d1   8 months ago     113MB
    nginx                    stable    50fe74b50e0d   8 months ago     141MB
    mysql                    5.7       c20987f18b13   8 months ago     448MB
    mysql                    latest    3218b38490ce   8 months ago     516MB
    portainer/portainer-ce   latest    0df02179156a   8 months ago     273MB
    ubuntu                   latest    ba6acccedd29   10 months ago    72.8MB
    hello-world              latest    feb5d9fea6a5   11 months ago    13.3kB
    portainer/portainer      latest    580c0e4e98b0   17 months ago    79.1MB
    kibana                   7.6.2     f70986bc5191   2 years ago      1.01GB
    elasticsearch            7.6.2     f29a1ee41030   2 years ago      791MB
    

    可以看到镜像已经创建完成, 使用该镜像创建容器docker run -it --name xxx codeink-ubuntu

  • 启动并进入使用自定义镜像创建的容器

    image-20220902182110204

    可以看到vim已经成功安装!

  • 查看镜像构建的过程

    root@su-codeink: ~ $ docker images
    REPOSITORY               TAG       IMAGE ID       CREATED          SIZE
    codeink-ubuntu           latest    bea813b92920   41 minutes ago   184MB
    tomcat                   9.0       b8e65a4d736d   8 months ago     680MB
    tomcat                   latest    fb5657adc892   8 months ago     680MB
    redis                    latest    7614ae9453d1   8 months ago     113MB
    nginx                    stable    50fe74b50e0d   8 months ago     141MB
    mysql                    5.7       c20987f18b13   8 months ago     448MB
    mysql                    latest    3218b38490ce   8 months ago     516MB
    portainer/portainer-ce   latest    0df02179156a   8 months ago     273MB
    ubuntu                   latest    ba6acccedd29   10 months ago    72.8MB
    hello-world              latest    feb5d9fea6a5   11 months ago    13.3kB
    portainer/portainer      latest    580c0e4e98b0   17 months ago    79.1MB
    kibana                   7.6.2     f70986bc5191   2 years ago      1.01GB
    elasticsearch            7.6.2     f29a1ee41030   2 years ago      791MB
    root@su-codeink: ~ $ docker history bea813b92920
    IMAGE          CREATED          CREATED BY                                      SIZE      
    bea813b92920   41 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin…   0B     
    fa1ecb17e31a   41 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B      
    88050887246c   41 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B      
    f6a088c78641   41 minutes ago   /bin/sh -c #(nop)  EXPOSE 80                    0B        
    3294228b2aaa   41 minutes ago   /bin/sh -c apt-get install -y vim               68.2MB  
    28137b9119fc   42 minutes ago   /bin/sh -c apt-get install -y apt-utils         5.15MB    
    0b8aa9d045f9   42 minutes ago   /bin/sh -c apt-get update -y                    37.8MB  
    1d325a7a75f0   44 minutes ago   /bin/sh -c #(nop) WORKDIR /home                 0B        
    122e22102dda   44 minutes ago   /bin/sh -c #(nop)  ENV MYPATH=/home             0B      
    3e1ebaa6c42e   44 minutes ago   /bin/sh -c #(nop)  MAINTAINER codeink<111>      0B      
    ba6acccedd29   10 months ago    /bin/sh -c #(nop)  CMD ["bash"]                 0B      
    <missing>      10 months ago    /bin/sh -c #(nop) ADD file:5d68d27cc15a80653…   72.8MB  
    
    

4.5.4 实战 Tomcat

  • 准备tomcat压缩包、JDK的压缩包

  • 编写Dockerfile

    FROM centos
    COPY README.md /usr/local/README.md
    
    ADD jdk-8u202-linux-x64.tar.gz /usr/local/
    ADD apache-tomcat-9.0.65.tar.gz /usr/local
    
    RUN yum -y install vim
    ENV MYPATH /usr/local
    WORKDIR $MYPATH
    
    ENV JAVA_HOMR /usr/local/jdk1.8.0_202
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar;$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.65
    ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.65
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib;$CATALINA_HOME/bin
    
    EXPOSE 8080
    
    CMD /usr/local/apache-tomcat-9.0.65/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.65/logs/catalina.out
    
  • 启动容器

    root@su-codeink: /data/file $  docker run -p 7001:8080 --name codeink-tomcat-test -v /home/docker-share/tomcat-test/webapps/test:/usr/local/apache-tomcat-9.0.65/webapps/test -v /home/docker-share/tomcat-test/logs:/usr/local/apache-tomcat-9.0.65/logs codeink-tomcat
    
  • 在被挂载的目录中进行编写

    • 创建WEB-INFO文件夹, 并创建web.xml文件

      <?xml version="1.0" encoding="gb2312"?>
      <web-app>
          <display-name>My Web Application</display-name>
          <description>
              An application for test.
          </description>
      </web-app>
      
    • 编写index.jsp/index.html/或者其他主界面文件

      <html>
      <body>
          <center>Now time is: <%=new java.util.Date()%></center>
      </body>
      </html>
      
  • 查看是否成功

    image-20220905111721511

4.5.5 挂载Volume

# 向一个dockerfile文件中写入下列指令

FROM ubuntu
VOLUME ["V01", "V02"]
CMD echo "====end===="
CMD /bin/bash

# 运行docker build 指令生成镜像

通过这种方式可以直接用镜像挂载

image-20220902134107948

可用看到镜像已经生成成功!

image-20220902134457661

使用自己的镜像创建一个容器

root@su-codeink: /home/test # docker run -it codeink/ubuntu:0.0.1 /bin/bash

root@095f73778e7c:/# ls
V01  V02  bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

# 其中的 V01、V02 就是我们在dockerfile文件中写的,也就是在生成容器的时候会自动挂载的数据卷目录

docker inspect xxx 
# 使用inspect命令可以看到容器的详细信息,在Mounts中可以看到被挂载的目录信息
"Mounts": [
    {
        "Type": "volume",
        "Name": "cbcfd09ded67c841d4f21a5a0b0b453c6e83dde544526495df155454abbdd7fd",
        "Source": "/var/lib/docker/volumes/cbcfd09ded67c841d4f21a5a0b0b453c6e83dde544526495df155454abbdd7fd/_data",
        "Destination": "V01",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    },
    {
        "Type": "volume",
        "Name": "36cd4342800b826a4cb9546ac63d7816b61350a897a67633f063be7c77f47952",
        "Source": "/var/lib/docker/volumes/36cd4342800b826a4cb9546ac63d7816b61350a897a67633f063be7c77f47952/_data",
        "Destination": "V02",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
],

4.6 发布镜像

可以在DockerHub进行发布!(需要注册账号)

直接docker login

可以使用docker tag 镜像id 修改后的tag

之后docker push 即可

image-20220905113504287

可以在阿里云镜像服务

  • 登录阿里云
  • 找到容器镜像服务
  • 创建命名空间
  • 创建容器镜像
  • 根据手册进行

5. Docker网络

5.1 Docker网络理解

image-20220905122622005

三个网卡:

  • lo: 本机回环地址
  • etho: 服务器内网地址
  • docker0: docker0地址

docker 如何处理web访问

  • 运行一个centos,一个tomcat

    在centos中可以直接使用 ip addr查看容器内网卡地址

    [root@4899a710ced0 /]# ip addr
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
        valid_lft forever preferred_lft forever
    180: eth0@if181: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
        valid_lft forever preferred_lft forever
    

    在tomcat(基于Debian系统),直接使用docker inspect 容器id即可查看容器IP地址

    "Networks": {
        "bridge": {
            "Gateway": "172.17.0.1",
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "GlobalIPv6PrefixLen": 0,
            "MacAddress": "02:42:ac:11:00:02",
            "DriverOpts": null
        }
    }
    

    可以在tomcat容器内安装一下net-tools,就可以shi用ipconfig 命令查看完整信息:

    # 首先需要将apt-get更新一下
    root@4132cfda09a8:/etc/apt# apt-get update
    
    # 安装一下net-tools工具
    root@4132cfda09a8:/etc/apt# apt-get install net-tools
    
    # 使用net-tools查看tomcat容器的网络配置
    root@4132cfda09a8:/etc/apt# 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 1315  bytes 18068129 (17.2 MiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 1305  bytes 100601 (98.2 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 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    

    可以看到在容器tomcat内,其IP是172.17.0.2, 而centos内的ip有个为172.17.0.3, 可以发现docker会给每个容器分配一个IP地址;此时再次查看主机的IP地址, 可以发现ip地址从3个变为了5个.

    root@su-codeink: ~ $ ip addr
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo 
            valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host 
            valid_lft forever preferred_lft forever
    2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
        link/ether 52:54:00:42:43:42 brd ff:ff:ff:ff:ff:ff
        inet 10.0.4.6/22 brd 10.0.7.255 scope global eth0
            valid_lft forever preferred_lft forever
        inet6 fe80::5054:ff:fe42:4342/64 scope link 
            valid_lft forever preferred_lft forever
    3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:ad:a7:d5:2d brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
            valid_lft forever preferred_lft forever
        inet6 fe80::42:adff:fea7:d52d/64 scope link 
            valid_lft forever preferred_lft forever
    177: vethd6c8b73@if176: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
        link/ether 06:c1:1e:3d:a3:50 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet6 fe80::4c1:1eff:fe3d:a350/64 scope link 
            valid_lft forever preferred_lft forever
    181: vethab4cbe1@if180: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
        link/ether ba:70:ed:5d:29:fb brd ff:ff:ff:ff:ff:ff link-netnsid 1
        inet6 fe80::b870:edff:fe5d:29fb/64 scope link 
           valid_lft forever preferred_lft forever
    

    docker使用的技术是evth-pair技术, 在177和181两个ip地址信息中可以看到177中显示了@if176,181中显示了@if180,

    evth-pair

    evth-pair就是一对的虚拟设备接口, 一段连着协议、一段彼此相连,

    OpenStac和Docker容器之间的连接、OVS的连接都是使用evth-pair技术

    可以测试一下 centos中是否可以ping通tomcat!

    image-20220905172015620

    可以ping通

image-20220905172239602

Docker 使用的是Linux的桥接, 宿主机中是一个Docker的网桥Docker0, Docker中所有的网络接口都是虚拟的.只要容器删除, 对应的一对网桥ip就没了.

image-20220905172507495

场景:在微服务中在连接数据时, 根据ip找到数据库地址, 但如果容器ip换掉了, 能否仅通过名字来访问容器?

root@su-codeink: ~ $ docker run -it --name centos-01 centos
root@su-codeink: ~ $ docker run -it --name centos-02 centos
root@su-codeink: ~ $ docker run -it --name centos-03 --link centos-02 centos


root@su-codeink: ~ $ docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
5cce9f5fe1c4   centos    "/bin/bash"   21 seconds ago   Up 20 seconds             centos-03
f43e5011363e   centos    "/bin/bash"   42 seconds ago   Up 41 seconds             centos-01
40303cdff6e3   centos    "/bin/bash"   53 seconds ago   Up 52 seconds             centos-02
root@su-codeink: ~ $ 

对结果进行查看:

root@su-codeink: ~ $ docker exec -it centos-01 ping centos-02
ping: centos-02: Name or service not known

root@su-codeink: ~ $ docker exec -it centos-03 ping centos-02
PING centos-02 (172.17.0.2) 56(84) bytes of data.
64 bytes from centos-02 (172.17.0.2): icmp_seq=1 ttl=64 time=0.082 ms
64 bytes from centos-02 (172.17.0.2): icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from centos-02 (172.17.0.2): icmp_seq=3 ttl=64 time=0.060 ms

root@su-codeink: ~ $ docker exec -it centos-02 ping centos-03
ping: centos-03: Name or service not known

可以发现, 只有centos03可以ping通centos02, 其他都无法ping通, 就算centos02也无法ping通centos03!

对结果分析:

  • 使用docker network ls 查看所有网络

  • 使用docker network inspect 网络id

image-20220905175016478

 "Containers": {
    "40303cdff6e3f9d43ab4afecefd05b241b4ccf35f4a6d9a6ac6a7b682743bd5a": {
        "Name": "centos-02",
        "EndpointID": "da04fe700e7ba8954e294bb8465e667ce1cc8750fb4b338e88eb0bd60312792d",
        "MacAddress": "02:42:ac:11:00:02",
        "IPv4Address": "172.17.0.2/16",
        "IPv6Address": ""
    },
    "5cce9f5fe1c4d56db171e79c31db1d50203b8a296ed7f891081a6ba909c3466b": {
        "Name": "centos-03",
        "EndpointID": "d80d64c81f13ebbde21e1cde57be49b58f31f9e5c3900e1d0d091461ac8e26ff",
        "MacAddress": "02:42:ac:11:00:04",
        "IPv4Address": "172.17.0.4/16",
        "IPv6Address": ""
    },
    "f43e5011363e15e300c6f45231d06089fca1f2aaa7ada0924e92787729943412": {
        "Name": "centos-01",
        "EndpointID": "87db19d95a1dbd32a85425844d8ecdabde26a9f7c62f5eee1500f244181f1b3d",
        "MacAddress": "02:42:ac:11:00:03",
        "IPv4Address": "172.17.0.3/16",
        "IPv6Address": ""
    }
}

使用docker inspect 容器id, 可以看到一个参数Links

"Links": [
    "/centos-02:/centos-03/centos-02"
],

但是, 已经不推荐使用了!

原因:docker0不支持容器名连接访问, 现在改为使用自定义网络

5.3 自定义网络

查看所有的docker网络docker network ls

image-20220905184113772

网络模式:

  • bridge: 桥接 Docker 默认
  • none: 不配置网络
  • host: 和宿主机共享网络
  • container: 容器网络连通(局限大)

测试

--net: 指定网络模式

docker0特点: 默认, 容器名不能访问, --link 可以打通连接

创建自己的网络:


root@su-codeink: ~ $ docker network create --driver bridge --subnet 192.168.100.0/24 --gateway 192.168.100.254  codeink-net
0332f225e381fc3d686fa1c283a40d6c3e8638bf67ffcb90a1ecb770f33e2bc6


root@su-codeink: ~ $ docker network ls
NETWORK ID     NAME          DRIVER    SCOPE
8f746dac50cd   bridge        bridge    local
0332f225e381   codeink-net   bridge    local
90f64b2d0c7f   host          host      local
ca05d4e43d85   none          null      local


root@su-codeink: ~ $ docker network inspect codeink-net 
[
    {
        "Name": "codeink-net",
        "Id": "0332f225e381fc3d686fa1c283a40d6c3e8638bf67ffcb90a1ecb770f33e2bc6",
        "Created": "2022-09-05T18:45:19.3457286+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.100.0/24",
                    "Gateway": "192.168.100.254"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

使用自定义网络运行容器

$ docker run -d -P --name codeink-tomcat-01 codeink/tomcat

$ docker run -d -P --name codeink-tomcat-02 codeink/tomcat

$ docker run -d -P --name codeink-tomcat-03 --net codeink-net  codeink/tomcat

$ docker run -d -P --name codeink-tomcat-04 --net codeink-net  codeink/tomcat

$ docker exec -it codeink-tomcat-04 ping codeink-tomcat-03
PING codeink-tomcat-03 (192.168.100.1) 56(84) bytes of data.
64 bytes from codeink-tomcat-03.codeink-net (192.168.100.1): icmp_seq=1 ttl=64 time=0.072 ms
64 bytes from codeink-tomcat-03.codeink-net (192.168.100.1): icmp_seq=2 ttl=64 time=0.058 ms

$ docker exec -it codeink-tomcat-04 ping 192.168.100.2
PING 192.168.100.2 (192.168.100.2) 56(84) bytes of data.
64 bytes from 192.168.100.2: icmp_seq=1 ttl=64 time=0.039 ms
64 bytes from 192.168.100.2: icmp_seq=2 ttl=64 time=0.034 ms

$ docker exec -it codeink-tomcat-04 ping 192.168.100.1
PING 192.168.100.1 (192.168.100.1) 56(84) bytes of data.
64 bytes from 192.168.100.1: icmp_seq=1 ttl=64 time=0.060 ms
64 bytes from 192.168.100.1: icmp_seq=2 ttl=64 time=0.052 ms

$ docker exec -it codeink-tomcat-04 ping codeink-tomcat-01
ping: codeink-tomcat-01: Name or service not known

$ docker exec -it codeink-tomcat-04 ping codeink-tomcat-02

即: 使用自定义网络时,不使用--link也可以直接使用容器名ping通均使用该自定义网络的容器, 但是还是不能直接使用容器名ping通没使用该网络的容器!

好处:

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

5.4 网络连通

使用docker network connect!!!

$ 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

Run 'docker network COMMAND --help' for more information on a command.

使用该命令后, 就是将该容器放到了该网络中

$ docker network inspect codeink-net 
[
    {
        "Name": "codeink-net",
        "Id": "0332f225e381fc3d686fa1c283a40d6c3e8638bf67ffcb90a1ecb770f33e2bc6",
        "Created": "2022-09-05T18:45:19.3457286+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.100.0/24",
                    "Gateway": "192.168.100.254"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "0ca324544f101ee899fe7a1eef12c7697468e6b7eded52a3d5b61d4a4f4bc42e": {
                "Name": "codeink-tomcat-04",
                "EndpointID": "580d4d96f7f0d457b0d80aa6b00825f2b4518be01c315fc33cd0cbcfd2226c0c",
                "MacAddress": "02:42:c0:a8:64:02",
                "IPv4Address": "192.168.100.2/24",
                "IPv6Address": ""
            },
            "55832c4673b60b72b84b63a727bca63fdab0c787d14360cb2ed6be7201674ae1": {
                "Name": "codeink-tomcat-01",
                "EndpointID": "a8dc21b35b2c4585938afc0c58ba10a4f7a6fe9c2c9e8ebb9fdabb8866ed640e",
                "MacAddress": "02:42:c0:a8:64:03",
                "IPv4Address": "192.168.100.3/24",
                "IPv6Address": ""
            },
            "e9bdf9a8d68822963bc38c7931051770712c84b60ecc445a0c34a6dfbd47feff": {
                "Name": "codeink-tomcat-03",
                "EndpointID": "bf26f78cebd7401396064e36bf4eeeef20b8afe5077b21a4ca109609114dbfaf",
                "MacAddress": "02:42:c0:a8:64:01",
                "IPv4Address": "192.168.100.1/24",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]




$ docker inspect codeink-tomcat-01
...
 "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "8f746dac50cd1aed398b87909d5b9ba7a943e1e0ec72a5f98f96485a7bc580c8",
                    "EndpointID": "b93c157537d2ddd1a9f92f5ecf958ff7ed346f0a558f1f2e866f0ba6a5dfd71f",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                },
                "codeink-net": {
                    "IPAMConfig": {},
                    "Links": null,
                    "Aliases": [
                        "55832c4673b6"
                    ],
                    "NetworkID": "0332f225e381fc3d686fa1c283a40d6c3e8638bf67ffcb90a1ecb770f33e2bc6",
                    "EndpointID": "a8dc21b35b2c4585938afc0c58ba10a4f7a6fe9c2c9e8ebb9fdabb8866ed640e",
                    "Gateway": "192.168.100.254",
                    "IPAddress": "192.168.100.3",
                    "IPPrefixLen": 24,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:c0:a8:64:03",
                    "DriverOpts": {}
                }
            }
...


image-20220905214106723

$ docker network ls
NETWORK ID     NAME          DRIVER    SCOPE
8f746dac50cd   bridge        bridge    local
0332f225e381   codeink-net   bridge    local
90f64b2d0c7f   host          host      local
ca05d4e43d85   none          null      local
$ docker network connect codeink-net codeink-tomcat-01
$ docker exec -it codeink-tomcat-01 ping codeink-tomcat-03
PING codeink-tomcat-03 (192.168.100.1) 56(84) bytes of data.
64 bytes from codeink-tomcat-03.codeink-net (192.168.100.1): icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from codeink-tomcat-03.codeink-net (192.168.100.1): icmp_seq=2 ttl=64 time=0.056 ms

5.5 实战:redis集群部署

image-20220905214246166

  • 创建网卡

    docker network create redis
    # 可以
    docker network inspect redis
    
  • 编写Shell脚本, 生成redis配置文件

for port in $(seq 1 6);
do
mkdir -p /data/redis/node-${port}/conf
touch /data/redis/node-${port}/conf/redis.conf
cat <<EOF >/data/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.100.100.${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

其中的 cluster-announce-ip是创建好的网卡的网络中的ip,

  • 编写shell,一键启动redis
for port in $(seq 1 6);
do
docker run -p 700${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /data/redis/node-${port}/data:/data \
-v /data/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.100.100.${port} redis:5.0 redis-server /etc/redis/redis.conf;
done
  • 查看redis启动情况

image-20220906092058626

  • 创建集群
docker exec -it redis-1 /bin/sh;
redis-cli --cluster create cat redis-cluster-ip.list | while read line 
do
eval "$line"
echo -n "172.100.100.$port:6378 "
done

redis-cli --cluster create 172.100.100.1:6379 172.100.100.2:6379 172.100.100.3:6379 172.100.100.4:6379 172.100.100.5:6379 172.100.100.6:6379 --cluster-replicas 1

image-20220906095954636

image-20220906100008654

$ redis-cli --cluster create 172.100.100.1:6379 172.100.100.2:6379 \
172.100.100.3:6379 172.100.100.4:6379 172.100.100.5:6379 \
172.100.100.6:6379 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.100.100.5:6379 to 172.100.100.1:6379
Adding replica 172.100.100.6:6379 to 172.100.100.2:6379
Adding replica 172.100.100.4:6379 to 172.100.100.3:6379
M: 502f6862c4c88d797426cd4b786ce6bd5c3be17a 172.100.100.1:6379
   slots:[0-5460] (5461 slots) master
M: 1eb282e642d33bc6cf8d03d608c28bc2a31b34c9 172.100.100.2:6379
   slots:[5461-10922] (5462 slots) master
M: 74e1e8a2f97673d33f45c4a124a630963ccaf83b 172.100.100.3:6379
   slots:[10923-16383] (5461 slots) master
S: d176a1ef844f455b11dd5bc82e504666a0ec1215 172.100.100.4:6379
   replicates 74e1e8a2f97673d33f45c4a124a630963ccaf83b
S: 1c041167447f10379c8d9d74baa3c7c866184994 172.100.100.5:6379
   replicates 502f6862c4c88d797426cd4b786ce6bd5c3be17a
S: 7de6f4f57d7536720656265b49dd27752cae99b9 172.100.100.6:6379
   replicates 1eb282e642d33bc6cf8d03d608c28bc2a31b34c9
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 172.100.100.1:6379)
M: 502f6862c4c88d797426cd4b786ce6bd5c3be17a 172.100.100.1:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 7de6f4f57d7536720656265b49dd27752cae99b9 172.100.100.6:6379
   slots: (0 slots) slave
   replicates 1eb282e642d33bc6cf8d03d608c28bc2a31b34c9
M: 74e1e8a2f97673d33f45c4a124a630963ccaf83b 172.100.100.3:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
M: 1eb282e642d33bc6cf8d03d608c28bc2a31b34c9 172.100.100.2:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 1c041167447f10379c8d9d74baa3c7c866184994 172.100.100.5:6379
   slots: (0 slots) slave
   replicates 502f6862c4c88d797426cd4b786ce6bd5c3be17a
S: d176a1ef844f455b11dd5bc82e504666a0ec1215 172.100.100.4:6379
   slots: (0 slots) slave
   replicates 74e1e8a2f97673d33f45c4a124a630963ccaf83b
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
# 使用集群方式
$ redis-cli -c
127.0.0.1:6379> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:338
cluster_stats_messages_pong_sent:343
cluster_stats_messages_sent:681
cluster_stats_messages_ping_received:338
cluster_stats_messages_pong_received:338
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:681
127.0.0.1:6379> cluster nodes
7de6f4f57d7536720656265b49dd27752cae99b9 172.100.100.6:6379@16379 slave 1eb282e642d33bc6cf8d03d608c28bc2a31b34c9 0 1662429755000 6 connected
74e1e8a2f97673d33f45c4a124a630963ccaf83b 172.100.100.3:6379@16379 master - 0 1662429755817 3 connected 10923-16383
1eb282e642d33bc6cf8d03d608c28bc2a31b34c9 172.100.100.2:6379@16379 master - 0 1662429754000 2 connected 5461-10922
502f6862c4c88d797426cd4b786ce6bd5c3be17a 172.100.100.1:6379@16379 myself,master - 0 1662429754000 1 connected 0-5460
1c041167447f10379c8d9d74baa3c7c866184994 172.100.100.5:6379@16379 slave 502f6862c4c88d797426cd4b786ce6bd5c3be17a 0 1662429755000 5 connected
d176a1ef844f455b11dd5bc82e504666a0ec1215 172.100.100.4:6379@16379 slave 74e1e8a2f97673d33f45c4a124a630963ccaf83b 0 1662429754013 4 connected
127.0.0.1:6379> 


127.0.0.1:6379> set a b
-> Redirected to slot [15495] located at 172.100.100.3:6379
OK
172.100.100.3:6379> get a
"b"

可以看到在node3中进行set a b, 为验证其高可用,将其关闭再试, 能够发现还可以找到!

$ redis-cli -c
127.0.0.1:6379> get a
-> Redirected to slot [15495] located at 172.100.100.4:6379
"b"

docker 搭建redis集群完成!

6. Docker进阶

6.1 Docker Compose

不使用Docker Compose的情况:

  • DockerFile build run 手动操作 --> 单个容器
  • 在微服务场景需要多次手动运行 --> 管理麻烦!

可以使用DockerCompose进行管理容器, 定义+运行 多个容器

官方描述

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:

  1. Define your app’s environment with a Dockerfile so it can be reproduced anywhere.
  2. Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.
  3. Run docker compose up and the Docker compose command starts and runs your entire app. You can alternatively run docker-compose up using Compose standalone(docker-compose binary).

6.1.1 作用

将多个容器编排, 单机场景!

一个docker-compose.yml内容如下:

version: "3.9"  # optional since v1.27.0
services:
  web:
    build: .
    ports:
      - "8000:5000"
    volumes:
      - .:/code
      - logvolume01:/var/log
    depends_on:
      - redis
  redis:
    image: redis
volumes:
    logvolume01: {}

6.1.2 安装

$ yum install -y docker-compose-plugin

$ docker compose version
Docker Compose version v2.10.2

6.1.3 Hi Compose

Docker 镜像 run --> 容器

DockerFile 构建镜像 --> 服务打包

docker-compose 启动项目(组合多个微服务/环境)

Docker 网络

6.1.4 yml语法

三层规则

1: version --> 版本

2: services --> 服务

​ 服务1: web

​ images

​ build

​ network

​ ports

3: 其它!()

depends_on: 依赖的顺序!

6.2 Swarm集群

暂未学习,直接进入kubernetes的学习

posted @   code墨&寇墨  阅读(79)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示
今天是妇女节