【云原生 • Docker】Docker入门

文章目录

一、Docker简介

1.1 为什么会有docker出现

假定您在开发一个尚硅谷的谷粒商城,您使用的是一台笔记本电脑而且您的开发环境具有特定的配置。其他开发人员身处的环境配置也各有不同。您正在开发的应用依赖于您当前的配置且还要依赖于某些配置文件。此外,您的企业还拥有标准化的测试和生产环境,且具有自身的配置和一系列支持文件。您希望尽可能多在本地模拟这些环境而不产生重新创建服务器环境的开销。请问?

您要如何确保应用能够在这些环境中运行和通过质量检测?并且在部署过程中不出现令人头疼的版本、配置问题,也无需重新编写代码和进行故障修复?

答案就是使用容器。Docker之所以发展如此迅速,也是因为它对此给出了一个标准化的解决方案-----系统平滑移植,容器虚拟化技术

环境配置相当麻烦,换一台机器,就要重来一次,费力费时。很多人想到,能不能从根本上解决问题,软件可以带环境安装?也就是说,安装的时候,把原始环境一模一样地复制过来。开发人员利用 Docker 可以消除协作编码时“在我的机器上可正常工作”的问题。

在这里插入图片描述
之前在服务器配置一个应用的运行环境,要安装各种软件,就拿尚硅谷电商项目的环境来说,Java/RabbitMQ/MySQL/JDBC驱动包等。安装和配置这些东西有多麻烦就不说了,它还不能跨平台。假如我们是在 Windows 上安装的这些环境,到了 Linux 又得重新装。况且就算不跨操作系统,换另一台同样操作系统的服务器,要移植应用也是非常麻烦的。
传统上认为,软件编码开发/测试结束后,所产出的成果即是程序或是能够编译执行的二进制字节码等(java为例)。而为了让这些程序可以顺利执行,开发团队也得准备完整的部署文件,让维运团队得以部署应用程式,开发需要清楚的告诉运维部署团队,用的全部配置文件+所有软件环境。不过,即便如此,仍然常常发生部署失败的状况。Docker的出现使得Docker得以打破过去「程序即应用」的观念。透过镜像(images)将作业系统核心除外,运作应用程式所需要的系统环境,由下而上打包,达到应用程式跨平台间的无缝接轨运作

1.2 docker理念

Docker是基于Go语言实现的云开源项目。

Docker的主要目标是“Build,Ship and Run Any App,Anywhere”,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到“一次镜像,处处运行”。
在这里插入图片描述
Linux容器技术的出现就解决了这样一个问题,而 Docker 就是在它的基础上发展过来的。将应用打成镜像,通过镜像成为运行在Docker容器上面的实例,而 Docker容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作

一句话

解决了运行环境和配置问题软件容器, 方便做持续集成并有助于整体发布的容器虚拟化技术。

1.3 什么是docker

在这里插入图片描述
Docker,翻译过来就是码头工人

Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可抑制的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。容器完全使用沙盒机制,相互之间不会存在任何接口。几乎没有性能开销,可以很容易的在机器和数据中心运行。最重要的是,他们不依赖于任何语言、框架或者包装系统。

小知识:沙盒也叫沙箱(sandbox)。在计算机领域指一种虚拟技术,而且多用于计算机安全技术。安全软件可以让它在沙盒中运行,如果含有恶意行为,则禁止程序的进一步运行,而这不会对系统造成任何危害。

Docker是dotCloud公司开源的一个基于LXC的高级容器引擎,源码托管在Github上,基于go语言并且遵从Apache2.0协议开源。
GitHub地址:https://github.com/moby/moby

小知识:LXC为Linux Container的简写。Linux Container 容器是一种内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性。
LXC主要通过Kernelnamespace实现每个用户实例之间的项目隔离,通过cgroup实现对资源的配额和调度。

1.4 Docker容器技术与虚拟机的区别。

相同点:docker和容器技术和虚拟机技术,都是虚拟化技术。

不同点:

虚拟机技术:
在这里插入图片描述
容器技术:
在这里插入图片描述
通过图片,我们很明显的看到容器少了一层Guest OS,也就是少了虚拟机操作系统这一层,所以docker效率比虚拟机效率高。达到了秒级启动的地步。

docker相较于VM的优点:

  1. 比VM小、快,Docker容器的尺寸减小相比于整个虚拟机大大简化了分布到云和分发时间的开销。Docker启动一个容器实例时间仅仅需要几秒钟。
  2. Docker是一个开放的平台,构建、发布和运行分布式应用程序。
  3. 开发人员不需要关系具体是哪个Linux操作系统
  4. Google、微软(azure)、亚马逊、IBM等都支持docker。
  5. Docker支持Unix/Linux操作系统,也支持Windows和Mac。

Docker局限性:
Docker用于应用程序时是最有用的,但并不包含数据。日志、数据库等通常放在Docker容器外。一个容器的镜像通常都很小,不用和存储大量数据,存储可以通过外部挂载等方式使用,比如:NFS、ipsan、MFS等 ,或者docker命令 ,-v映射磁盘分区。

总之,docker只用于计算,存储交给别人。

1.5 通过docker架构图初步了解docker。

在这里插入图片描述
等了解了docker之后,这张图所代表的的内容就很清晰明了,希望大家学完docker之后还能回来看看这张图。这里简单给大家介绍一下docker的工作流程。

工作流程:

  1. 启动docker
  2. 下载镜像到本地
  3. 启动docker容器实例

提示:大家可以去注册一个dockerhub,之后会详细给大家讲解它的作用(非常重要!连docker hub账号都没有,玩什么docker!)。

Docker核心技术:

  1. Namespace —> 实现Container的进程、网络、消息、文件系统和主机名的隔离。
  2. Cgroup —> 实现对资源的配额和调度。

注意:Cgroup的配额,可以指定实例使用的CPU个数,内存大小等。

1.6 Docker特性。

  • 文件系统隔离:每个进程容器运行在一个完全独立的根文件系统里。
  • 资源隔离:系统资源,像CPU和内存等可以分配到不同的容器中,使用cgroup。
  • 网络隔离:每个进程容器运行在自己的网路空间,虚拟接口和IP地址。
  • 日志记录:Docker将收集到和记录的每个进程容器的标准流(stdout/stderr/stdin),用于实时检索或者批量检索
  • 变更管理:容器文件系统的变更可以提交到新的镜像中,并可重复使用以创建更多的容器。无需使用模板或者手动配置。
  • 交互式shell:Docker可以分配一个虚拟终端并且关联到任何容器的标准输出上,例如运行一个一次性交互shell。

二、Docker的安装

2.1 前提说明

在这里插入图片描述
前提条件

目前,CentOS 仅发行版本中的内核支持 Docker。Docker 运行在CentOS 7 (64-bit)上,
要求系统为64位、Linux系统内核版本为 3.8以上,这里选用Centos7.x

查看自己的内核

uname命令用于打印当前系统相关信息(内核版本号、硬件架构、主机名称和操作系统类型等)。
在这里插入图片描述

2.2 Docker的基本组成

镜像(image)

Docker镜像(image)就是一个只读的模板,镜像可以用来创建很多Docker容器,一个镜像可以创建很多容器

它也相当于是一个root文件系统。比如官方镜像 centos:7 就包含了完整的一套 centos:7 最小系统的 root 文件系统。相当于容器的“源代码”,docker镜像文件类似于Java的类模板,而docker容器实例类似于java中new出来的实例对象

在这里插入图片描述

容器(container)

  1. 从面向对象角度

Docker 利用容器(Container)独立运行的一个或一组应用,应用程序或服务运行在容器里面,容器就类似于一个虚拟化的运行环境,容器是用镜像创建的运行实例。就像是Java中的类和实例对象一样,镜像是静态的定义,容器是镜像运行时的实体。容器为镜像提供了一个标准的和隔离的运行环境,它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台

  1. 从镜像容器角度

可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

仓库(repository)

仓库(Repository)是集中存放镜像文件的场所。

类似于

  • Maven仓库,存放各种jar包的地方;
  • github仓库,存放各种git项目的地方;
  • Docker公司提供的官方registry被称为Docker Hub,存放各种镜像模板的地方。

仓库分为公开仓库(Public)和私有仓库(Private)两种形式。

最大的公开仓库是 Docker Hub(https://hub.docker.com/)
存放了数量庞大的镜像供用户下载。国内的公开仓库包括阿里云 、网易云等

小总结

需要正确的理解仓库/镜像/容器这几个概念:

Docker 本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就是image镜像文件。只有通过这个镜像文件才能生成Docker容器实例(类似Java中new出来一个对象)。

image文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的容器实例。

镜像文件

  • image 文件生成的容器实例,本身也是一个文件,称为镜像文件。

容器实例

  • 一个容器运行一种服务,当我们需要的时候,就可以通过docker客户端创建一个对应的运行实例,也就是我们的容器

仓库

  • 就是放一堆镜像的地方,我们可以把镜像发布到仓库中,需要的时候再从仓库中拉下来就可以了。

2.3 Docker平台架构图解(架构版)

Docker 是一个 C/S 模式的架构,后端是一个松耦合架构,众多模块各司其职。

Docker运行的基本流程为:

  1. 用户是使用Docker Client和Docker Daemon建立通信,并发送请求给后者。
  2. Docker Daemon作为Docker架构中的主题部分,首先提供Docker Server的功能使其可以接受Docker Client的请求。
  3. Docker Engine执行Docker 内部的一系列工作,每一项工作都是以一个Job的形式存在的。
  4. Job的运行过程中,当需要容器镜像时,则从Docker Registry中下载镜像,并通过镜像管理驱动Graph drive将下载镜像以Graph的形式存储。
  5. 当需要为Docker 创建网络环境时,通过网络管理驱动Network Driver创建并配置Docker 容器网络环境。
  6. 当需要限制Docker容器运行资源或执行用户指令等操作时,则通过Exec driver来完成。
  7. Libcontainer是一项独立的容器管理包,Network Driver以及Exec driver都是通过Libcontainer来实现具体对容器进行的操作。

在这里插入图片描述

2.4 CentOS7安装Docker

有兴趣的小伙伴可以通过下方链接去官网查看。

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

  1. 确定你是CentOS7及以上版本
cat /etc/redhat-release
  1. 卸载旧版本
 yum remove docker
  1. yum安装gcc相关
yum -y install gcc
yum -y install gcc-c++
  1. 安装需要的软件包
yum install -y yum-utils
  1. 配置国内docker-ce的yum源(这里采用的是阿里云)
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

yum-config-manager命令作用是添加yum源。
敲完命令之后大家执行一下命令去看一下有没有配置成功。

cd /etc/yum.repos.d
ls

在这里插入图片描述

看到上图中的框框里的内容就代表配置成功了。

  1. 更新yum软件包索引
yum makecache fast
  1. 安装docker
yum -y install docker-ce docker-ce-cli containerd.io
  1. 启动docker
systemctl start docker
  1. 测试
[root@VM-4-13-centos ~]# docker version
Client: Docker Engine - Community
 Version:           24.0.2
 API version:       1.43
 Go version:        go1.20.4
 Git commit:        cb74dfc
 Built:             Thu May 25 21:53:10 2023
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          24.0.2
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.20.4
  Git commit:       659604f
  Built:            Thu May 25 21:52:10 2023
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.21
  GitCommit:        3dce8eb055cbb6872793272b4f20ed16117344f8
 runc:
  Version:          1.1.7
  GitCommit:        v1.1.7-0-g860f061
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
  1. 测试
[root@VM-4-13-centos yum.repos.d]# docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
  1. 卸载
systemctl stop docker
yum remove docker-ce docker-ce-cli containerd.io
rm -rf /var/lib/docker
rm -rf /var/lib/containerd

2.5 阿里云镜像加速

地址:https://cr.console.aliyun.com的控制台,使用支付宝账号登录,左侧加速器帮助页面会为你显示独立的加速地址,这个加速地址每个人的都不同。

  1. 点击控制台
    在这里插入图片描述

  2. 选择容器镜像服务
    在这里插入图片描述

  3. 获取加速器地址
    在这里插入图片描述

  4. 可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器。把自己的专属加速地址放到下面的地址改一下,写入文件就可以了。

mkdir -p /etc/docker
vim  /etc/docker/daemon.json
{
  "registry-mirrors": ["https://eu5rxjvf.mirror.aliyuncs.com"]
}
systemctl daemon-reload  #启动配置
systemctl restart docker  #重启docker服务
  1. 配置好了之后,我们使用之前学的命令,docker info查看一下是否新增了阿里云的地址。
    在这里插入图片描述

可以看到此地址,代表配置成功。

在这里插入图片描述

2.6 为什么Docker会比VM虚拟机快

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

由于docker不需要Hypervisor(虚拟机)实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。

  1. docker利用的是宿主机的内核,而不需要加载操作系统OS内核

当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。进而避免引寻、加载操作系统内核返回等比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载OS,返回新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了返回过程,因此新建一个docker容器只需要几秒钟。

在这里插入图片描述
在这里插入图片描述

三、Docker常用命令

3.1 帮助启动类命令

  • 启动docker: systemctl start docker
  • 停止docker: systemctl stop docker
  • 重启docker: systemctl restart docker
  • 查看docker状态: systemctl status docker
  • 开机启动: systemctl enable docker
  • 查看docker概要信息: docker info
  • 查看docker总体帮助文档: docker --help
  • 查看docker命令帮助文档: docker 具体命令 --help

3.2 镜像命令

docker images

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

OPTIONS说明:
-a :列出本地所有的镜像(含历史映像层)
-q :只显示镜像ID

[root@VM-4-13-centos ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED       SIZE
hello-world   latest    9c7a54a9a43c   3 weeks ago   13.3kB

各个选项说明:

  • REPOSITORY:表示镜像的仓库源
  • TAG:镜像的标签版本号
  • IMAGE ID:镜像ID
  • CREATED:镜像创建时间
  • SIZE:镜像大小

同一仓库源可以有多个 TAG版本,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。
如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像

docker search

docker search 镜像名           #搜索镜像
OPTIONS说明:
--limit : 只列出N个镜像,默认25个
docker search --limit 5 redis
[root@VM-4-13-centos ~]# docker search centos #从docker hub中搜索docker名为centos的镜像
NAME                                         DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
centos                                       DEPRECATED; The official build of CentOS.       7591      [OK]       
kasmweb/centos-7-desktop                     CentOS 7 desktop for Kasm Workspaces            38                   
bitnami/centos-base-buildpack                Centos base compilation image                   0                    [OK]
bitnami/centos-extras-base                                                                   0                    
couchbase/centos7-systemd                    centos7-systemd images with additional debug…   7                    [OK]
continuumio/centos5_gcc5_base                                                                3                    
datadog/centos-i386                                                                          0                    
dokken/centos-7                              CentOS 7 image for kitchen-dokken               5                    
dokken/centos-8                              CentOS 8 image for kitchen-dokken               3                    
spack/centos7                                CentOS 7 with Spack preinstalled                1                    
dokken/centos-6                              EOL: CentOS 6 image for kitchen-dokken          0                    
atlas/centos7-atlasos                        ATLAS CentOS 7 Software Development OS          0                    
spack/centos6                                CentOS 6 with Spack preinstalled                1                    
couchbase/centos-72-java-sdk                                                                 0                    
ustclug/centos                               Official CentOS Image with USTC Mirror          0                    
couchbase/centos-72-jenkins-core                                                             0                    
dokken/centos-stream-8                                                                       4                    
couchbase/centos-70-sdk-build                                                                0                    
couchbase/centos-69-sdk-build                                                                0                    
eclipse/centos_jdk8                          CentOS, JDK8, Maven 3, git, curl, nmap, mc, …   5                    [OK]
couchbase/centos-69-sdk-nodevtoolset-build                                                   0                    
adoptopenjdk/centos7_build_image                                                             1                    
corpusops/centos-bare                        https://github.com/corpusops/docker-images/     0                    
dokken/centos-stream-9                                                                       6                    
corpusops/centos                             centos corpusops baseimage                      0  

大家可以看到搜索出来的最上一行有几个表头,这里给大家介绍一下

  • name:代表此镜像的名称
  • description:此镜像的描述
  • stars:下载次数
  • official:是否由官方提供(官方提供可放心下载,可以基于此镜像做自己的镜像)

docker pull

docker pull 镜像名 [标签]      #下载镜像(如果不写tag,默认是latest)
[root@VM-4-13-centos ~]# docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
7b1a6ab2e44d: Pull complete 
Digest: sha256:626ffe58f6e7566e00254b638eb7e0f3b11d4da9675088f4781a50ae288f3322
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest

docker system df

docker system df #查看镜像/容器/数据卷所占的空间
[root@VM-4-13-centos ~]# docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          3         2         72.8MB    72.78MB (99%)
Containers      4         0         0B        0B
Local Volumes   0         0         0B        0B
Build Cache     0         0         0B        0B

docker rmi

docker rmi 镜像名 [标签]       #删除镜像    docker rmi -f $(docker images -aq)  删除全部镜像

#删除单个
docker rmi  -f 镜像ID

#删除多个
docker rmi -f 镜像名1:TAG 镜像名2:TAG

docker commit


docker commit  -a "xxx"  -m="描述信息" "xxx" 镜像ID 名字:版本   #提交镜像 
-a :提交的镜像作者;
-m :提交时的说明文字;

导入镜像

docker load -i    /xxx/xxx.tar         #导入镜像
docker save -o   /xxx/xxx.tar          #保存一个镜像为一个tar包

面试题:谈谈docker虚悬镜像是什么?

  • 仓库名、标签都是<none>的镜像,俗称虚悬镜像dangling image
    在这里插入图片描述
  • Dockerfile写一个虚悬镜像
[root@VM ~]# vim Dockerfile

from ubuntu
CMD echo 'action is success'


[root@VM ~]#  docker build .
  • 查看虚悬镜像
[root@VM ~]# docker image ls -f dangling=true

在这里插入图片描述

  • 删除
docker image prune

虚悬镜像已经失去存在价值,可以删除

在这里插入图片描述

3.2 容器命令

新建+启动容器

docker run [可选参数] image 命令 #启动容器(无镜像会先下载镜像)
#参数说明
--name = "Name"   容器名字
-c   后面跟待完成的命令
-d   以后台方式运行并且返回ID,启动守护进程式容器
-i   使用交互方式运行容器,通常与t同时使用
-t   为容器重新分配一个伪输入终端。也即启动交互式容器
-p   指定容器端口    -p 容器端口:物理机端口  映射端口
-P   随机指定端口
-v   给容器挂载存储卷

列出当前所有正在运行的容器

docker ps [OPTIONS]

OPTIONS说明(常用):

  • -a :列出当前所有正在运行的容器+历史上运行过
  • -l :显示最近创建的容器。
  • -n:显示最近n个创建的容器。
  • -q :静默模式,只显示容器编号

退出容器

两种退出方式

  • run进去容器,exit退出,容器停止
exit                           #直接退出容器 
  • run进去容器,ctrl+p+q退出,容器不停止
crlt + P + Q                   #退出容器但是不终止运行

启动已停止运行的容器

docker start 容器实例的ID        #启动容器
docker restart 容器实例的ID       #重启容器

停止容器

docker stop 容器ID或者容器名

强制停止容器

docker kill 容器ID或容器名

删除已停止的容器

docker rm      容器实例的ID   #删除容器(正在运行容器不能删除,除非加-f选项)
#一次性删除多个容器实例
docker rm -f $(docker ps -a -q)
docker ps -a -q | xargs docker rm

3.3 容器命令(重要)

有镜像才能创建容器,这是根本前提(下载一个Redis6.0.8镜像演示)

启动守护式容器(后台服务器)

在大部分的场景下,我们希望 docker 的服务是在后台运行的, 我们可以过 -d 指定容器的后台运行模式。

docker run -d 容器名

使用镜像centos:latest以后台模式启动一个容器

docker run -d centos

问题:然后docker ps -a 进行查看, 会发现容器已经退出
很重要的要说明的一点: Docker容器后台运行,就必须有一个前台进程.
容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。

这个是docker的机制问题,比如你的web容器,我们以nginx为例,正常情况下,
我们配置启动服务只需要启动响应的service即可。例如service nginx start
但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用,
这样的容器后台启动后,会立即自杀因为他觉得他没事可做了.
所以,最佳的解决方案是,将你要运行的程序以前台进程的形式运行,
常见就是命令行模式,表示我还有交互操作,别中断,O(∩_∩)O哈哈~

redis 前后台启动演示case

  • 前台交互式启动
docker run -it redis:6.0.8
  • 后台守护式启动
docker run -d redis:6.0.8

查看容器日志

docker logs 容器实例的ID          #查看容器日志

查看容器内运行的进程

docker top    容器实例的ID                  #查看容器内进程

查看容器内部细节

docker inspect 容器ID

进入正在运行的容器并以命令行交互

docker attach /docker exec  容器实例的ID   #同为进入容器命令,不同的是attach连接终止会让容器退出后台运行,而exec不会。并且,docker attach是进入正在执行的终端,不会启动新的进程,而docker exec则会开启一个新的终端,可以在里面操作。


docker exec -it 容器ID bashShell
docker attach 容器ID

推荐大家使用 docker exec 命令,因为退出容器终端,不会导致容器的停止。

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

docker cp  容器id:容器内路径   目的主机路径           #从容器内拷贝文件到主机(常用)或者从主机拷贝到容器(一般用挂载)

docker cp e36597b5739a:/tmp/aa.txt  /emp

导入和导出容器

  • export 导出容器的内容留作为一个tar归档文件[对应import命令]
docker export 容器ID > 文件名.tar
  • cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号

在这里插入图片描述

四、镜像原理

4.1 镜像是什么?

是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是image镜像文件。

只有通过这个镜像文件才能生成Docker容器实例(类似Java中new出来一个对象)。

4.2 分层的镜像

以我们的pull为例,在下载的过程中我们可以看到docker的镜像好像是在一层一层的在下载
在这里插入图片描述

4.3 Docker镜像加载原理

UnionFS(联合文件系统)

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等等。
在这里插入图片描述
对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。

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

镜像分层最大的一个好处就是共享资源,方便复制迁移,就是为了复用。

比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;
同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

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

当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。

在这里插入图片描述

4.4 Docker镜像commit操作案例

命令

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

实验

  1. 下载一个默认的tomcat,这里作者已经下载好了,就不用再下载了。

在这里插入图片描述

  1. 启动tomcat。
docker run -itd -p 8080:8080 tomcat:latest /bin/bash

然后进入此容器

docker exec -it adbc85d6449a /bin/bash

在这里插入图片描述

  1. 默认tomcat镜像的webapp网页文件里是没有东西的,我们要从webapps.dist中把它拷贝出来。
    在这里插入图片描述

  2. 打开8080端口,在浏览器访问tomcat docker。
    在这里插入图片描述

  3. 提交镜像。

docker commit -m="add webapps app"  -a="This my create tomcat"  6a6e4a979428  tomcat02:1.0

在这里插入图片描述
这里我们就制作了我们的第一个镜像,之后我还会教大家怎么将镜像发布到docker hub上。

  1. 运行新的镜像和之前的镜像对比
    在这里插入图片描述
    可以发现我们之前修改的文件。

4.5 本地镜像发布到阿里云流程

在这里插入图片描述

  1. 本地镜像素材原型
    在这里插入图片描述

  2. 阿里云开发者平台
    https://promotion.aliyun.com/ntms/act/kubernetes.html
    在这里插入图片描述

  3. 创建仓库镜像
    在这里插入图片描述

  4. 选择控制台,进入容器镜像服务
    在这里插入图片描述

  5. 选择个人实例
    在这里插入图片描述

  6. 命名空间
    在这里插入图片描述

  7. 继续
    在这里插入图片描述

  8. 仓库名称
    在这里插入图片描述

  9. 继续
    在这里插入图片描述
    在这里插入图片描述

  10. 进入管理界面获得脚本
    在这里插入图片描述

  11. 将镜像推送到阿里云

将镜像推送到阿里云registry

管理界面脚本

在这里插入图片描述

  1. 脚本实例
 docker login --username=zzyybuy registry.cn-hangzhou.aliyuncs.com

docker tag cea1bb40441c registry.cn-hangzhou.aliyuncs.com/atguiguwh/myubuntu:1.1
docker push registry.cn-hangzhou.aliyuncs.com/atguiguwh/myubuntu:1.1

上面命令是作者自己本地的,你自己酌情处理,不要粘贴我的。

在这里插入图片描述

4.6 将阿里云上的镜像下载到本地

下载到本地

在这里插入图片描述

docker pull registry.cn-hangzhou.aliyuncs.com/atguiguwh/myubuntu:1.1

4.7 本地镜像发布到私有库

为什么有私有库

  1. 官方Docker Hub地址:https://hub.docker.com/,中国大陆访问太慢了且准备被阿里云取代的趋势,不太主流。
  2. Dockerhub、阿里云这样的公共镜像仓库可能不太方便,涉及机密的公司不可能提供镜像给公网,所以需要创建一个本地私人仓库供给团队使用,基于公司内部项目构建镜像。
  3. Docker Registry是官方提供的工具,可以用于构建私有镜像仓库

将本地镜像推送到私有库

  1. 下载镜像Docker Registry,专门用来搭建私有库的镜像
docker pull registry

在这里插入图片描述
在这里插入图片描述

  1. 运行私有库Registry,相当于本地有个私有Docker hub
docker run -d -p 5000:5000  -v /zzyyuse/myregistry/:/tmp/registry --privileged=true registry

默认情况,仓库被创建在容器的/var/lib/registry目录下,建议自行用容器卷映射,方便于宿主机联调
在这里插入图片描述

  1. curl验证私服库上有什么镜像
 curl -XGET http://192.168.111.162:5000/v2/_catalog

可以看到,目前私服库没有任何镜像上传过。。。。。。

在这里插入图片描述

  1. 将新镜像zzyyubuntu:1.2修改符合私服规范的Tag
    按照公式:
docker   tag   镜像:Tag   Host:Port/Repository:Tag

自己host主机IP地址,填写同学你们自己的,不要粘贴错误,

使用命令 docker tag 将zzyyubuntu:1.2 这个镜像修改为192.168.111.162:5000/zzyyubuntu:1.2

docker tag  zzyyubuntu:1.2  192.168.111.162:5000/zzyyubuntu:1.2

在这里插入图片描述

  1. 修改配置文件使之支持http
    在这里插入图片描述
    别无脑照着复制,registry-mirrors 配置的是国内阿里提供的镜像加速地址,不用加速的话访问官网的会很慢。

2个配置中间有个逗号 ','别漏了,这个配置是json格式的。

vim命令新增如下红色内容:vim /etc/docker/daemon.json

{
  "registry-mirrors": ["https://aa25jngu.mirror.aliyuncs.com"],
  "insecure-registries": ["192.168.111.162:5000"] #增加这个
}

上述理由:docker默认不允许http方式推送镜像,通过配置选项来取消这个限制。====> 修改完后如果不生效,建议重启docker

  1. push推送到私服库
docker push 192.168.111.162:5000/zzyyubuntu:1.2

在这里插入图片描述

  1. curl验证私服库上有什么镜像2
curl -XGET http://192.168.111.162:5000/v2/_catalog

在这里插入图片描述

  1. pull到本地并运行
docker pull 192.168.111.162:5000/zzyyubuntu:1.2

在这里插入图片描述

docker run -it 镜像ID /bin/bash

在这里插入图片描述

五、Docker容器数据卷

5.1 使用数据卷的坑

Docker挂载主机目录访问如果出现cannot open directory .: Permission denied

解决办法:在挂载目录后多加一个--privileged=true参数即可

如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,
在SELinux里面挂载目录被禁止掉了额,如果要开启,我们一般使用–privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。

5.2 容器数据卷介绍

docker容器在产生数据的时候,如果不通过docker commit生成新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除之后,数据自然而然的也会消失。为了能保存数据,容器中引用了数据卷的概念。

5.3 作用以及特点

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

卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此docker不会再容器删除时删除其挂载的数据卷。

它还存在以下几种特点:

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

5.4 使用数据卷

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

docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录      镜像名

我们在创建容器之前,先看看挂载路径上有没有test01这个目录,可以看到,是没有的。执行命令之后进入到容器内,我们ls看一下容器的home目录,是空的。

docker run -it -v /home/test01:/home centos /bin/bash

在这里插入图片描述
另外打开一个终端,cd /home目录,这下我们发现多出来了一个test01目录,这个test01目录,就是我们刚刚启动的容器内部的home目录,并且,此时这两个目录是同步的状态,我们在home目录中写入任何新的文件,都会同步到主机home目录下的test01目录。

在这里插入图片描述
我们在这里测试一下,echo进去一个a.txt文件。
在这里插入图片描述
然后来到宿主机上,看一眼是不是test01目录下也出现了a.txt。(双向绑定)
在这里插入图片描述
当然,我们可以使用更简单的方法查看是否挂载成功,大家还记得是那条命令吗?没错,是docker inspect 容器ID。我们找到这个Mounts,它代表着挂载,type是类型(绑定),source是源(/home/test01),也就是把什么挂载到哪里。destination(home)就是挂载的目标路径了。

在这里插入图片描述
这里作者只演示了修改容器内文件同步到宿主机挂载文件。其实反过来也是一样的,这里就不再赘述了。之后如果要修容器内挂载文件,只需在我们本地挂载点修改就好了,它会自动同步到docker。

  1. docker修改,主机同步获得
  2. 主机修改,docker同步获得
  3. docker容器stop,主机修改,docker容器重启看数据是否同步。

5.5 读写规则映射添加说明

读写(默认)

docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:rw      镜像名

在这里插入图片描述

rw = read + write

只读

docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro      镜像名

ro = read only

容器实例内部被限制,只能读取不能写
在这里插入图片描述

5.6 卷的继承和共享

容器1完成和宿主机的映射

docker run -it  --privileged=true -v /mydocker/u:/tmp --name u1 ubuntu

在这里插入图片描述
在这里插入图片描述

容器2继承容器1的卷规则

docker run -it  --privileged=true --volumes-from 父类  --name u2 ubuntu

在这里插入图片描述

5.7 具名挂载与匿名挂载

这里先教给大家一个新武器。

docker volum ls #查看所有卷的情况。

匿名挂载

我们首先使用匿名挂载的命令启动一个容器。

docker run -d -P --name=nginxt01 -v /etc/nginx nginx

然后使用刚刚教给大家的新武器查看卷。
在这里插入图片描述
这里84开头的那一长串就是挂载到宿主机的名字。

我们继续追查下去。这里教给大家一个很简单的命令,less。如果输出的信息太多了,我们找不到,就可以这样使用

cmd | less 栗子: docker inspect 84(容器ID) | less

然后输入/name, name是你想查到的内容,就可以很轻松的找到啦。

大家仔细看一下,是不是/etc/nginx就是叫84开头的那一长串,挂载到了我/var/lib…路径下,我们复制这个路径继续去查看。

在这里插入图片描述
怎么样,是不是在我们的宿主机就发现了这样的一个文件呢?这就是所谓的匿名挂载!是不是很简单。
在这里插入图片描述

具名挂载

具名挂载就很简单了,跟我们之前演示的指定路径挂载很相似,这里给大家简单地演示一下。

同样,我们使用具名挂载的方式启动一个容器。

docker run -d -P --name=nginxt02 -v jumingguazai:/etc/nginx nginx
docker volume ls 查看卷

在这里插入图片描述

docker inspect ID | less 找到挂载点。

在这里插入图片描述
我们再复制一下路径,找到nginx的配置文件。
在这里插入图片描述
这就是具名挂载。

如何确定是具名挂载还是匿名挂载:
-v  容器内路径               #匿名挂载
-v  卷名:容器内路径          #具名挂载
-v  /宿主机路径:容器内路径    # 指定路径挂载

tips:

通过 -v 容器内路径  :ro   rw   可以改变读写权限
ro  readonly   #只读
rw  readwrite  #可写可读
例: docker run -d --name nginx01 -v test01:/etc/nginx:ro nginx
    docker run -d --name nginx01 -v test01:/etc/nginx:rw nginx

六、DockerFile

6.1 什么是Dockerfile?

Dockerfile是一个创建镜像所有命令的文本文件,包含了一条条指令和说明,每条指令构建一层,通过docker build命令,根据Dockerfile的内容构建镜像。

因此每一条指令的内容, 就是描述该层如何构建。

有了Dockefile,就可以制定自己的docker镜像规则,只需要在Dockerfile上添加或者修改指令,,就可生成docker 镜像。

通俗来说,Dockerfile是用来构建docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。

官网:https://docs.docker.com/engine/reference/builder/

构建三步骤

  1. 编写Dockerfile文件
  2. docker build命令构建镜像
  3. docker run依镜像运行容器实例

6.2 DockerFile构建过程解析

Dockerfile内容基础知识

  1. 每条保留字指令(关键字)都必须为大写字母且后面要跟随至少一个参数。
  2. 指令按照从上到下,顺序执行。
  3. #表示注释。
  4. 每条指令都会创建一个新的镜像层并对镜像进行提交。

Docker执行Dockerfile的大致流程

我们先通过下面这张图片来理解一下镜像的构成以及运行过程。
在这里插入图片描述

  1. docker从基础镜像(ubuntu)运行一个容器。
  2. 执行一条指令(ADD run.sh /)并对镜像进行修改。
  3. 执行类似docker commit的操作提交一个新的镜像层
  4. docker再基于刚提交的镜像运行一个新容器
  5. 执行dockerfile中的下一条指令直到所有指令都执行完成。

在这里我们来整理一下docker容器、dockerfile、docker镜像的关系:

  • dockerfile是面向开发的,发布项目做镜像的时候就要编写dockerfile文件。
  • dockerfile:构建文件,定义了一切的步骤,源代码。
  • dockerImanges:通过dockerfile构建生成的镜像,最终发布和运行的产品。
  • docker容器:容器就是镜像运行起来提供服务的。

小总结

从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段

  • Dockerfile是软件的原材料
  • Docker镜像是软件的交付品
  • Docker容器则可以认为是软件镜像的运行态,也即依照镜像运行的容器实例。

Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
在这里插入图片描述

  1. Dockerfile:需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
  2. Docker镜像:在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时会真正开始提供服务;
  3. Docker容器:容器是直接提供服务的。

6.3 Dockerfile 指令选项

FROM

FROM centos

基础镜像,当前新镜像是基于那个镜像的,指定一个已经存在的镜像作为模板,第一条必须是FROM 。

MAINTAINER

MAINTAINER Developer_dhx

镜像维护者的姓名和邮箱地址,已被弃用,代替词LABEL

LABEL

LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:

LABEL <key>=<value> <key>=<value> <key>=<value> ...
比如我们可以添加镜像的作者:
LABEL org.opencontainers.image.authors="runoob"

RUN

镜像构建时需要运行的命令

RUN mkdir /usr/local/java

存在两种格式

  1. shell格式

在这里插入图片描述

RUN yum -y install vim
  1. exec格式

在这里插入图片描述

RUN是在 docker build时运行

CMD

指定容器启动后的要干的事件

在这里插入图片描述
注意

Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换

参考官网Tomcat的dockerfile演示讲解

在这里插入图片描述
官网最后一行命令

在这里插入图片描述
我们演示自己的覆盖操作

CMD和RUN的区别

注意:CMD类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

  • CMD是在docker run 时运行。
  • RUN是在 docker build时运行。

EXPOSE

当前容器对外暴露出的端口

EXPOSE 8080

WORKDIR

指定在创建容器后,终端默认登录的进来工作目录,一个落脚点(类似CD命令)

WORKDIR /usr

USER

指定该镜像以什么样的用户去执行,如果都不指定,默认是root

ENV

用来在构建镜像过程中设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

ENV MY_PATH /usr/mytest

这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;

也可以在其它指令中直接使用这些环境变量,比如:

WORKDIR $MY_PATH

ADD

将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包。

ADD 源目录/文件 目标目录/文件

COPY

类似ADD,拷贝文件和目录到镜像中。 将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置

COPY 源目录/文件 目标目录/文件

和 ADD 相似,但压缩文件不会自动解压

VOLUME

容器数据卷,用于数据保存和持久化工作

ENTRYPOINT

  • 也是用来指定一个容器启动时要运行的命令
  • 类似于 CMD 指令,但是ENTRYPOINT不会被docker run后面的命令覆盖, 而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序

命令格式:

在这里插入图片描述

ENTRYPOINT可以和CMD一起用,一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参。

当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再是直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令,他两个组合会变成在这里插入图片描述
案例如下:假设已通过 Dockerfile 构建了 nginx:test 镜像

在这里插入图片描述

是否传参按照dockerfile编写执行传参运行
Docker命令docker run nginx:testdocker run nginx:test -c /etc/nginx/new.conf
衍生出的实际命令nginx -c /etc/nginx/nginx.connginx -c /etc/nginx/new.conf

优点

  • 在执行docker run的时候可以指定 ENTRYPOINT 运行所需的参数。
  • 注意
  • 如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

七、Docker微服务实战

7.1 构建微服务

  1. 通过IDEA新建一个普通微服务模块,创建一个Module并取名为spring-boot-docker

  2. 改POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>spring-boot-docker</artifactId>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.14</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${project.parent.version}</version>
            </plugin>
        </plugins>
    </build>

</project>
  1. 修改YML配置文件
server:
  port: 6001
  1. 主启动类
@SpringBootApplication
public class SpringBootDockerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootDockerApplication.class, args);
    }

}
  1. 业务类
@RestController
public class OrderController {

    @Value("${server.port}")
    private String port;

    @RequestMapping("/order/docker")
    public  String helloDocker(){
        return  "hello docker"+"\t"+port+"\t"+ UUID.randomUUID().toString();
    }

    @RequestMapping(value = "/order/index",method = RequestMethod.GET)
    public  String index(){
        return "服务端口号: "+"\t"+port+"\t"+UUID.randomUUID().toString();
    }
}

7.2 通过dockerfile发布微服务部署到docker容器

  1. IDEA工具里面搞定微服务jar包
    在这里插入图片描述

  2. 编写Dockerfile

# 基础镜像使用java
FROM java:8
# 作者
MAINTAINER zzyy
# VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
# 将jar包添加到容器中并更名为zzyy_docker.jar
ADD docker_boot-0.0.1-SNAPSHOT.jar zzyy_docker.jar
# 运行jar包
RUN bash -c 'touch /zzyy_docker.jar'
ENTRYPOINT ["java","-jar","/zzyy_docker.jar"]
#暴露6001端口作为微服务
EXPOSE 6001
  1. 将微服务jar包和Dockerfile文件上传到同一个目录下/mydocker
    在这里插入图片描述

  2. 构建镜像

docker build -t zzyy_docker:1.6 .

在这里插入图片描述

  1. 运行容器
 docker run -d -p 6001:6001 zzyy_docker:1.6

在这里插入图片描述

  1. 访问测试
    在这里插入图片描述

八、Docker网络

8.1 是什么?

docker不启动,默认网络情况

我们使用ifconfig可以看到三组网络
在这里插入图片描述

  • ens33:本机的外网地址
  • lo:本地环回地址,可以代表localhost。
  • virbr0:在CentOS7的安装过程中如果有**选择相关虚拟化的的服务安装系统后**,启动网卡时会发现有一个以网桥连接的私网地址的virbr0网卡(virbr0网卡:它还有一个固定的默认IP地址192.168.122.1),是做虚拟机网桥的使用的,其作用是为连接其上的虚机网卡提供 NAT访问外网的功能。
  • 我们之前学习Linux安装,勾选安装系统的时候附带了libvirt服务才会生成的一个东西,如果不需要可以直接将libvirtd服务卸载,yum remove libvirt-libs.x86_64

docker启动后,网络情况

会产生一个名为docker0的虚拟网桥,这是我们本节的重点,docker的网络。

在这里插入图片描述
关于docker0呢,其实就是一个叫docker0的虚拟网桥。我们使用brctl命令来查看一下。(没有这个命令的下载yum -y install bridge-utils

brctl show 

在这里插入图片描述

8.2 清空本机docker环境

docker rm -f $(docker ps -aq)
docker rmi -f $(docker images -aq)

8.3 docker网络模式

1、docker网络模式有以下几种

查看docker网络模式命令

docker network ls   #列出docker网卡

在这里插入图片描述

  • bridge:默认为该模式(桥接,自己创建也是用它),此模式会为每一个分配,设置IP等,并将容器连接到一个docker0 的虚拟网桥,通过docker 0 网桥以及iptables nat 表配置与宿主机通信。
  • Host:容器不会虚拟出自己的网卡,配置主机的IP等,而是使用宿主机的IP和端口。
  • None: 该模式关闭了容器的网络功能。(一般不用)
  • Container: 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP。(一般不用)
    在这里插入图片描述
  • bridge模式:使用–network bridge指定,默认使用docker0
  • host模式:使用–network host指定
  • none模式:使用–network none指定
  • container模式:使用–network container:NAME或者容器ID指定

2、常用基本命令:

在这里插入图片描述

查看网络

docker network ls

查看网络源数据

docker network inspect  XXX网络名字 #查看网卡详细信息

在这里插入图片描述

创建网络

docker network create aa_network

删除网络

docker network rm XXX网络名字

在这里插入图片描述

3、能干嘛?

  • 容器间的互联和通信以及端口映射
  • 容器IP变动时候可以通过服务名直接网络通信而不受到影响

4、创建自定义网络的容器

我们直接启动命令, --net bridge,就是docker0(默认)
docker run -d -P --name=tomcat01 --net bridge tomcat

docker0特点:默认,域名不能访问,--link不建议使用

下面我们自己来创建一个bridge。

docker network create --driver bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 testnet

docekr network ls

只需要两条命令,你就创建完了自己的网络!

在这里插入图片描述

docker network inspect 网卡名字  #查看网卡详细信息

在这里插入图片描述

5、发布两个在自己创建的网络里的容器

docker run -d -P --name=tomcat01-net --net=testnet tomcat:7
docker run -d -P --name=tomcat02-net --net testnet tomcat:7

然后使用docker network inspect testnet,就可以看到刚才创建的这两个容器的IP了。
在这里插入图片描述
还记得我们前面说的docker0的缺点之一,不能通过域名访问吗?而我们自定义的网络,就修复了这个功能!

docker exec -it tomcat01-net ping -c 3 IP
docker exec -it tomcat01-net ping -c 3 tomcat02-net

提示,ping -c可以自定义ping的次数

在这里插入图片描述

8.4 容器实例内默认网络IP生产规则

  1. 先启动两个ubuntu容器实例

在这里插入图片描述

  1. docker inspect 容器ID or 容器名字
    在这里插入图片描述

  2. 关闭u2实例,新建u3,查看ip变化

4.

结论

docker容器内部的ip是有可能会发生改变的

8.5 bridge

是什么?

  • Docker服务默认会创建一个docker0的网桥(其上有一个docker0内部接口),该桥接网络的名称为docker0。
  • 它在 内核层 连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到 同一个物理网络
  • Docker默认指定了docker0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥相互通信

查看 bridge 网络的详细信息,并通过 grep 获取名称项

docker network inspect bridge | grep name

在这里插入图片描述

ifconfig |grep docker

在这里插入图片描述

案例说明

  1. Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
  2. docker run 的时候,没有指定network的话默认使用的网桥模式就是bridge,使用的就是docker0。在宿主机ifconfig,就可以看到docker0和自己create的network(后面讲)eth0,eth1,eth2……代表网卡一,网卡二,网卡三……,lo代表127.0.0.1,即localhost,inet addr用来表示网卡的IP地址
  3. 网桥docker0创建一对对等虚拟设备接口一个叫veth,另一个叫eth0,成对匹配。
    • 整个宿主机的网桥模式都是docker0,类似一个交换机有一堆接口,每个接口叫veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair);
    • 每个容器实例内部也有一块网卡,每个接口叫eth0;
    • docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配。

通过上述,将宿主机上的所有容器都连接到这个内部网络上,两个容器在同一个网络下,会从这个网关下各自拿到分配的ip,此时两个容器的网络是互通的。
在这里插入图片描述

  1. 代码演示
docker run -d -p 8081:8080   --name tomcat81 billygoo/tomcat8-jdk8

docker run -d -p 8082:8080   --name tomcat82 billygoo/tomcat8-jdk8

ip addr
docker exec -it tomcat81 bash
docker exec -it tomcat82 bash
  1. 两两匹配验证
    在这里插入图片描述

8.6 host

是什么?

直接使用宿主机的IP地址与外界进行通信,不再需要额外进行NAT转换。

案例说明

  1. 容器将 不会获得 一个独立的Network Namespace, 而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡而是使用宿主机的IP和端口。
    在这里插入图片描述

  2. 代码警告版本

docker run -d -p 8083:8080 --network host --name tomcat83 billygoo/tomcat8-jdk8

在这里插入图片描述
问题:

docke启动时总是遇见标题中的警告

原因:

docker启动时指定--network=host-net=host,如果还指定了-p映射端口,那这个时候就会有此警告,并且通过-p设置的参数将不会起到任何作用,端口号会以主机端口号为主,重复时则递增。

解决:

解决的办法就是使用docker的其他网络模式,例如–network=bridge,这样就可以解决问题,或者直接无视。。。。O(∩_∩)O哈哈~

  1. 代码正确版本
docker run -d  --network host --name tomcat83 billygoo/tomcat8-jdk8

无之前的配对显示了,看容器实例内部

在这里插入图片描述

  1. 没有设置-p的端口映射了,如何访问启动的tomcat83??

http://宿主机IP:8080/

在CentOS里面用默认的火狐浏览器访问容器内的tomcat83看到访问成功,因为此时容器的IP借用主机的,所以容器共享宿主机网络IP,这样的好处是外部主机与容器可以直接通信。

8.7 none

是什么?

  • 在none模式下,并不为Docker容器进行任何网络配置。
  • 也就是说,这个Docker容器没有网卡、IP、路由等信息,只有一个lo。
  • 需要我们自己为Docker容器添加网卡、配置IP等。
  • 禁用网络功能,只有lo标识(就是127.0.0.1表示本地回环)

案例说明

docker run -d -p 8084:8080 --network none --name tomcat84 billygoo/tomcat8-jdk8

进入容器内部查看
在这里插入图片描述
在容器外部查看

在这里插入图片描述

8.8 container

是什么?

  • 新建的容器和 已经存在的一个容器共享 一个网络ip配置而不是和宿主机共享。
  • 新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。
  • 同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。

在这里插入图片描述

案例说明

错误案例
docker run -d -p 8085:8080   --name tomcat85 billygoo/tomcat8-jdk8
docker run -d -p 8086:8080 --network container:tomcat85 --name tomcat86 billygoo/tomcat8-jdk8

运行结果
在这里插入图片描述

  • 相当于tomcat86和tomcat85公用同一个ip同一个端口,导致端口冲突
  • 本案例用tomcat演示不合适。。。换一个镜像给大家演示,
正确案例

Alpine操作系统是一个面向安全的轻型 Linux发行版

Alpine Linux 是一款独立的、非商业的通用 Linux 发行版,专为追求安全性、简单性和资源效率的用户而设计。 可能很多人没听说过这个 Linux 发行版本,但是经常用 Docker 的朋友可能都用过,因为他小,简单,安全而著称,所以作为基础镜像是非常好的一个选择,可谓是麻雀虽小但五脏俱全,镜像非常小巧,不到 6M的大小,所以特别适合容器打包。

docker run -it                             --name alpine1  alpine /bin/sh

docker run -it --network container:alpine1 --name alpine2  alpine /bin/sh

运行结果,验证共用搭桥

在这里插入图片描述
假如此时关闭alpine1,再看看alpine2

在这里插入图片描述

15: eth0@if16: 消失了。。。。。。关闭alpine1,再看看alpine2
在这里插入图片描述

8.9 自定义网络

过时的link

在这里插入图片描述

before

案例
docker run -d -p 8081:8080   --name tomcat81 billygoo/tomcat8-jdk8

docker run -d -p 8082:8080   --name tomcat82 billygoo/tomcat8-jdk8

上述成功启动并用docker exec进入各自容器实例内部

docker exec -it tomcat81 bash
docker exec -it tomcat82 bash
问题

按照IP地址ping是OK的
在这里插入图片描述
在这里插入图片描述
按照服务名ping结果不行

在这里插入图片描述
在这里插入图片描述

after

案例

自定义桥接网络,自定义网络默认使用的是桥接网络bridge

新建自定义网络

docker network create 网络名字

在这里插入图片描述
新建容器加入上一步新建的自定义网络

docker run -d -p 8081:8080 --network zzyy_network  --name tomcat81 billygoo/tomcat8-jdk8

docker run -d -p 8082:8080 --network zzyy_network  --name tomcat82 billygoo/tomcat8-jdk8

互相ping测试

在这里插入图片描述
在这里插入图片描述

问题结论

自定义网络本身就维护好了主机名和ip的对应关系(ip和域名都能通)

8.10 veth-pair技术

什么是veth-pair技术?要理解它,我们首先来启动两个tomcat容器。

docker run -d -P --name=tomcat01 tomcat:7
docker run -d -P --name=tomcat02 tomcat:7
提示:选择tomcat7是因为这个镜像包含了ip addr 等常用命令!

启动机器之后,我们查看容器ip,通过容器的ip 去ping宿主机ip,发现是通的。

docker exec -it tomcat01 ip addr

在这里插入图片描述

ping 172.17.0.3

在这里插入图片描述
理解:我们每启动一个docker容器,docker就会给docker容器分配一个ip,安装docker之后,会产生一个叫docker0的网卡,这里使用的就是 veth-pair技术

使用ip addr命令,查看我们的网卡。

在这里插入图片描述
我们发现多出来了两个网卡,到了这里,你已经知道这两张网卡是那里来的了吧。没错,是启动容器之后产生的!我们回过头来查看我们在启动的容器IP,就会很清晰的发现,这个网卡是成对存在的!容器内的64对应着宿主机的65,容器内的66对应宿主机的67。

什么是veth-pair?

veth-pair 就是一堆的虚拟设备接口,他们都是成对出现的,一端连接着协议,一端连接着彼此。使得它充当了一个桥梁的作用。

在这里插入图片描述

8.11 docker网络详解

我们来绘制一个简单的网络模型,这样veth-pair的作用就清晰明了了。

在这里插入图片描述
不难看出,tomcat01和tomcat02是共用的同一个路由器,即docker0。所有的容器在不指定我网络的情况下,都是docker0路由的,docekr会给我们的容器分配一个默认IP。
docker网络就是下面这个网络模型所描述的。(docker所有的网络接口都是虚拟的,虚拟的转发效率高)

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值