一文学会docker

287 阅读50分钟

docker

 大家好呀,我们今天又又又来开新坑了,今天这个坑就是Docker了,我们今天开始就要来了解一下Docker了。

博客地址: 云边日落

作者:酒笙

c6948122701920d9581b2f8754023e3c.png

什么是docker

  1. docker发展史
  • 在最开始的时候,docker不叫docker,叫dotcloud。这是由几个年轻人成立的小公司,在当时这样的一个小公司混的还算不错,但是还是打不过大厂,paas市场竞争激烈,dotcloud举步维艰,最后这些年轻人不甘心,不能让自己的坚持与努力付之东流,于是便把他们的核心技术开源,也就是docker,在当时的话,docker的主要功能就是把Linux的代码打包,应用在其他开发平台中。最后这个docker就风靡全球,于是乎,dotcloud就索性改名docker了,并且就全身心的投入到了docker的开发之中
  1. docker的应用场景
  • Web应用的自动化打包和发布

  • 自动化测试和持续继承、发布

  • 在服务型环境中部署和调试数据库或其他后台应用

  • 从头编译或者拓展现有的openshift或cloud foundry平台来搭建自己的PaaS环境。

  1. docker的优势
  • docker 启动快速属于秒级别。虚拟机通常需要几分钟去启动

  • docker 需要的资源更少, docker 在操作系统级别进行虚拟化, docker 容器和内核交互,几乎没有性能损耗,性能优于通过 Hypervisor 层与内核层的虚拟化

  • docker 更轻量, docker 的架构可以共用一个内核与共享应用程序库,所占内存极小。同样的硬件环境, Docker 运行的镜像数远多于虚拟机数量,对系统的利用率非常高

  • 与虚拟机相比, docker 隔离性更弱, docker 属于进程之间的隔离,虚拟机可实现系统级别隔

  • 安全性: docker 的安全性也更弱。 Docker 的租户 root 和宿主机 root 等同,一旦容器内的用户从普通用户权限提升为root权限,它就直接具备了宿主机的root权限,进而可进行无限制的操作。虚拟机租户 root 权限和宿主机的 root 虚拟机权限是分离的,并且虚拟机利用如 Intel 的 VT-d 和 VT-x 的 ring-1 硬件隔离技术,这种隔离技术可以防止虚拟机突破和彼此交互,而容器至今还没有任何形式的硬件隔离,这使得容器容易受到攻击

  • 可管理性: docker 的集中化管理工具还不算成熟。各种虚拟化技术都有成熟的管理工具,例如 VMware vCenter 提供完备的虚拟机管理能力

  • 高可用和可恢复性: docker 对业务的高可用支持是通过快速重新部署实现的。虚拟化具备负载均衡,高可用,容错,迁移和数据保护等经过生产实践检验的成熟保障机制, VMware 可承诺虚拟机 99.999% 高可用,保证业务连续性

  • 快速创建、删除:虚拟化创建是分钟级别的, Docker 容器创建是秒级别的, Docker 的快速迭代性,决定了无论是开发、测试、部署都可以节约大量时间

  • 交付、部署:虚拟机可以通过镜像实现环境交付的一致性,但镜像分发无法体系化。 Docker 在 Dockerfile 中记录了容器构建过程,可在集群中实现快速分发部署

dockers的三个基本概念

  1. image(镜像)

  2. container(容器)

  3. repository(仓库)

  4. image(镜像)

  • 镜像是docker运行的前提,仓库是存放镜像的地方,那么镜像就是核心了。

  • Docker 镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。

  • 我们简单来说一下,这个储存格式-联合文件系统,这是一个分层的问阿金系统,可以将不同的目录挂载到同一个虚拟文件下。那么我们docker的镜像就是使用的这样一个文件系统。

  • 下图就是镜像的存储格式,这张图是分层的,最下面一层,上面也是一层层的好像集装箱罗列在一起.这就是镜像最直观的存储方式.下面是操作系统的引导,上面是linux操作系统,再上面是一些相关的软件,如果是我们自己的程序,就可以是tomcat,jdk,再往上是应用代码,每一层是我们自己都可以控制得,最上面一层先忽略不看,因为这是和容器有关的.注意一点,docker镜像系统的每一层都是只读的,然后把每一层加载完成之后这些文件都会被看成是同一个目录,相当于只有一个文件系统.docker的这种文件系统被称之为镜像.

  1. container(容器)

    为了便于理解,大家可以把容器想象成虚拟机,每个虚拟机都有自己的文件系统,可以把图1整个一部分看成是文件系统,与虚拟机系统的区别是这里面的文件系统是一层一层的,并且最下面的n层都是只读的,只有上面一层是可写的.为什么要有可写的这层呢?大家的程序运行起来,势必会要写一些日志,写一些文件,或者对系统的某一些文件做一些修改,所以容器在最上面一层创建了可读可写的文件系统.

    在程序的运行过程中,如果要写镜像文件时,因为镜像的每一层都是只读的,它会把文件的每一层拷到文件的最上层,然后再对它进行修改,修改之后,当我们的应用读一个文件时会从顶层进行查找,如果没有才会找下一层.

    由于容器的最上一层是可以修改的,镜像是不能修改的,这样就能保证镜像可以生成多个容器独立运行,没有任何干扰.

    简要的概括就是:容器 = 镜像 + 读写层。

  2. repository(仓库)

  • Docker 仓库是集中存放镜像文件的场所。镜像构建完成后,可以很容易的在当前宿主上运行,但是, 如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry (仓库注册服务器)就是这样的服务。有时候会把仓库 (Repository) 和仓库注册服务器 (Registry) 混为一谈,并不严格区分。Docker 仓库的概念跟 Git 类似,注册服务器可以理解为 GitHub 这样的托管服务。实际上,一个 Docker Registry 中可以包含多个仓库 (Repository) ,每个仓库可以包含多个标签 (Tag),每个标签对应着一个镜像。所以说,镜像仓库是 Docker 用来集中存放镜像文件的地方类似于我们之前常用的代码仓库。

    通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签.。

仓库又可以分为两种形式:

  • public(公有仓库)

  • private(私有仓库)

  • Docker Registry 公有仓库是开放给用户使用、允许用户管理镜像的 Registry 服务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。

  • 除了使用公开服务外,用户还可以在本地搭建私有 Docker RegistryDocker 官方提供了 Docker Registry镜像,可以直接使用做为私有 Registry 服务。当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。

  • 我们主要把 Docker 的一些常见概念如 ImageContainerRepository 做了详细的阐述,也从传统虚拟化方式的角度阐述了 docker 的优势,我们从下图可以直观地看到 Docker 的架构: 1100338-20181011200344086-1510826338.png

  • Docker 使用 C/S 结构,即客户端/服务器体系结构。 Docker 客户端与 Docker 服务器进行交互,Docker服务端负责构建、运行和分发 Docker 镜像。 Docker 客户端和服务端可以运行在一台机器上,也可以通过 RESTfulstock 或网络接口与远程 Docker 服务端进行通信。

1100338-20181011200343656-1972949758.png

  • 这张图展示了 Docker 客户端、服务端和 Docker 仓库(即 Docker HubDocker Cloud ),默认情况下Docker 会在 Docker 中央仓库寻找镜像文件,这种利用仓库管理镜像的设计理念类似于 Git ,当然这个仓库是可以通过修改配置来指定的,甚至我们可以创建我们自己的私有仓库。

docker安装

1.下载关于Docker的依赖环境


yum -y install yum-utils device-mapper-persistent-data lvm2

2.设置下载Docker的镜像源


yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

3.安装Docker


yum makecache fast
yum -y install docker-ce

4.启动Docker,并设置为开机自动启动,测试

# 启动Docker服务
systemctl start docker
# 设置开机自动启动
systemctl enable docker
# 测试
docker run hello-world
  1. 查看刚才下载的hello-word镜像
docker images
卸载docker
  1. 删除依赖
yum remove docker-ce docker-ce-cli containerd.io
  1. 删除资源
rm -rf /var/lib/docker
rm -rf /var/lib/containerd
#  /var/lib/docker       docker工作的默认路径
阿里云镜像加速
  1. 登录阿里云

{abtn icon="fa-heart-o" color="#f86dc5" href="www.aliyun.com/" radius="17px" content="阿里云"/}

  1. 在弹性计算找到容器计算服务

image-20210720101445457.png

  1. 创建账号然后点击镜像工具里面的镜像加速

image-20210720101625198.png

  1. 配置使用
	sudo mkdir -p /etc/docker
	sudo tee /etc/docker/daemon.json <<-'EOF'
	{
	  "registry-mirrors": ["https://vjtmk5k2.mirror.aliyuncs.com"]
	}
	EOF
	sudo systemctl daemon-reload
	sudo systemctl restart docker
  1. 查看是否配置成功
 cat /etc/docker/daemon.json 
	/*返回如下
	{
	  "registry-mirrors": ["https://vjtmk5k2.mirror.aliyuncs.com"]
	}
	*/

运行过程

运行流程图.jpg

底层原理

docker是怎样工作做的?

  • Docker Engine是一个客户端-服务器应用程序,具有以下主要组件:

  • 一个服务器,它是一种长期运行的程序,称为守护进程(dockerd命令)。

  • 一个REST API,它指定程序可以用来与守护进程对话并指示它做什么的接口。

  • 命令行接口(CLI)客户端(docker命令)。

  • Docker是一个Client Server结构的系统,Docker守护进程运行在主机上,然后通过Socket连接从客户 端访问,守护进程从客户端接受命令并管理运行在主机上的容器。

底层运行图.png

docker为什么比VM快?

  1. Docker不需要Hypervisor实现硬件资源虚拟化,运行在Docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上Docker将会在效率上有明显优势。
  2. Docker利用的是宿主机的内核,而不需要GuestOS。因此,当新建一个容器时,Docker不需要和虚拟机一样重新加载一个操作系统内核。可避免引导寻址、加载操作系统内核返回这个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载GuestOS,返回新增过程是分钟级别的。而Docker由于利用宿主机的操作系统,则省略了返回的过程,因此新建一个Docker容器只需要几秒钟。

图.png

docker基本命令

4a707dadbe31eacd92cfe425c5d437b6.jpg

作者:酒笙

{music id="1486593195" color="#cf4abf" autoplay="autoplay"/}

帮助命令

docker version    #版本信息
docker info         #系统信息
docker 命令 --help    #帮助命令

帮助文档地址:docs.docker.com/engine/refe…

镜像命令

docker images 查看本机所有镜像

[root@jiusheng]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    d1165f221234   4 months ago   13.3kB

#REPOSITORY            镜像仓库源
#TAG                          镜像标签
#IMAGE ID                 镜像id
# CREATED                 镜像创建的时间
#SIZE                          镜像大小


#可选项

  -a , --all                   #列出所有镜像
  -q , --quiet              #显示镜像id


docker search 搜索镜像

# 官网搜索: https://hub.docker.com/
docker search 搜索名
#搜索MySQL镜像
docker search mysql

[root@jiusheng]# docker search mysql
NAME                              DESCRIPTION                                                           STARS     OFFICIAL    AUTOMATED
mysql                             MySQL is a widely used, open-source relation…       11147        [ OK]       
mariadb                           MariaDB Server is a high performing open sou…     4228        [OK]       

#条件搜索
 --filter=STARS=5000        #搜索出来的镜像就是STARS大于5000的
 
 [root@jisuheng]# docker search mysql --filter=STARS=5000
NAME      DESCRIPTION                                                        STARS     OFFICIAL   AUTOMATED
mysql     MySQL is a widely used, open-source relation…     11147     [OK]       

 
 

docker pull 下载镜像

#下载镜像 docker pull 镜像名[:tag]    下载指定版本

docker pull 镜像名    #默认下载最新版本

[root@jiusheng]# docker pull mysql
Using default tag: latest     #不填写指定版本,默认下载最新版本
latest: Pulling from library/mysql
b4d181a07f80: Pull complete                #分层下载,也就是 docker iamge核心,联合文件系统
b4d181a07f80: Pull complete               
a462b60610f5: Pull complete 
578fafb77ab8: Pull complete 
524046006037: Pull complete 
d0cbe54c8855: Pull complete 
aa18e05cc46d: Pull complete 
fd6f649b1d0a: Pull complete 
2a97d48c2fdc: Pull complete 
30f0c7db48fc: Pull complete 
f5dda8df049e: Pull complete 
671b83fd7448: Pull complete 
5d9cc55fa997: Pull complete 
Digest: sha256:18d8d109aa64673c78aebfb845b929cfdac97a553332f4310f4de8d67ceb03d2
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest
#真实地址等价于 docker pull mysql   =   docker pull  docker.io/library/mysql:latest




#下载指定版本
docker pull mysql:5.7
#具体有哪些版本可以去官网查看,不要乱写

[root@jiusheng]# docker pull mysql:5.7
5.7: Pulling from library/mysql
b4d181a07f80: Already exists      #这就是分层下载的好处,只下载不一样的。
a462b60610f5: Already exists 
578fafb77ab8: Already exists 
524046006037: Already exists 
d0cbe54c8855: Already exists 
aa18e05cc46d: Already exists 
fd6f649b1d0a: Already exists 
8a2b858b000b: Pull complete 
322182b17422: Pull complete 
070e28050a88: Pull complete 
613bdfd8796e: Pull complete 
Digest: sha256:956e11ac581cad9ac8747a9a1d61b8ffcfa6845e0f23bdbab6ba20a2ad792cbf   #这是一个签名
Status: Downloaded newer image for mysql:5.7        #版本
docker.io/library/mysql:5.7



docker rmi 删除镜像

docker rmi -f 镜像id     #删除指定镜像
docker rmi -f 镜像id,镜像id    #删除多个指定镜像
docker rmi -f $(docker images -aq)      #使用递归删除所有镜像

容器命令

有了镜像之后,才可以创建容器,容器依赖于镜像。

我们这里下载一个centos的镜像

docker pull centos

新建容器并启动

docker run [可选参数] images

#参数说明
 
--name="Name"   #容器名字,用于区分容器
-d			      #后台方式运行
-it			        #使用交互式运行,并进入容器查看内容
-p                          #指定容器端口
	-p ip : 主机端口 : 容器端口
	-p 主机端口 :容器端口 常用
	-p 容器端口
	
-P                        随机容器端口

测试,启动并进入容器

[root@jiusheng]# docker run -it centos /bin/bash
[root@2d13e5147554 /]# ls    #查看容器内的centos
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr
[root@2d13e5147554 /]# 

退出容器

exit        #停止容器并退出
Ctrl + p + q  #容器不停止退出

列出所有运行的容器

#docker ps (可选参数)
docekr ps      #列出正在运行的容器
docker ps -a #列出当前正在运行的容器和历史运行的容器
docker ps -n=?  #显示最近创建的容器,?是数字,表示显示几个
docker -p       #显示容器编号
#示例
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps -n=1
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS                     PORTS     NAMES
2d13e5147554   centos    "/bin/bash"   6 minutes ago   Exited (0) 4 minutes ago             heuristic_tu
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps -n=4
CONTAINER ID   IMAGE          COMMAND       CREATED         STATUS                     PORTS     NAMES
2d13e5147554   centos         "/bin/bash"   6 minutes ago   Exited (0) 4 minutes ago             heuristic_tu
ff7056f81cfe   d1165f221234   "/hello"      25 hours ago    Exited (0) 25 hours ago              nervous_kalam

删除容器

和前面删除镜像的方式一样,只是镜像是rmi而容器是rm,殊途同归

docker rm 容器id                               #删除指定容器,同时如果容器在运行,就不能删除
docker rm -f $(docker ps -aq)          #使用递归删除所有容器
docker ps -a -q |xargs docker rm    #删除所有容器,也可写作docker ps -aq|xargs docker rm

启动和停止容器

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

其他常用命令

后台启动容器

#docker run -d 镜像名
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker run -d centos
3c7893d0514ae66e0d31bc9efb725b98504467599376e494dcea47d629a13dbf
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@iZj6c5ctiawsbu90vbskdwZ ~]# 
#这里我们通过docker ps 发现容器停止了,那么是怎么一会事,我们说一说。

#docekr 容器在使用后台运行的时候,如果说没有一个前台进程,那么就会自动停止,也就是说,如果要使用后台运行,就必须要有一个前台进程!

查看日志

docker logs -f -t --tail  ?容器id   #?表示数字,即你要显示多少条日志,同时-f -t可以写在一起即-tf

docker logs -f t 容器id   #显示全部日志


显示容器进程信息

docker top 容器id
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker top 1ff8b6186c5f
UID                 PID                    PPID                C                   STIME               TTY                 TIME                CMD
root                22368               22349               0                   11:08               pts/0               00:00:00            /bin/bash


查看镜像元数据

docker inspect top 容器id
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
 CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS         PORTS     NAMES
1ff8b6186c5f   centos    "/bin/bash"   10 seconds ago   Up 9 seconds             inspiring_thompson
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker inspect 1ff8b6186c5f
[
    {
        "Id": "1ff8b6186c5f5d19b715a5c320b7ecb330f9e570e9bba2ff82bce2ceb7344262",
        "Created": "2021-07-21T03:08:39.027552726Z",
        "Path": "/bin/bash",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 22368,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2021-07-21T03:08:39.311797803Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
        "ResolvConfPath": "/var/lib/docker/containers/1ff8b6186c5f5d19b715a5c320b7ecb330f9e570e9bba2ff82bce2ceb7344262/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/1ff8b6186c5f5d19b715a5c320b7ecb330f9e570e9bba2ff82bce2ceb7344262/hostname",
        "HostsPath": "/var/lib/docker/containers/1ff8b6186c5f5d19b715a5c320b7ecb330f9e570e9bba2ff82bce2ceb7344262/hosts",
        "LogPath": "/var/lib/docker/containers/1ff8b6186c5f5d19b715a5c320b7ecb330f9e570e9bba2ff82bce2ceb7344262/1ff8b6186c5f5d19b715a5c320b7ecb330f9e570e9bba2ff82bce2ceb7344262-json.log",
        "Name": "/inspiring_thompson",
        "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/f374005ba37d8dd511a5663780d1a6d9f73721853d0f865f93fa06c294099b6e-init/diff:/var/lib/docker/overlay2/95fb52765b6ea97468e0c38889f47d9e3c95d2e69d556c18798f00ebb3e2cfb1/diff",
                "MergedDir": "/var/lib/docker/overlay2/f374005ba37d8dd511a5663780d1a6d9f73721853d0f865f93fa06c294099b6e/merged",
                "UpperDir": "/var/lib/docker/overlay2/f374005ba37d8dd511a5663780d1a6d9f73721853d0f865f93fa06c294099b6e/diff",
                "WorkDir": "/var/lib/docker/overlay2/f374005ba37d8dd511a5663780d1a6d9f73721853d0f865f93fa06c294099b6e/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "1ff8b6186c5f",
            "Domainname": "",
            "User": "",
            "AttachStdin": true,
            "AttachStdout": true,
            "AttachStderr": true,
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": true,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "Image": "centos",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20201204",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS"
            }
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "236a57971cd0b33ec1fd5b3c8cd725fabd85aef3a796de461a699c42b6e289f6",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/236a57971cd0",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "03ed818c13a101bd6254b5e5c18ede6f9c776efb2e65ac382f711b8f8b265b2b",
            "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": "3be7a57080be0d228e4f459c30ed8bc85ab61b84ac10ddbeaa546ad97f294539",
                    "EndpointID": "03ed818c13a101bd6254b5e5c18ede6f9c776efb2e65ac382f711b8f8b265b2b",
                    "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
                }
            }
        }
    }
]

进入当前正在运行的容器

我们通常都是通过后台方式运行,需要进入容器修改配置信息

#方式一
docker exec -it 容器id BashShell

[root@jiusheng]# docker exec -it  1ff8b6186c5f /bin/bash
[root@1ff8b6186c5f /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr

#方式二
docker attach 容器id

[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker attach 1ff8b6186c5f
[root@1ff8b6186c5f /]# 


#区别

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

从容器拷贝数据到本机

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

#进入容器内部
[root@1ff8b6186c5f /]# cd /home
[root@1ff8b6186c5f home]# ls
#在容器内部新建一个文件
[root@1ff8b6186c5f home]# touch jiusheng.np
[root@1ff8b6186c5f home]# exit
exit
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED       STATUS                      PORTS     NAMES
1ff8b6186c5f   centos    "/bin/bash"   3 hours ago   Exited (0) 16 seconds ago             inspiring_thompson
3c7893d0514a   centos    "/bin/bash"   3 hours ago   Exited (0) 3 hours ago                clever_lalande
#把文件拷贝到本机
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker cp 1ff8b6186c5f:/home/jiusheng.np /home
[root@iZj6c5ctiawsbu90vbskdwZ ~]# cd /home
[root@iZj6c5ctiawsbu90vbskdwZ home]# ls
admin  jiusheng.np

#我们可以卡看到哈,在容器里面建立的jiusheng.np,我们已经复制到了本机的home目录里面。

小结

f27d6a7d3f1f098f727223b8c7b16fe8.png

勤能补拙,温故而知新

docker命令导图.png

attach    Attach to a running container #当前 shell 下 attach 连接指定运行镜像
build      Build an image from a Dockerfile #通过 Dockerfile 定制镜像
commit  create a new image from a container changes #提交当前容器为新的镜像
cp          copy files/folders from the containers filesystem to the host path #从容器中拷贝指定文件或者目录到宿主机中
create    Create a new container #创建一个新的容器,同 run,但不启动容器
diff         Inspect changes on a container's filesystem #查看 docker 容器变化
events    Get real time events from the server #从docker 服务获取容器实时事件
exec       Run a command in an existing container #在已存在的容器上运行命令
export   Stream the contents of a container as a tar archive #导出容器的内容流作为一个 tar 归档文件[对应import ]
history  Show the history of an image #展示一个镜像形成历史
images  List images # 列出系统当前镜像
import  create a new filesystem image from the contents of a tarball #从tar包中的内容创建一个新的文件系统映像[对应export]
info       Display system-wide information # 显示系统相关信息
inspect  Return low-level information on a container #查看容器详细信息
kill         Kill a running container #kill 指定 docker 容器
load      Load an image from a tar archive # 从一个 tar 包中加载一个镜像[对应 save]
login     Register or Login to the docker registry server # 注册或者登陆一个 docker 源服务器
logout  Log out from a Docker registry server # 从当前 Docker registry 退出
logs      Fetch the logs of a container #输出当前容器日志信息
port      Lookup the public-facing port which is NAT-ed to PRIVATE_PORT #查看映射端口对应的容器内部源端
pause   pause all processes within a container #暂停容器
ps         List containers #列出容器列表
pull        the docker registry server #从docker镜像源服务器拉取指定镜像
push      Push an image or a repository to the docker registry server # 推送指定镜像或者库镜像至docker源服务器
restart    Restart a running container #重启运行的容器
rm           Remove one or more containers # 移除一个或者多个容器
rmi           Remove one or more images #移除一个或多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或 -f 强制删除]
run          Run a command in a new container #创建一个新的容器并运行一个命令
save       Save an image to a tar archive # 保存一个镜像为一个 tar 包[对应 load]
search    Search for an image on the Docker Hub #在 docker hub 中搜索镜像
start         Start a stopped containers # 启动容器
stop        Stop a running containers #停止容器
tag          Tag an image into a repository #给源中镜像打标签
top         Lookup the running processes of a container #查看容器中运行的进程信息
unpause    Unpause a paused container # 取消暂停容器
version    Show the docker version information #查看 docker 版本号
wait          Block until a container stops, then print its exit code #截取容器停止时的退出状态值

格式

# 1. 拉取镜像到本地
docker pull 镜像名称[:tag]
# 举个例子 tomcat
docker pull daocloud.io/library/tomcat:8.5.15-jre8

# 2. 查看全部本地的镜像
docker images

# 3. 删除本地镜像
docker rmi 镜像的标识

# 4. 镜像的导入导出(不规范)
# 将本地的镜像导出
docker save -o 导出的路径 镜像id
# 加载本地的镜像文件
docker load -i 镜像文件
# 修改镜像名称
docker tag 镜像id 新镜像名称:版本

# 1. 运行容器
# 简单操作
docker run 镜像的标识|镜像名称[tag]
# 常用的参数
docker run -d -p  宿主机端口:容器端口 --name 容器名称 镜像的标识|镜像名称[tag]
# -d: 代表后台运行容器
# -p: 宿主机端口:容器端口: 为了映射当前Linux的端口和容器的端口
# --name 容器名称: 指定容器的名称

# 2. 查看正在运行的容器
docker ps [OPTIONS]
# OPTIONS说明:
# -a: 代表查看全部的容器,包括没有运行
# -q: 只查看容器的标识
# -f: 根据条件过滤显示的内容
# --format: 指定返回值的模板文件
# -l: 显示最近创建的容器
# -n: 列出最近创建的n个容器
# --no-trunc: 不截断输出
# -s: 显示总的文件大小

# 3. 查看容器的日志
docker logs -f 容器id
# -f: 可以滚动查看日志的最后几行

# 4. 进入到容器内部
docker exec -it 容器id bash

# 5. 删除容器(删除容器前,需要先停止容器)
docker stop 容器id
# 停止指定的容器
docker stop $(docker ps -qa)
# 停止全部容器
docker rm 镜像id
# 删除指定容器
docker rm $(docker ps -qa)
# 删除全部容器

#6. 启动容器
docker start 容器id

作业练习

安装Nginx

  1. 安装nginx
docker search nginx
  1. 下载镜像
docker pull nginx
  1. 运行镜像
# -d 后台运行
# --name  给容器命名
# -p     端口映射,本机端口:容器内部端口

docker run -d --name jiusheng -p 520:80 nginx

#查看是否启动
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                 NAMES
82e88fd7529c   nginx     "/docker-entrypoint.…"   12 seconds ago   Up 10 seconds   0.0.0.0:520->80/tcp   jiusheng

#查看端口是否连通
[root@iZj6c5ctiawsbu90vbskdwZ ~]# curl localhost:520
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
  1. 进入容器
docker exec -it jiusheng /bin/bach
  1. 端口映射概念 ku14hfb9.png

安装tomcat

注意,在官网上的使用方法如下:

docker run -it --rm tomcat:9.0

这里我们不推荐,我们一般是使用后台启动,停止了容器后,还可以查找到, 但是docker run -it --rm ,使用之后就会直接删除,查找不到,也就是说是一个即用即删的,多用于测试!

  1. 搜索tomcat镜像
docker searce tomcat
  1. 下载tomcat
docker pull tomcat
  1. 启动运行
docker run -d -p 250:8080 --name tomcat01 tomcat
  1. 测试访问
curl localhost:250
访问ip:250
  1. 访问的通,没有出现想要的页面
#进入容器
docker exec -it tomcat01 /bin/bash
#发现少了命令,同时没有web。

#原因:默认最小安装,剔除了不必要的东西,保证最小化运行环境。

#解决方法
cp -r webapps.dist/* webapps

#之后就可以访问量

部署elasticsearch简称es+kibana

#官方命令
#--net somenetwork 网络配置
#"discovery.type=single-node"   集群配置,默认单节点
docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:tag
#我们做一些修改
docker run -d --name elasticsearch  -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e EC_JAVA_OPTS="=-Xms64m -Xm512m" elasticsearch:7.6.2
#去掉了网络服务
#改了名字
#增加了环境限制,别问,问就是这个非常耗内存,我的机子托不动,然后指定了版本号

docker run -d --name=es2 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m"  elasticsearch:7.6.2

  1. 查看容器占用内存
	docker stats 容器id
  1. 检查是否启动成功
	curl localhost:9200
	#参考
	[root@iZj6c5ctiawsbu90vbskdwZ ~]# curl localhost:9200
	{
	  "name" : "62ee34017bec",
	  "cluster_name" : "docker-cluster",
	  "cluster_uuid" : "3OGmDOBLSOOYOeQQ23F7dQ",
	  "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"
	}
	

部署可视化面板

Portainer

这里需要主要的是,我们安装ce版本即可,因为这是开源切免费的!

官网地址:

documentation.portainer.io/v2.0/deploy…

Portainer 服务器部署

docker volume create portainer_data

docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce


Portainer 仅代理部署

docker run -d -p 9001:9001 --name portainer_agent --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/docker/volumes:/var/lib/docker/volumes portainer/agent
#查看是否启动成功
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID   IMAGE             COMMAND     CREATED          STATUS          PORTS                    NAMES
8b100ad7b90f   portainer/agent   "./agent"   24 seconds ago   Up 23 seconds   0.0.0.0:9001->9001/tcp   portainer_agent

访问测试

这是一个登录界面,在这里我们需要建立管理员角色

l16bsnn6.png

创建成功之后,我们进入后台界面

l16btf1s.png

这样就完安装完成了,我们也不使用,就简单的了解就好了

镜像讲解

Docker镜像加载原理

镜像是什么

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

UnionFS(联合文件系统)

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

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

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 这里才 200M ?

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

分层理解

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

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

  • 最大的好处,我觉得莫过于是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。查看镜像分层的方式可以通过 docker image inspect 命令!

所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。 举一个简单的例子,假如基于 Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。该镜像当前已经包含 3 个镜像层,如下图所示(这只是一个用于演示的很简单的例子

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含 3 个文件,而镜像包含了来自两个镜像层的 6 个文件。

上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。 下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有 6 个文件,这是因为最上层中的文件7 是文件 5 的一个更新版本。

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。 Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。 Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顾名思义,每种存储引擎都基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。 Docker 在 Windows 上仅支持 windowsfilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和 CoW[1]。下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图

特点

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

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

commit

commit的作用相当于快照

提交镜像

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

测试

  1. 启动tomcat

    docker run -it  -p 432:8080 comcat
    
  2. 进入comcat

    docker exec -it 容器id /bin/bash
    
  3. 拷贝数据

    cp -r webapps.dist/* webapps
    
  4. 访问地址是否修改成功

    http://47.243.161.30:432/
    
  5. 退出容器并提交新的修改

    #退出容器
    exit
    
    #提交修改
    docker commit -a="jiusheng" -m="webapps" 0cee6cf8bd57 comcat02:1.1
    
  6. 查看是否生成成功

    docker images
    
    comcat02                 1.1       31ea9dda1fda   8 seconds ago   677MB
    portainer/portainer-ce   latest    865cf8021627   2 weeks ago     210MB
    portainer/agent          latest    3cdf856343c6   2 weeks ago     138MB
    nginx                    latest    4cdc5dd7eaad   2 weeks ago     133MB
    tomcat                   latest    36ef696ea43d   3 weeks ago     667MB
    centos                   latest    300e315adb2f   7 months ago    209MB
    kibana                   7.6.2     f70986bc5191   16 months ago   1.01GB
    elasticsearch            7.6.2     f29a1ee41030   16 months ago   791MB
    
    

容器数据卷

docker数据卷概念

Docker的理念是:将运用与运行的环境打包形成容器运行 ,运行可以伴随着容器。

Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了。

所以我们希望:数据可以持久化、容器之间(甚至容器与宿主机之间)可以数据共享。为了能保存数据可以在docker中使用卷。卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。

卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性:

  • 数据卷可在容器之间共享或重用数据
  • 卷中的更改可以直接生效
  • 数据卷中的更改不会包含在镜像的更新中
  • 数据卷的生命周期一直持续到没有容器使用它为止

为什么使用数据卷

​ Docker的镜像是由一系列的只读层组合而来,当启动一个容器的时候,Docker加载镜像的所有只读层,并在最上层加入一个读写层。这个设计使得Docker可以提高镜像构建、存储和分发的效率,节省了时间和存储空间,然而也存在如下问题。

容器中的文件在宿主机上存在形式复杂,不能在宿主机上很方便的对容器中的文件进行访问

  1. 多个容器之间的数据无法共享
  2. 当删除容器时,容器产生的数据将丢失

​ 为了解决这些问题,Docker引入了数据卷(volume)机制。volume是存在一个或多个容器中的特定文件或文件夹,这个目录能够独立于联合文件系统的形式在宿主机中存在,并为数据的共享与持久提供一下便利。

  1. volume在容器创建时就初始化,在容器运行时就可以使用其中的文件
  2. volume能在不同的容器之间共享和重用
  3. volume中的数据的操作会马上生效
  4. volume中数据操作不会影响到镜像本身
  5. volume的生存周期独立于容器的生存周期,即使删除容器,volume仍然会存在,没有任何容器使用的volume也不会被Docker删除

volume命令

了解volume的命令

  • 使用帮助文档查看命令
docker volume --help
  • 参数说明
  create       	   #创建卷
  inspect    	 #显示一个或多个数据卷的详细信息
  ls             	 #列出所有卷
  prune     	#删除所有未使用的数据卷
  rm           	    #删除一个或多个卷

  1. 创建一个数据卷

基本格式如下:

docker volume create 名字

docker volume create jiu

此时,数据卷默认会放到/var/lib/docker/volumes路径下,会发现所新建的数据卷位置,查看命令如下: ## 参数可以为数字“1”,字母L:大小写均可,但效果不一样 ls -1 /var/lib/docker/volumes

为什么会在这里,我们可以来看一下docker的文件目录:

docker的默认目录为/var/lib/docker/

里面的结构如下

├── containers #用来存储容器信息 ├── image #用来存储镜像中间件及本身信息,大小,依赖信息 │ └── overlay2 │ ├── distribution │ ├── imagedb │ │ ├── content │ │ │ └── sha256 │ │ └── metadata │ │ └── sha256 │ ├── layerdb │ └── repositories.json ├── network #网络信息 │ └── files │ └── local-kv.db ├── overlay2 #存放镜像 │ └── l ├── plugins │ ├── storage │ │ └── blobs │ │ └── tmp │ └── tmp ├── swarm ├── tmp #docker临时目录 ├── trust #docker信任目录 └── volumes #docker卷目录 └── metadata.db

  1. 列出所有数据卷
docker volume ls
  1. 查询数据卷信息

格式:

docker volume inspect 数据卷名

docker volume inspect jiu


[root@iZj6c5ctiawsbu90vbskdwZ docker]# docker volume inspect jiu
[
    {
        "CreatedAt": "2021-07-27T16:49:41+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/jiu/_data",   #存放位置
        "Name": "jiu",   #数据卷名
        "Options": {},
        "Scope": "local"
    }
]

  1. 删除一个数据卷

格式:

docker volume rm 数据卷名

docker volume rm jiu


[root@iZj6c5ctiawsbu90vbskdwZ docker]# docker volume ls
DRIVER    VOLUME NAME
local     jiu
[root@iZj6c5ctiawsbu90vbskdwZ docker]# docker volume rm jiu
jiu
[root@iZj6c5ctiawsbu90vbskdwZ docker]# docker volume ls
DRIVER    VOLUME NAME
#可以看到已经删除成功了
  1. 删除所有没有使用的数据卷

格式:

docker volume prune

docker volume prune


#这里我们提前创建了一些数据卷
[root@iZj6c5ctiawsbu90vbskdwZ docker]# docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
jiu
sheng
hahha
Total reclaimed space: 0B
#可以看到没有使用的数据均已经全部删除完毕了

数据卷的使用

数据卷目前有两种方式来进行使用,一种是直接通过命令来进行挂载,一种是通过DockerFile来进行添加

命令格式:

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

测试

  1. 启动并挂载数据卷
docker run -it -v /home/ceshi:/home centos /bin/bash
  1. 查看是否生成挂载目录测试,并成功挂载
[root@iZj6c5ctiawsbu90vbskdwZ /]# cd /home/
[root@iZj6c5ctiawsbu90vbskdwZ home]# ls
admin  ceshi
[root@iZj6c5ctiawsbu90vbskdwZ home]#


[root@iZj6c5ctiawsbu90vbskdwZ ceshi]# docker inspect 1795f7f64501
[
    {
        "Id": "1795f7f64501188c8e74a8f9f5b2fb8703a84f0d7b36606f3f98ce2c06b93f3f",
        "Created": "2021-07-27T09:33:28.066660046Z",
        "Path": "/bin/bash",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 8000,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2021-07-27T09:33:28.409923354Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
        "ResolvConfPath": "/var/lib/docker/containers/1795f7f64501188c8e74a8f9f5b2fb8703a84f0d7b36606f3f98ce2c06b93f3f/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/1795f7f64501188c8e74a8f9f5b2fb8703a84f0d7b36606f3f98ce2c06b93f3f/hostname",
        "HostsPath": "/var/lib/docker/containers/1795f7f64501188c8e74a8f9f5b2fb8703a84f0d7b36606f3f98ce2c06b93f3f/hosts",
        "LogPath": "/var/lib/docker/containers/1795f7f64501188c8e74a8f9f5b2fb8703a84f0d7b36606f3f98ce2c06b93f3f/1795f7f64501188c8e74a8f9f5b2fb8703a84f0d7b36606f3f98ce2c06b93f3f-json.log",
        "Name": "/gallant_sanderson",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": [
                "/home/ceshi:/home"            
            ],
            "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/9952b87bf9c7b7b84fbbdb2ac08fdc7ceb96b8cdf21c4f2d1d2f49bd8595ee1f-init/diff:/var/lib/docker/overlay2/95fb52765b6ea97468e0c38889f47d9e3c95d2e69d556c18798f00ebb3e2cfb1/diff",
                "MergedDir": "/var/lib/docker/overlay2/9952b87bf9c7b7b84fbbdb2ac08fdc7ceb96b8cdf21c4f2d1d2f49bd8595ee1f/merged",
                "UpperDir": "/var/lib/docker/overlay2/9952b87bf9c7b7b84fbbdb2ac08fdc7ceb96b8cdf21c4f2d1d2f49bd8595ee1f/diff",
                "WorkDir": "/var/lib/docker/overlay2/9952b87bf9c7b7b84fbbdb2ac08fdc7ceb96b8cdf21c4f2d1d2f49bd8595ee1f/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/home/ceshi",                   #我们可以看到这里是挂载上去了的,那我们接着来测试
                "Destination": "/home",                     #容器内的地址
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
        "Config": {
            "Hostname": "1795f7f64501",
            "Domainname": "",
            "User": "",
            "AttachStdin": true,
            "AttachStdout": true,
            "AttachStderr": true,
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": true,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "Image": "centos",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20201204",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS"
            }
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "c5803986c1107b2e97d534aab5c2725f355b7cef1c171afd8486f72d0b83a382",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/c5803986c110",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "f6f8cedcc0ad532f2c01910f84e3436c1c33ec8aa0d2e47236de75bde44c8384",
            "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": "3be7a57080be0d228e4f459c30ed8bc85ab61b84ac10ddbeaa546ad97f294539",
                    "EndpointID": "f6f8cedcc0ad532f2c01910f84e3436c1c33ec8aa0d2e47236de75bde44c8384",
                    "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
                }
            }
        }
    }
]

  1. 在本机添加文件
#生成一个jiusheng.666的文件
[root@iZj6c5ctiawsbu90vbskdwZ ceshi]# touch jiusheng.666
[root@iZj6c5ctiawsbu90vbskdwZ ceshi]# ls
jiusheng.666
  1. 到容器里面查看是否同步
#可以看到是已经同步的了
[root@1795f7f64501 /]# cd /home/
[root@1795f7f64501 home]# ls
jiusheng.666
  1. 在容器内删除文件
[root@1795f7f64501 home]# rm jiusheng.666 
rm: remove regular empty file 'jiusheng.666'? y
[root@1795f7f64501 home]# 
#这里我们在容器里面已经吧文件jiusheng.666删除掉了,我们去宿主机看看文件还在不在

[root@iZj6c5ctiawsbu90vbskdwZ ceshi]# ls
[root@iZj6c5ctiawsbu90vbskdwZ ceshi]# 
#可以看到是没有任何文件的,也就是说这里目录下的文件是双向绑定的,同时,你停止或者删除容器,里面的内容也是不会变得,出给你认为的去修改或者删除!

挂载之后的文件就是共享,同时不管你删除容器还是停止容器,映射出来的文件不会随之消失!

这里删除或者停止容器的测试就不在赘述了。

拓展

我们在实际使用的过程中,会发现有一些的命令会多一个ro 或者rw

这个是读取权限:

ro 只读

rw 可读可写

不设置的话,默认.rw

docker run -it -v /myDataVolume:/dataVolumeContainer:ro centos

-v			#代表数据卷
/myDataVolume				#宿主机绝对路径目录
:/dataVolumeContainer		#容器内目录
centos				#镜像名
:ro			#设置权限为只读

安装MySQL

  1. 下载mysql
docker pull mysql:5.6
  1. 运行容器并进行数据挂载
#这是官方给的方式,我们进行就该
#my-secret-pw -d   表示密码,进行修改
#-e 是环境变量
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
docker run -p 3306:3306 --name mymysql -v $PWD/conf:/etc/mysql/conf.d -v $PWD/logs:/logs -v $PWD/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7

参数解释:
-p 3306:3306:将容器的 3306 端口映射到主机的 3306 端口。
-v $PWD/conf:/etc/mysql/conf.d:将主机当前目录下的 conf/my.cnf 挂载到容器的 /etc/mysql/my.cnf。
-v $PWD/logs:/logs:将主机当前目录下的 logs 目录挂载到容器的 /logs。
-v $PWD/data:/var/lib/mysql :将主机当前目录下的data目录挂载到容器的 /var/lib/mysql 。
-e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码。


l16bv1ep.png

  1. 连接看测试 l16bvssf.png

可以看到连接成功,下面我们创建一个表来测试

l16bwlk0.png

这个时候我们来数据是否同步

l16bx8o4.png

  1. 我们停止掉原来的数据库,同时新开一个数据库
docker run -p 3307:3306 --name mysql01 -v $PWD/conf:/etc/mysql/conf.d -v $PWD/logs:/logs -v $PWD/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7

我们来进行连接

l16bxv20.png

我们之前创建的数据都还在

l16byho6.png

至此,我们可以很明确的知道,数据卷的使用,可以实现数据的持久化。不再一删除容器就什么都没有了!

具名和匿名挂载

什么是具名挂载和匿名挂载?

我们前面挂载数据卷的时候是通过 -v 主机路径:容器内路径 ,来进行挂载的,那么我们不指定主机的挂载路径只指定容器内路径,-v 容器内路径 那么这个就是匿名挂载, 反之如果我们吧主机路径变成别名,那么就是具名挂载在,比如: -v jiusheng:容器内路径

匿名挂载

  1. 使用匿名挂载启动nginx
docker run -d -P --name nginx01 -v /etc/nginx nginx

参数解读:
-P 随机端口
-v  匿名挂载会随机生成挂载路径
  1. 使用volume查看数据卷
docker volume ls


[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker volume ls
DRIVER              VOLUME NAME
local               0ba2accbb52f84f4ddd1b92995db0ce4e8adbb3f710595f26823f9f01f014c65
local               8f054507bd037b086e742d764f415df0fcbb08e7d1e71f3c83c1e112f7c28ca1
local               81e46324431241ff7b95a6cceb4b5dd85d9b9eefb03aa55d46f153b101a8502f
local               82a3da984765cbbdb73797cec9038650e035a2511a07479370587787fc331501
local               53050314ad0cf8d879280a1c1df3a587f497ae93315da31cc5d97ae7a0907f3c
local               bc56b1d4485fb0a171f5807204408a6257109311e37365bbfd79387afc940cb9
local               cb7e41c8d674d05d355c10b0a7101bf7569500b78c38d8f50ca6f87ed5c265d6
local               f4785b207baa99a0214b40816dcc51e265a5ea5a66e4f55a1ab1b6d286ab47f9

  1. 查看匿名挂载路径
docker volume inspect



[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker volume inspect f4785b207baa99a0214b40816dcc51e265a5ea5a66e4f55a1ab1b6d286ab47f9
[
    {
        "CreatedAt": "2021-07-29T08:56:05+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/f4785b207baa99a0214b40816dcc51e265a5ea5a66e4f55a1ab1b6d286ab47f9/_data",
        "Name": "f4785b207baa99a0214b40816dcc51e265a5ea5a66e4f55a1ab1b6d286ab47f9",
        "Options": null,
        "Scope": "local"
    }
]

具名挂载

  1. 使用具名挂载nginx
docker run -d -P --name nginx02 -v jumingguazai:/etc/nginx nginx
  1. 查看数据卷
docker volume ls

[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker volume ls
DRIVER              VOLUME NAME
local               jumingguazai

  1. 查看具名挂载地址
docker volume inspect jumingguazai

[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker volume inspect jumingguazai
[
    {
        "CreatedAt": "2021-07-29T10:46:44+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/jumingguazai/_data",
        "Name": "jumingguazai",
        "Options": null,
        "Scope": "local"
    }
]

我们可以看到,不管是匿名挂载还是具名挂载,默认的挂载目录地址都是在/var/lib/docker/volumes/xxx/_data

我们通过具名挂载可以方便的找到我们挂载的卷,所以大多数情况也就使用具名挂载

区分挂载类型

-v 容器内路径匿名挂载
-v 卷名:容器内路径具名挂载
-v /宿主机路径:容器内路径指定路径挂载 ,注意有/

dockerfile挂载数据卷

编写脚本

FROM centos
VOLUME ["jiusheng01","jiusheng02"]
CMD echo "-------jiushengzuishuai------"
CMD /bin/bash

基本格式

docker build -f 脚本名 -t 镜像名 .

创建一个自己的镜像

docker build -f dockerfile -t jiu/centos .
#我这是在创建的文件里面,所以没有写绝对路径,注意!
[root@iZj6c5ctiawsbu90vbskdwZ jiusheng]# docker build -f dockerfile -t jiu/centos .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos
latest: Pulling from library/centos
7a0437f04f83: Pull complete 
Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
Status: Downloaded newer image for centos:latest
 ---> 300e315adb2f
Step 2/4 : VOLUME ["jiusheng01","jiusheng02"]
 ---> Running in 493198964ebc
Removing intermediate container 493198964ebc
 ---> 708ee122fc35
Step 3/4 : CMD echo "-------jiushengzuishuai------"
 ---> Running in 4fa544e52a5d
Removing intermediate container 4fa544e52a5d
 ---> 1636e3ed06f7
Step 4/4 : CMD /bin/bash
 ---> Running in 8e41d980a363
Removing intermediate container 8e41d980a363
 ---> e812a670c034
Successfully built e812a670c034
Successfully tagged jiu/centos:latest

#我这里没有centos,所以多了一个下载

查看是否构建成功

docker images

[root@iZj6c5ctiawsbu90vbskdwZ jiusheng]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
jiu/centos          latest              e812a670c034        30 seconds ago      209MB
nginx               latest              08b152afcfae        6 days ago          133MB
mysql               5.7                 8cf625070931        6 days ago          448MB
centos              latest              300e315adb2f        7 months ago        209MB

运行镜像

docker run -it e812a670c034 /bin/bash


[root@85a2c18ffc33 /]# ls -l
total 56
lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x   5 root root  360 Jul 29 07:22 dev
drwxr-xr-x   1 root root 4096 Jul 29 07:22 etc
drwxr-xr-x   2 root root 4096 Nov  3  2020 home
drwxr-xr-x   2 root root 4096 Jul 29 07:22 jiusheng01
drwxr-xr-x   2 root root 4096 Jul 29 07:22 jiusheng02
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 Dec  4  2020 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 102 root root    0 Jul 29 07:22 proc
dr-xr-x---   2 root root 4096 Dec  4  2020 root
drwxr-xr-x  11 root root 4096 Dec  4  2020 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 Jul 29 01:08 sys
drwxrwxrwt   7 root root 4096 Dec  4  2020 tmp
drwxr-xr-x  12 root root 4096 Dec  4  2020 usr
drwxr-xr-x  20 root root 4096 Dec  4  2020 var

l16bzb80.png

查看挂载地址

docker inspect 85a2c18ffc33

        "Mounts": [
            {
                "Type": "volume",
                "Name": "d6f8d3df6d8bf7a8067a547550ecf24ec6d8e2217a6f66ec4b694175eca015e9",
                "Source": "/var/lib/docker/volumes/d6f8d3df6d8bf7a8067a547550ecf24ec6d8e2217a6f66ec4b694175eca015e9/_data",
                "Destination": "jiusheng02",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "29cbc761ed2c5cfad7360e0b30918f29011d2a6b4962f50a245501b25323380b",
                "Source": "/var/lib/docker/volumes/29cbc761ed2c5cfad7360e0b30918f29011d2a6b4962f50a245501b25323380b/_data",
                "Destination": "jiusheng01",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

#我们可以看到也是挂载到了对于的目录下,后面的操作就不在演示了

数据卷容器

定义:命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器

容器间的传递共享

docker run -it --name 子容器名 --volumes-from 父容器名 镜像名
  1. 启动一个子容器
docker run -it --name jiu01 --volumes-from 85a2c18ffc33 e812a670c034
#这里直接使用上面创建的容器为父容器,估不再新建,直接创建子容器
  1. 在子容器里面创建一个文件
[root@3f816b8ff216 /]# cd jiusheng01
[root@3f816b8ff216 jiusheng01]# touch jiushengya.txt
  1. 到父容器里面查看
[root@85a2c18ffc33 /]# cd jiusheng01
[root@85a2c18ffc33 jiusheng01]# ls
jiushengya.txt
#数据同步共享

所有子容器数据与父容器以及父容器的其它子容器同步,同时删除容器不会删除数据,父容器停止或者删除,不会影响子容器

DocKerFile

dockerfile概念

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

构建步骤

  1. 编写一个dockerfile文件
  2. 使用doicker build 构建一个镜像
  3. 使用docker run 运行镜像
  4. 使用docker push 发布一个镜像

Dockerfile优点

  • 易于版本化管理,Dockerfile 本身是一个文本文件,方便存放在代码仓库做版本管理,可以很方便地找到各个版本之间的变更历史
  • 过程可追溯,Dockerfile 的每一行指令代表一个镜像层,根据 Dockerfile 的内容即可很明确地查看镜像的完整构建过程
  • 屏蔽构建环境异构,使用 Dockerfile 构建镜像无须考虑构建环境,基于相同 Dockerfile 无论在哪里运行,构建结果都一致

Dockerfile构建过程解析

基础

  • 每条指令都必须大写字母,后面跟随至少一个参数

  • 指令从上到下按序执行

  • #表示注释

  • 每条指令都会创建一个镜像层,并对镜像进行提交

Dockerfile 书写原则

  1. 单一原则
  • 由于容器的本质是进程,一个容器代表一个进程,因此不同功能的应用应该尽量拆分为不同的容器,每个容器只负责单一业务进程。
  1. 注释信息
  • Dockerfile 也是一种代码,我们应该保持良好的代码编写习惯,晦涩难懂的代码尽量添加注释,让协作者可以一目了然地知道每一行代码的作用,并且方便扩展和使用。
  1. 保持容器最小化
  • 应该避免安装无用的软件包,比如在一个 nginx 镜像中,我并不需要安装 vim 、gcc 等开发编译工具。这样不仅可以加快容器构建速度,而且可以避免镜像体积过大。
  1. 合理选择基础镜像
  • 容器的核心是应用,因此只要基础镜像能够满足应用的运行环境即可。例如一个Java类型的应用运行时只需要JRE,并不需要JDK,因此我们的基础镜像只需要安装JRE环境即可。
  1. 使用 .dockerignore 文件
  • 在使用git时,我们可以使用.gitignore文件忽略一些不需要做版本管理的文件。同理,使用.dockerignore文件允许我们在构建时,忽略一些不需要参与构建的文件,从而提升构建效率。.dockerignore的定义类似于.gitignore。
  1. 尽量使用构建缓存
  • Docker 构建过程中,每一条 Dockerfile 指令都会提交为一个镜像层,下一条指令都是基于上一条指令构建的。如果构建时发现要构建的镜像层的父镜像层已经存在,并且下一条命令使用了相同的指令,即可命中构建缓存。

    Docker 构建时判断是否需要使用缓存的规则如下:

  • 从当前构建层开始,比较所有的子镜像,检查所有的构建指令是否与当前完全一致,如果不一致,则不使用缓存;

  • 一般情况下,只需要比较构建指令即可判断是否需要使用缓存,但是有些指令除外(例如ADD和COPY)。

  • 对于ADD和COPY指令不仅要校验命令是否一致,还要为即将拷贝到容器的文件计算校验和(根据文件内容计算出的一个数值,如果两个文件计算的数值一致,表示两个文件内容一致 ),命令和校验和完全一致,才认为命中缓存。

  • 因此,基于 Docker 构建时的缓存特性,我们可以把不轻易改变的指令放到 Dockerfile 前面(例如安装软件包),而可能经常发生改变的指令放在 Dockerfile 末尾(例如编译应用程序)。

  1. 正确设置时区
  • 我们从 Docker Hub 拉取的官方操作系统镜像大多数都是 UTC 时间(世界标准时间)。如果你想要在容器中使用中国区标准时间(东八区),请根据使用的操作系统修改相应的时区信息

    #Dockerfile 几种常用操作系统的修改方式:
    #Ubuntu 和Debian 系统
    
    RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    RUN echo "Asia/Shanghai" >> /etc/timezone
    
    #CentOS系统
    RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    
  1. 使用国内软件源加快镜像构建速度
  • 由于我们常用的官方操作系统镜像基本都是国外的,软件服务器大部分也在国外,所以我们构建镜像的时候想要安装一些软件包可能会非常慢。
  1. 最小化镜像层数
  • 在构建镜像时尽可能地减少 Dockerfile 指令行数。例如我们要在 CentOS 系统中安装make和net-tools两个软件包,应该在 Dockerfile 中使用以下指令:

  •   RUN yum install -y make net-tools
    
  • 而不应该写成这样:

  •   RUN yum install -y make
      RUN yum install -y net-tools
    

dockerfile指令

所有的关键字都必须是大写,同时第一行不能是注释,必须是FROM

#表示注释

1.FROM : 基础镜像 2.MANTAINER:镜像维护作者名和邮箱 3.RUN:容器构建需要的命令 4.EXPOSE:暴露端口 5.WORKDIR:登录后默认的工作目录 6.ENV:构建镜像过程中设置的环境变量 7.ADD:将宿主机目录下的文件拷贝进镜像并且会自动处理url和解压tar压缩包 8.COPY:将从构建上下文目录中(源路径)的文件/目录复制到新的一层的镜像内的(目标路径)位置 9.VOLUME:容器数据卷 10.CMD:指定容器启动时需要运行的命令,dockerFile中可以有多个cmd指令,但只有最后一个生效,cmd会被docker run之后的参数替换 11.ENTRYPOINT:指定一个容器启动时要运行的命令,可以有多条,都会生效 12.ONBUILD:当构建一个被继承的dockerFile时的运行命令,父镜像在被子镜像继承后,父镜像的onbuild被触发

实战测试

官方配置

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

FROM scratch    指定镜像
ADD centos-7-x86_64-docker.tar.xz /   #cenos7压缩包

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"]

创建一个自己的镜像

#进入home目录
cd home/
#创建DocKerFile文件
mkdir DocKerFile
#进入dockerfile
cd DocKerFile/
#随便创建一个文件名,写脚本
vim mycenos


#写入如下信息
FROM centos   
#指定镜像

MAINTAINER jiusheng<2936688581@qq.com>      #作者信息

ENV MYPATH /usr/local    #工作目录

WORKDIR $MYPATH

RUN yum -y install vim net-tools    #下载vim 和net-tools

EXPOSE 80    #暴露端口

CMD echo $MYPATH
CMD echo "-----jiusheng--"       #输出信息

CMD /bin/bash              

运行命令,构建镜像

基本格式:

注意,后面是有一个 .

docker build -f 文件路径 -t 镜像名:[tag] .

[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker build -f mycenos -t jiu_centos .
Sending build context to Docker daemon  2.048kB
Step 1/9 : FROM centos
 ---> 300e315adb2f
Step 2/9 : MAINTAINER jiusheng<2936688581@qq.com>
 ---> Running in 591cbf9c38f9
Removing intermediate container 591cbf9c38f9
 ---> cbdb558b172f
Step 3/9 : ENV MYPATH /usr/local
 ---> Running in f9c692dbac96
Removing intermediate container f9c692dbac96
 ---> 51316b596261
Step 4/9 : WORKDIR $MYPATH
 ---> Running in 3d4f6d2f173d
Removing intermediate container 3d4f6d2f173d
 ---> 51338bb008c2
Step 5/9 : RUN yum -y install vim net-tools
 ---> Running in cf3421730130
CentOS Linux 8 - AppStream                      6.8 MB/s | 8.3 MB     00:01    
CentOS Linux 8 - BaseOS                         4.9 MB/s | 4.5 MB     00:00    
CentOS Linux 8 - Extras                          22 kB/s | 9.8 kB     00:00    
Dependencies resolved.
================================================================================
 Package            Arch       Version                      Repository     Size
================================================================================
Installing:
 net-tools          x86_64     2.0-0.52.20160912git.el8     baseos        322 k
 vim-enhanced       x86_64     2:8.0.1763-15.el8            appstream     1.4 M
Installing dependencies:
 gpm-libs           x86_64     1.20.7-17.el8                appstream      39 k
 vim-common         x86_64     2:8.0.1763-15.el8            appstream     6.3 M
 vim-filesystem     noarch     2:8.0.1763-15.el8            appstream      48 k
 which              x86_64     2.21-12.el8                  baseos         49 k

Transaction Summary
================================================================================
Install  6 Packages

Total download size: 8.1 M
Installed size: 31 M
Downloading Packages:
(1/6): gpm-libs-1.20.7-17.el8.x86_64.rpm        395 kB/s |  39 kB     00:00    
(2/6): vim-enhanced-8.0.1763-15.el8.x86_64.rpm   13 MB/s | 1.4 MB     00:00    
(3/6): vim-filesystem-8.0.1763-15.el8.noarch.rp 909 kB/s |  48 kB     00:00    
(4/6): which-2.21-12.el8.x86_64.rpm             2.3 MB/s |  49 kB     00:00    
(5/6): vim-common-8.0.1763-15.el8.x86_64.rpm     30 MB/s | 6.3 MB     00:00    
(6/6): net-tools-2.0-0.52.20160912git.el8.x86_6 2.9 MB/s | 322 kB     00:00    
--------------------------------------------------------------------------------
Total                                           7.4 MB/s | 8.1 MB     00:01     
warning: /var/cache/dnf/appstream-02e86d1c976ab532/packages/gpm-libs-1.20.7-17.el8.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 8483c65d: NOKEY
CentOS Linux 8 - AppStream                      1.4 MB/s | 1.6 kB     00:00    
Importing GPG key 0x8483C65D:
 Userid     : "CentOS (CentOS Official Signing Key) <security@centos.org>"
 Fingerprint: 99DB 70FA E1D7 CE22 7FB6 4882 05B5 55B3 8483 C65D
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
Key imported successfully
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                        1/1 
  Installing       : which-2.21-12.el8.x86_64                               1/6 
  Installing       : vim-filesystem-2:8.0.1763-15.el8.noarch                2/6 
  Installing       : vim-common-2:8.0.1763-15.el8.x86_64                    3/6 
  Installing       : gpm-libs-1.20.7-17.el8.x86_64                          4/6 
  Running scriptlet: gpm-libs-1.20.7-17.el8.x86_64                          4/6 
  Installing       : vim-enhanced-2:8.0.1763-15.el8.x86_64                  5/6 
  Installing       : net-tools-2.0-0.52.20160912git.el8.x86_64              6/6 
  Running scriptlet: net-tools-2.0-0.52.20160912git.el8.x86_64              6/6 
  Running scriptlet: vim-common-2:8.0.1763-15.el8.x86_64                    6/6 
  Verifying        : gpm-libs-1.20.7-17.el8.x86_64                          1/6 
  Verifying        : vim-common-2:8.0.1763-15.el8.x86_64                    2/6 
  Verifying        : vim-enhanced-2:8.0.1763-15.el8.x86_64                  3/6 
  Verifying        : vim-filesystem-2:8.0.1763-15.el8.noarch                4/6 
  Verifying        : net-tools-2.0-0.52.20160912git.el8.x86_64              5/6 
  Verifying        : which-2.21-12.el8.x86_64                               6/6 

Installed:
  gpm-libs-1.20.7-17.el8.x86_64                                                 
  net-tools-2.0-0.52.20160912git.el8.x86_64                                     
  vim-common-2:8.0.1763-15.el8.x86_64                                           
  vim-enhanced-2:8.0.1763-15.el8.x86_64                                         
  vim-filesystem-2:8.0.1763-15.el8.noarch                                       
  which-2.21-12.el8.x86_64                                                      

Complete!
Removing intermediate container cf3421730130
 ---> 96c4435f5f36
Step 6/9 : EXPOSE 80
 ---> Running in a5363e9470cd
Removing intermediate container a5363e9470cd
 ---> ee1bd76b09e4
Step 7/9 : CMD echo $MYPATH
 ---> Running in 110b43851555
Removing intermediate container 110b43851555
 ---> bcb634848307
Step 8/9 : CMD echo "-----jiusheng--"
 ---> Running in e8acecac7db8
Removing intermediate container e8acecac7db8
 ---> 700270977443
Step 9/9 : CMD /bin/bash
 ---> Running in 5df30afb5f3f
Removing intermediate container 5df30afb5f3f
 ---> aeeaf736a24e
Successfully built aeeaf736a24e
Successfully tagged jiu_centos:latest

查看是否构建成功

[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
jiu_centos          latest              aeeaf736a24e        13 minutes ago      275MB
nginx               latest              08b152afcfae        9 days ago          133MB
mysql               5.7                 8cf625070931        9 days ago          448MB
centos              latest              300e315adb2f        7 months ago        209MB

测试运行

docker run -it jiu_centos

[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker run -it jiu_centos
#查看工作目录
[root@c2538f1711ea local]# pwd
/usr/local
#是我们设定的工作目录

#检测功能是否能用
[root@c2538f1711ea local]# 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 8  bytes 656 (656.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

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

[root@c2538f1711ea local]# vim jiu

[1]+  Stopped                 vim jiu

#完全能用,构建成功

列出本地镜像的变更历史

docker history 镜像名


[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker history jiu_centos
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
aeeaf736a24e        26 minutes ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin…   0B                  
700270977443        26 minutes ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B                  
bcb634848307        26 minutes ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B                  
ee1bd76b09e4        26 minutes ago      /bin/sh -c #(nop)  EXPOSE 80                    0B                  
96c4435f5f36        26 minutes ago      /bin/sh -c yum -y install vim net-tools         66MB                
51338bb008c2        27 minutes ago      /bin/sh -c #(nop) WORKDIR /usr/local            0B                  
51316b596261        27 minutes ago      /bin/sh -c #(nop)  ENV MYPATH=/usr/local        0B                  
cbdb558b172f        27 minutes ago      /bin/sh -c #(nop)  MAINTAINER jiusheng<29366…   0B                  
300e315adb2f        7 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           7 months ago        /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B                  
<missing>           7 months ago        /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7…   209MB        

CMD 和 ENTRYPOINT 区别

测试CMD

# 编写dockerfile文件
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# vim ceshi
FROM centos
CMD ["ls","-a"]
 
 
# 构建镜像
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker build -f ceshi -t ceshiya .
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM centos
 ---> 300e315adb2f
Step 2/2 : CMD ["ls","-a"]
 ---> Running in f4f284cd463d
Removing intermediate container f4f284cd463d
 ---> c9afee7729d7
Successfully built c9afee7729d7
Successfully tagged ceshiya:latest
 
 
# run 运行 发现我们的 ls -a 命令生效
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker run ceshiya
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

 
 
# 想追加一个命令 -l	ls -al 
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker run ceshiya -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
 
 
# cmd 的情况下 -l 替换了 CMD ["ls","-a"] 命令 -l 不是命令 所以报错

测试ENTRYPOINT

# 编写dockerfile文件
[root@root dockerfile]# vi ceshi01

FROM centos
ENTRYPOINT ["ls","-a"]

 
# 构建镜像
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker build -f ceshi01 -t ceshiya01 .
Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM centos
 ---> 300e315adb2f
Step 2/2 : ENTRYPOINT ["ls","-a"]
 ---> Running in 5490b3031487
Removing intermediate container 5490b3031487
 ---> 6102c6aeb29c
Successfully built 6102c6aeb29c
Successfully tagged ceshiya01:latest

 
 
# run 运行 发现我们的 ls -a 命令生效
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker run ceshiya01
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

 
 
# 想追加一个命令 -l	ls -al 发现生效 
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker run ceshiya01 -l
total 56
drwxr-xr-x   1 root root 4096 Aug  1 03:02 .
drwxr-xr-x   1 root root 4096 Aug  1 03:02 ..
-rwxr-xr-x   1 root root    0 Aug  1 03:02 .dockerenv
lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x   5 root root  340 Aug  1 03:02 dev
drwxr-xr-x   1 root root 4096 Aug  1 03:02 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 Dec  4  2020 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 109 root root    0 Aug  1 03:02 proc
dr-xr-x---   2 root root 4096 Dec  4  2020 root
drwxr-xr-x  11 root root 4096 Dec  4  2020 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 Jul 29 01:08 sys
drwxrwxrwt   7 root root 4096 Dec  4  2020 tmp
drwxr-xr-x  12 root root 4096 Dec  4  2020 usr
drwxr-xr-x  20 root root 4096 Dec  4  2020 var

发布镜像

发布到官方 docker hub 上

官网

需要注册账号!

查看登录命令

[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker login --help

Usage:	docker login [OPTIONS] [SERVER]

Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.

Options:
  -p, --password string   Password
      --password-stdin    Take the password from stdin
  -u, --username string   Username
[root@iZj6c5ctiawsbu90vbskdwZ ~]# 

登录账号

[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker login -u jiusheng
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
#这样就算成功了
Login Succeeded
[root@iZj6c5ctiawsbu90vbskdwZ ~]# 

提交镜像

docker push 信息/镜像:版本号

docker push jiusheng/centos:1.0

发布到阿里云

  1. 登录阿里云

  2. 找到容器镜像服务

l16c0n8m.png

  1. 点击个人实例

l16c19tz.png

  1. 点击创建镜像仓库

l16c1wml.png

  1. 点击本地仓库创建

l16c2om8.png

  1. 查看阿里云帮助文档

l16c3dr5.png

docker网络

初识docker0

  1. 这是我们没有安装docker时候的网络
[root@iZj6c5ctiawsbu90vbskdwZ ~]# ip a
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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:16:3e:01:9e:7a brd ff:ff:ff:ff:ff:ff
    inet 172.21.27.152/18 brd 172.21.63.255 scope global dynamic eth0
       valid_lft 315359962sec preferred_lft 315359962sec
  1. 我们安装好docker之后会发现多了一个docker0
[root@iZj6c5ctiawsbu90vbskdwZ ~]# ip a
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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:16:3e:01:9e:7a brd ff:ff:ff:ff:ff:ff
    inet 172.21.27.152/18 brd 172.21.63.255 scope global dynamic eth0
       valid_lft 315359848sec preferred_lft 315359848sec
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:4c:03:0f:26 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
  1. 安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络)、 none 、host

l16c483a.png

  1. docker network 指令了解
[root@iZj6c5ctiawsbu90vbskdwZ ~]# 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.


  1. 验证一下docker0默认网络
#启动一个容器
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker run -d -P --name tomcat01 tomcat
Unable to find image 'tomcat:latest' locally
latest: Pulling from library/tomcat
627b765e08d1: Pull complete 
c040670e5e55: Pull complete 
073a180f4992: Pull complete 
bf76209566d0: Pull complete 
f10db7ba7580: Pull complete 
5b2f970878fa: Pull complete 
ed434bfebf18: Pull complete 
f6c437110aa9: Pull complete 
a772951f83db: Pull complete 
752225c3768e: Pull complete 
Digest: sha256:6e40250d8fac4eca05c2067cb81f79427e4ddbaf4e78d5ecd21c35e8c5f2bfcf
Status: Downloaded newer image for tomcat:latest
6017ba277147c0b023ee2aa475108a4f8b88e8f7d182180308fc60ff0f41c714


#查看网络

[root@iZj6c5ctiawsbu90vbskdwZ ~]# ip a
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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:16:3e:01:9e:7a brd ff:ff:ff:ff:ff:ff
    inet 172.21.27.152/18 brd 172.21.63.255 scope global dynamic eth0
       valid_lft 315358148sec preferred_lft 315358148sec
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:4c:03:0f:26 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
7: veth961d52c@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether b2:82:8d:b4:75:6b brd ff:ff:ff:ff:ff:ff link-netnsid 0

#查看容器里面的网络

root@6017ba277147:/usr/local/tomcat# ip a
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
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

#我们可以看到容器内有一个eth0@if7的网络,同时可以发现eth0@if7和veth961d52c@if6是相互绑定的,也是成对出现的。


#查看能否ping通容器

[root@iZj6c5ctiawsbu90vbskdwZ ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.095 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.078 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.041 ms

#发现可以ping通


原理

我们每启动一个容器,docker就会给我们的容器分配一个ip,docker使用的是桥接模式,使用的技术evth-pair技术

同时ip是成对出现的

evth-pair起到一个连接的桥梁,一般用来连接虚拟网络设备

  1. 在启动一个容器
#查看网卡

[root@iZj6c5ctiawsbu90vbskdwZ ~]# 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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:16:3e:01:9e:7a brd ff:ff:ff:ff:ff:ff
    inet 172.21.27.152/18 brd 172.21.63.255 scope global dynamic eth0
       valid_lft 315357189sec preferred_lft 315357189sec
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:4c:03:0f:26 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
7: veth961d52c@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether b2:82:8d:b4:75:6b brd ff:ff:ff:ff:ff:ff link-netnsid 0
9: veth3880b7f@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether b6:23:87:6f:bc:ef brd ff:ff:ff:ff:ff:ff link-netnsid 1
#可以看到有多了一对
  1. 容器ping容器
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat02 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.082 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.055 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.050 ms

#我们可以看到,是可以相互ping通的

网络图 l16c4xzs.png

--link

不推荐使用,只做了解

不通过ip来访问容器,直接通过容器名访问

  1. 容器和容器进行ping
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat01 ping tomcat02
ping: tomcat02: Name or service not known

  1. 使用--link
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673
  1. 查看是否可以ping通
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.074 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.055 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.058 ms
#发现可以通过容器名ping通
  1. 反向是否可以ping通
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
#发现是ping不同的,应为没有配置
  1. 查看网络信息
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
f4e21fcb0d76   bridge    bridge    local
3c7452c40eb3   host      host      local
a122752ffd10   none      null      local
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker network inspect f4e21fcb0d76
[
    {
        "Name": "bridge",
        "Id": "f4e21fcb0d76f6a60dd870d02ed9604686240449350685f8100a9525fc564be1",
        "Created": "2021-08-01T16:00:00.258764824+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16"           #docker0
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "21b9e1bdfe0988f74199afb82805e502cfda94fccc8e269728c98b54f26637de": {
                "Name": "tomcat02",
                "EndpointID": "bd4419e2ca78725ddae30f95adc0d523680ff16c95960971d8fbaa823b531f1d",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673": {
                "Name": "tomcat03",
                "EndpointID": "070b04e67e1dfbdeb5039b9db6d61e1ee0989953467b4edd9cc0641adbbab21f",
                "MacAddress": "02:42:ac:11:00:04",
                "IPv4Address": "172.17.0.4/16",
                "IPv6Address": ""
            },
            "6017ba277147c0b023ee2aa475108a4f8b88e8f7d182180308fc60ff0f41c714": {
                "Name": "tomcat01",
                "EndpointID": "717371bbe0ff45dd69480cd95bc1bfb41c0a02b10fef0df3a11fe46b2bf6cbe6",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]


#查看tomcat03
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker inspect 4438f44dd6ff
[
    {
        "Id": "4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673",
        "Created": "2021-08-01T09:41:06.910147871Z",
        "Path": "catalina.sh",
        "Args": [
            "run"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 13874,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2021-08-01T09:41:07.368939358Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:46cfbf1293b176161813fa05bb8f7e82df1ec7def5c226c48bc48a60ed305ac7",
        "ResolvConfPath": "/var/lib/docker/containers/4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673/hostname",
        "HostsPath": "/var/lib/docker/containers/4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673/hosts",
        "LogPath": "/var/lib/docker/containers/4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673/4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673-json.log",
        "Name": "/tomcat03",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": [
            "e2d063fb5a968904b5e3ec6def704cc3790f9b1efcd9ce7c0240a939383ee549"
        ],
        "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": [
                "/tomcat02:/tomcat03/tomcat02"               #这里可以发现tomcat03里面的配置出现了tomcat02
            ],
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": true,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],


#进入Tomcat03查看

[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.3	tomcat02 21b9e1bdfe09
172.17.0.4	4438f44dd6ff


#我们可以发现,这里直接就绑定了Tomcat02

自定义网络

容器互联

  1. 创建一个jiusheng网络
#删除之前的所有容器
docker rm -f $(docker ps -aq)

#创建网络
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 jiusheng
db61398754c4de6d331db1788071e11ad9fa5883167cba1f0bf021bf671527c8

[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker network ls
NETWORK ID     NAME       DRIVER    SCOPE
f4e21fcb0d76   bridge     bridge    local
3c7452c40eb3   host       host      local
db61398754c4   jiusheng   bridge    local
a122752ffd10   none       null      local
  1. 查看创建网络信息
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker network inspect db61398754c4
[
    {
        "Name": "jiusheng",
        "Id": "db61398754c4de6d331db1788071e11ad9fa5883167cba1f0bf021bf671527c8",
        "Created": "2021-08-01T17:58:35.111862913+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

  1. 使用jiushneg网络
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker run -d -P --name tomcat02 --net jiusheng tomcat
1a04efb744627d546dbb8e22ed162062c56718b24836a45ee28d5f33af83f994
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker run -d -P --name tomcat01 --net jiusheng tomcat
ecccd3d1869c3d95d6e28787765bf26eea01866bf317b4ea3fe01f8549fea281
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED          STATUS          PORTS                     NAMES
ecccd3d1869c   tomcat    "catalina.sh run"   4 seconds ago    Up 3 seconds    0.0.0.0:49160->8080/tcp   tomcat01
1a04efb74462   tomcat    "catalina.sh run"   12 seconds ago   Up 12 seconds   0.0.0.0:49159->8080/tcp   tomcat02

  1. 容器互相ping
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat01 ping tomcat02
PING tomcat02 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat02.jiusheng (192.168.0.2): icmp_seq=1 ttl=64 time=0.061 ms
64 bytes from tomcat02.jiusheng (192.168.0.2): icmp_seq=2 ttl=64 time=0.051 ms
64 bytes from tomcat02.jiusheng (192.168.0.2): icmp_seq=3 ttl=64 time=0.063 ms
#发现可以直接ping通

自定义网络好处

  1. 不同集群的网络是相对的
  2. 让容器的网络基于dns的域名解析
  3. 拥有与宿主机之间安全的隔离环境
  4. 自由的选择或放弃一个网络

不同网络之间的连通

  1. 创建两个不通网络的容器
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker run -d -P --name tomcat01 --net jiusheng tomcat
76ab3aba3e19257a29e6b4702a9145d7da4f59150e63de4af865cec4d8f94dfa
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker run -d -P --name tomcat02  tomcat
8ad64e755f65f210eac46fd61c4ea2251810f4307b5d84e8aa67f764b30db50b
  1. 查看是否运行
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED          STATUS          PORTS                     NAMES
8ad64e755f65   tomcat    "catalina.sh run"   6 seconds ago    Up 5 seconds    0.0.0.0:49162->8080/tcp   tomcat02
76ab3aba3e19   tomcat    "catalina.sh run"   16 seconds ago   Up 15 seconds   0.0.0.0:49161->8080/tcp   tomcat01

  1. 把tomcat加入jiusheng网络
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker network connect jiusheng tomcat02
  1. 查看jiusheng网络
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker network inspect jiusheng
[
    {
        "Name": "jiusheng",
        "Id": "db61398754c4de6d331db1788071e11ad9fa5883167cba1f0bf021bf671527c8",
        "Created": "2021-08-01T17:58:35.111862913+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "76ab3aba3e19257a29e6b4702a9145d7da4f59150e63de4af865cec4d8f94dfa": {
                "Name": "tomcat01",
                "EndpointID": "dd654b8cb571b23e2fa206b08097bf35ea4ea901b420b8cfd2309bda48f18b06",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            },
            
            #我们可以看到,这里直接就把tomcat02加入了进来
            "8ad64e755f65f210eac46fd61c4ea2251810f4307b5d84e8aa67f764b30db50b": {
                "Name": "tomcat02",
                "EndpointID": "65c3a8b0634c77c689b512b5b9ee0a8473776cb63a8d45c44451f6bd41b8690f",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

  1. 测试ping通
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat01 ping tomcat02
PING tomcat02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat02.jiusheng (192.168.0.3): icmp_seq=1 ttl=64 time=0.088 ms
64 bytes from tomcat02.jiusheng (192.168.0.3): icmp_seq=2 ttl=64 time=0.061 ms
64 bytes from tomcat02.jiusheng (192.168.0.3): icmp_seq=3 ttl=64 time=0.048 ms
#发现是可以ping通的
  1. 反向ping
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat02 ping tomcat01
PING tomcat01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat01.jiusheng (192.168.0.2): icmp_seq=1 ttl=64 time=0.034 ms
64 bytes from tomcat01.jiusheng (192.168.0.2): icmp_seq=2 ttl=64 time=0.052 ms
64 bytes from tomcat01.jiusheng (192.168.0.2): icmp_seq=3 ttl=64 time=0.050 ms
#也是可以ping通的

部署redis,就不在演示了,也简单,自行百度

结语

文章因为字数限制,没有写全,需要观看全文的,可移步到本文博客,转载请注明出处。