docker 学习指南——持续更新

发布于 2022-06-16  1.8k 次阅读


一.虚拟化技术

1.1 虚拟化介绍

操作系统层虚拟化是指通过划分一个宿主操作系统的特定部分,产生一个个隔离的操作执行环境。操作系统层的虚拟化是操作系统内核直接提供的虚拟化,虚拟出的操作系统之间共享底层宿主操作系统内核和底层的硬件资源。操作系统虚拟化的关键点在于将操作系统与上层应用隔离开,将对操作系统资源的访问进行虚报化,使上层应用觉得自己独占操作系统。

操作系统虚拟化的好处是实现了虚拟操作系统与物理操作系统的隔离并且有效避免物理操作系统的重复安装。比较有名的操作系统虚报化解决方案有Virtual Server、Zone、Virtuozzo 及虚拟专用服务器(Vital Pnvate Sever,VPS)。VPS是利用虚拟服务器软件在一台物理机上创建多个相互隔离的小服务器。这些小服务器本身就有自己的操作系统,其运行和管理与独立主机完全相。其可以保证用户独享资源,且可以节约成本。

1.2 虚拟化分类

  1. 仿真虚拟化 [对系统硬件没有要求,性能最低] VMware
  2. 半虚拟化 [虚拟机可以使用真机物理硬件,性能高,需要改内核] xen
  3. 硬件辅助虚拟化 vmware kvm
    • 需要硬件支持 【cpu 主板】
    • 不需要改内核
    • 可以直接使用真机硬件,性能最贴近宿主机
  4. 容器虚拟化 lxc docker

1.3 主机虚拟化和容器虚拟比较

主机虚拟化

vmachines.png
  • 应用程序运行环境强隔离
  • 虚拟机操作系统与底层操作系统无关化
  • 虚拟机内部操作不会影响到物理机
  • 拥有操作系统会占用部署资源及存储
  • 网络传输效率低
  • 当应用程序需要调用硬件响应用户访问时间延迟大

容器虚拟化

container_virtual.png
  • 可以实现应用程序的隔离
  • 直接使用物理机的操作系统可以快速响应用户请求
  • 不占用部署时间
  • 占用少量磁盘空间

容器虚拟化缺点:学习成本增加、操作控制麻烦、网络控制与主机虚拟化有所区别、服务治理。

二.docker 介绍

2.1 Docker 开源项目的背景

docker 是基于Go语言编写的开源容器项目。诞生于2013年初,最初的发起者是dotCloud 公司,目前docker 已经全球最大的容器服务提供商。docker 项目已加入Linux 基金会,并遵循Apache 2.0协议,全部开源代码均在 https: // github com/docker 项目仓库进行维护.

LXC 是早期得容器技术 发布于2008年是第一套完整的容器管理解决方案,不需要任何补丁直接运行在linux内核之上管理容器

2.2 Linux 容器技术

docker 算得上是linux 容器的技术的代表,目前市面上使用的比较多的就是linux 容器技术就是docker。具体docker的发展之路,我这里就不说了。

什么是容器技术呢?容器有效地将由单个操作系统管理的 资源划分到孤立的组中,以更好地在孤立的组之间平衡有冲突的资惊使用需求 与虚拟化相 比,这样既不需要指令级模拟,也不需要即时编译 容器可以在核心 CPU 本地运行指令,而不需要任何专门的解释机制此外,也避免了准虚拟化( para-virtualization )和系统调用替换 中的复杂性。

简单的说容器就是:更加轻量且耦合性更低的沙盒(sendbox),每个容器内运行着一个应用,不同容器之间相互隔离,容器之间也可以通过网络互相通信。容器的创建和停止十分快速,几乎跟创建和终止原生应用一致;另外,容器自身对系统资源的额外需求也十分有限,远远低于传统虚拟机。很多时候,甚至直接把容器当作应用本身也没有任何问题。

2.3 为什么要使用docker

在开发和运维过程中,Docker 具备如下几个方面的优势:

更快速的交付和部署:使用docker 运维人员可以使用镜像来快速构建一套标准的软件运行环境,当开发完成代码编写后,运维人员可以直接使用相同的环境来部署代码。只要开发测试过代码,就可以确保在生产环境无缝运行。Docker可以快速的创建和删除容器,实现快速的迭代,节约开发、测试、部署的大量时间。并且,整个过程全程可见,使团队更容易理解应用的创建和工作过程。

更高效的资源利用:运行Docker容器不需要额外的虚拟化管理程序的支持,Docker 是内核级的虚拟化,可以实现更高的性能,同时对资源的额外需求很低。与传统虚拟化方式相比,Docker 的性能要高1~2个量级。

更轻松迁移和扩展:运行Docker 容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器,同事支持主流的操作系统发行版本。这种兼容让用户可以在不同平台之间轻松的迁移应用。

更简单的更新管理:使用Dockerfile ,只需要小小的配置修改,就可以代替以往大量的更新工作。所有修改都以增量的方式被分配和更新,从而实现自动化并且高效的容器管理。

对比传统虚拟机总结

特性容器虚拟机
启动秒级分钟级
硬盘使用一般为 MB一般为 GB
性能接近原生弱于
系统支持量单机支持上千个容器一般几十个

docker 基本架构:

Docker 采用了 C/S架构,包括客户端和服务端。 Docker daemon 作为服务端接受来自客户的请求,并处理这些请求(创建、运行、分发容器)。 客户端和服务端既可以运行在一个机器上,也可通过 socket 或者 RESTful API 来进行通信。

docker daemon 一般在宿主主机后台运行,等待接收来自客户端的消息。 Docker 客户端则为用户提供一系列可执行命令,用户用这些命令实现跟 Docker daemon 交互。

容器 — 镜像 — 仓库 — daemon — client 之间的关系

clientdaemon.jpg

2.4 Docker的名字空间

名字空间是 Linux 内核一个强大的特性。每个容器都有自己单独的名字空间,运行在其中的应用都像是在独立的操作系统中运行一样。名字空间保证了容器之间彼此互不影响。

pid 名字空间:不同用户的进程就是通过 pid 名字空间隔离开的,且不同名字空间中可以有相同 pid。所有的 LXC 进程在 Docker 中的父进程为Docker进程,每个 LXC 进程具有不同的名字空间。同时由于允许嵌套,因此可以很方便的实现嵌套的 Docker 容器。

net 名字空间:有了 pid 名字空间, 每个名字空间中的 pid 能够相互隔离,但是网络端口还是共享 host 的端口。网络隔离是通过 net 名字空间实现的, 每个 net 名字空间有独立的 网络设备, IP 地址, 路由表, /proc/net 目录。这样每个容器的网络就能隔离开来。Docker 默认采用 veth 的方式,将容器中的虚拟网卡同 host 上的一 个Docker 网桥 docker0 连接在一起。

ipc 名字空间:容器中进程交互还是采用了 Linux 常见的进程间交互方法(interprocess communication - IPC), 包括信号量、消息队列和共享内存等。然而同 VM 不同的是,容器的进程间交互实际上还是 host 上具有相同 pid 名字空间中的进程间交互,因此需要在 IPC 资源申请时加入名字空间信息,每个 IPC 资源有一个唯一的 32 位 id。

mnt 名字空间:类似 chroot,将一个进程放到一个特定的目录执行。mnt 名字空间允许不同名字空间的进程看到的文件结构不同,这样每个名字空间 中的进程所看到的文件目录就被隔离开了。同 chroot 不同,每个名字空间中的容器在 /proc/mounts 的信息只包含所在名字空间的 mount point。

uts 名字空间:UTS(“UNIX Time-sharing System”) 名字空间允许每个容器拥有独立的 hostname 和 domain name, 使其在网络上可以被视作一个独立的节点而非 主机上的一个进程。

user 名字空间:每个容器可以有不同的用户和组 id, 也就是说可以在容器内用容器内部的用户执行程序而非主机上的用户。

三.docker 安装

3.1 卸载旧版本


较旧的Docker版本称为dockerdocker-engine。如果已安装这些程序,请卸载它们以及相关的依赖项。
rpm -qa|grep -i docker 查询已经安装的docker

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

如果yum报告未安装这些软件包,则可以。
的内容(/var/lib/docker/包括图像,容器,卷和网络)被保留。现在将Docker Engine软件包称为docker-ce。

3.2 安装方法 yum

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

  • 大多数用户会 设置Docker的存储库并从中进行安装,以简化安装和升级任务。这是推荐的方法。
  • 一些用户下载并手动安装 RPM软件包, 并完全手动管理升级。这在诸如在无法访问互联网的空白系统上安装Docker的情况下非常有用。
  • 在测试和开发环境中,一些用户选择使用自动 便利脚本来安装Docker。

3.2.1使用存储库安装

在新主机上首次安装Docker Engine之前,需要设置Docker存储库。之后,您可以从存储库安装和更新Docker。
设置存储库
安装yum-utils软件包(提供yum-config-manager 实用程序)并设置稳定的存储库。

$ sudo yum install -y yum-utils
官网的yum源,国外
$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
国内阿里的yum源
    https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

3.3安装DOCKER引擎


安装最新版本的Docker Engine和容器,或转到下一步以安装特定版本:

$  sudo yum install docker-ce docker-ce-cli containerd.io 

如果提示您接受GPG密钥,请验证指纹是否匹配

060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35,如果是,则接受它。

有多个Docker存储库?
如果启用了多个Docker存储库,则在未在yum installor yum update命令中指定版本的情况下进行安装或更新将始终安装可能的最高版本,这可能不适合您的稳定性需求。
启动Docker

$ sudo systemctl start docker

通过运行hello-world 映像来验证是否正确安装了Docker Engine 。

此命令下载测试图像并在容器中运行它。容器运行时,它会打印参考消息并退出。

Docker Engine已安装并正在运行。您需要使用sudo来运行Docker命令。

四.docker镜像

4.1 docker 镜像原理

如果只考虑 Docker 容器的操作系统属性,那么镜像=轻量级操作系统安装包。

如果需考虑 Docker 容器的应用软件属性,那么镜像=(轻量级操作系统+应用)安装包

镜像是怎么产生的?

镜像从逻辑上可以简单理解是一个文件,但实际上是多层文件的组合。

所以,镜像虽然不是一个单独的文件,但可以被导出成为一个压缩文件:

# 镜像导出成一个tarball文件
docker save image

# 加载一个 tarball 镜像文件
docker load image

镜像存放在哪里?运行容器时,Docker 会从 /var/lib/docker/image 目录下寻找是否镜像文件。

镜像可以看成是由多个镜像层叠加起来的一个文件系统(通过UnionFS与AUFS文件联合系统实现),镜像层也可以简单理解为一个基本的镜像,而每个镜像层之间通过指针的形式进行叠加。

1.png
2.png

根据上图,镜像层的主要组成部分包括镜像层 ID、镜像层指针 「指向父层」、元数据「 Layer Metadata,包含了 Docker 构建和运行的信息和父层的层次信息」。只读层和读写层「Top Layer」的组成部分基本一致,同时读写层可以转换成只读层「 通过docker commit 操作实现」。

元数据(metadata)就是关于这个层的额外信息,它不仅能够让Docker获取运行和构建时的信息,还包括父层的层次信息。需要注意,只读层和读写层都包含元数据。

3.png

每一层都包括了一个指向父层的指针。如果一个层没有这个指针,说明它处于最底层。

4.png

在docker主机中镜像层(image layer)的元数据被保存在名为”json”的文件中,一个容器的元数据好像是被分成了很多文件,但或多或少能够在/var/lib/docker/containers/目录下找到,就是一个可读层的id。这个目录下的文件大多是运行时的数据,比如说网络,日志等等。

镜像是一堆只读层的统一视角,除了最底层没有指向外,每一层都指向它的父层。统一文件系统( Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在。在用户的角度看来,只存在一个文件系统。镜像每一层都是不可写的,都是只读层。

5.png

我们可以看到镜像包含多个只读层,它们重叠在一起。除了最下面一层,其它层都会有一个指针指向下一层。这些层是Docker内部的实现细节,并且能够在docker主机的文件系统上访问到。统一文件系统(union file system,升级版为AUFS)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。

4.2docker镜像管理

镜像搜索-search

从docker镜像仓库模糊搜索镜像
用法:

------------

    docker search 镜像关键字

[root@docker~]# docker search centos

NAME          DESCRIPTION           STARS     OFFICIAL        AUTOMATED
centos   The official build of CentOS.   5674   [OK]                

#字段说明:
NAME:镜像名称
DESCRIPTION:镜像描述 
STARS:镜像星级,数字越大表示用的人越多
OFFICIAL:是否为官方  跟[OK]说明是官方
AUTOMATED: 是否为自动化构建的镜像

镜像下载-pull命令

从docker指定的仓库下载镜像到本地命令
docker pull 镜像名称

[root@docker~]# docker pull centos

Using default tag: latest
latest: Pulling from library/centos
729ec3a6ada3: Pull complete 
Digest: sha256:f94c1d992c193b3dc09e297ffd54d8a4f1dc946c37cbeceb26d35ce1647f88d9
Status: Downloaded newer image for centos:latest
docker.io/library/centos:latest

本地镜像查看-images命令

查看本地存储的镜像

[root@docker ~]# docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
docker.io/gitlab/gitlab-ce   latest              515ad1a75677        7 weeks ago         1.9 GB
docker.io/redis              latest              1319b1eaa0b7        7 weeks ago         104 MB

#字段说明:
REPOSITORY:镜像的名字
TAG:镜像的标签
IMAGE ID:镜像的ID号
CREATED:镜像建立时间
SIZE: 镜像大小

镜像详细信息-inspect命令

显示镜像的详细导入由save保存出来的压缩文件镜像
docker load -i 镜像压缩文件名称 [镜像名称或者ID]

[root@docker~]# docker load -i centos_base.tar 

Loaded image: centos:latest信息

用法:
    docker inspect [镜像名称或者ID]

[root@docker~]# docker inspect 0f3e07c0138f 
[
    {
        "Id": "sha256:0f3e07c0138fbe05abcb7a9cc7d63d9bd4c980c3f61fea5efa32e7c4217ef4da",
        "RepoTags": [
            "centos:latest"
        ],
        "RepoDigests": [
            "centos@sha256:f94c1d992c193b3dc09e297ffd54d8a4f1dc946c37cbeceb26d35ce1647
.................此除省略

本地镜像删除-rmi命令

删除本地镜像库中的某个镜像命令:
docker rmi [镜像名称或者ID]

[root@docker~]# docker rmi centos

Untagged: centos:latest
Untagged: centos@sha256:f94c1d992c193b3dc09e297ffd54d8a4f1dc946c37cbeceb26d35ce1647f88d9
Deleted: sha256:0f3e07c0138fbe05abcb7a9cc7d63d9bd4c980c3f61fea5efa32e7c4217ef4da
Deleted: sha256:9e607bb861a7d58bece26dd2c02874beedd6a097c1b6eca5255d5eb0d2236983

镜像保存-save命令

保存镜像为压缩文件命令:

docker save -o 压缩文件名称 [镜像名称或者ID

[root@docker~]# docker save -o centos_base.tar centos

[root@docker~]# ls

anaconda-ks.cfg  centos_base.tar

镜像载入-load命令

导入由save保存出来的压缩文件镜像命令:

docker load -i 镜像压缩文件名称 [镜像名称或者ID]

[root@docker~]# docker load -i centos_base.tar 

Loaded image: centos:latest

镜像管理命令-image命令

镜像管理命令,和上面的命令相似

[root@docker~]# docker image --help
Usage:  docker image COMMAND
Manage images

Commands:
  build       Build an image from a Dockerfile
  history     Show the history of an image
  import      Import the contents from a tarball to create a filesystem image
  inspect     Display detailed information on one or more images
  load        Load an image from a tar archive or STDIN
  ls          List images
  prune       Remove unused images
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rm          Remove one or more images
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE

五.docker容器

5.1 容器概念

容器是 Docker 最重要的组件,容器就是一个轻量级虚拟机。

5.2容器管理

5.2.1 docker ps

显示本地容器列表,但是默认不显示关闭的容器,只显示运行中的容器,除非加上命令选项 -a
docker ps [-a 显示所有容器,默认只显示运行的]

root@docker~]# docker ps
CONTAINER ID      IMAGE   COMMAND           CREATED    STATUS     PORTS      NAMES
8f4c3f823843    centos  "/bin/bash"  3 seconds ago  Exited(0) 3 seconds ago     centos7_6

5.2.2 docker inspect

显示容器的详细信息
docker inspect [容器名称或者ID]

[root@docker~]# docker inspect centos
[
    {
        "Id": "sha256:0f3e07c0138fbe05abcb7a9cc7d63d9bd4c980c3f61fea5efa32e7c4217ef4da",
        "RepoTags": [
            "centos:latest",
            "docker_centos:v1"
        ],
        "RepoDigests": [],
        "Parent": "",
        "Comment": "",
        "Created": "2019-10-01T23:19:57.105928163Z",
        "Container": "711572e3c0c1ac06d5c13c4e668ec170b8ad8786b5f0949f884a5f7fd350d856",
        "ContainerConfig": {
            "Hostname": "711572e3c0c1",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
 .........此处省略

5.2.3 docker run

容器创建命令
docker run [options] 镜像名称

#后台执行容器

[root@docker~]# docker run -d --name centos7_6 centos 

#前台执行的容器

[root@docker~]# docker run -it --name centos7_5  centos /bin/bash

[root@5a1f02b4041c /]# 

-i 交互式创建
-t 创建一个伪终端
-d 后台执行
--name 容器名称
/bin/bash 在伪终端中执行的命令
5.2.4 docker rm

删除一个本地容器
docker rm [容器名称或者ID] [–force]

[root@docker~]# docker rm centos7_5
centos7_5

默认删除的容器必须是关闭状态,建议如果希望删除一个运行的容器,可以先关闭在删除。
当然也可以在后面直接加上--force 强制删除一个运行中的容器
容器执行命令-exec命令

在运行容器中执行一个命令,如果想在容器中执行一个命令,那么这个exec命令就很有用了。

docker exec [容器名称或者ID] 命令

[root@docker~]# docker exec centos7_6 ls /
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
容器信息输出-attach命令

将一个运行容器的标准输出、错误输出、标准输入调入前台
默认容器都会在后台运行,如果你想进入容器内,就可以使用该命令。这样你就可以交互式的在容器中执行命令了。
docker attach [容器名称或者ID]

[root@docker~]# docker attach centos7_6

[root@128dc0ffc489 /]# 
容器启动-start命令

启动一个容器
docker start [容器名称或者ID]

[root@docker~]# docker start centos7_6
centos7_6
停止一个容器-stop命令

关闭一个容器
docker stop [容器名称或者ID]

[root@docker~]# docker stop centos7_6
centos7_6
重启一个容器-restart命令

重启一个容器
docker restart [容器名称或者ID]

[root@docker~]# docker restart centos7_6
centos7_6
容器挂起-pause命令

挂起运行中的容器


docker pause [容器名称或者ID]

[root@docker~]# docker pause centos7_6

centos7_6

[root@docker~]# docker ps

CONTAINER ID     IMAGE     COMMAND     CREATED  STATUS    PORTS  NAMES
128dc0ffc489  centos "/bin/bash" 19 minutes ago  Up 14 minutes (Paused)    centos7_6
容器恢复-unpause命令

恢复挂起容器
docker unpause [容器名称或者ID]

[root@docker~]# docker unpause centos7_6
centos7_6
容器重命名-rename命令

重命名容器
docker rename 容器名称 容器新名称

[root@docker~]# docker rename centos7_6 centos76
容器端口映射信息-port命令

显示容器与宿主机的端口隐射信息
docker port [容器名称或者ID]

[root@docker~]# docker port 32fd02f05446
5000/tcp -> 0.0.0.0:5000

容器的TCP 5000端口与宿主机的所有IP的5000端口绑定

杀死一个或多个容器-kill命令

杀死运行的容器
docker kill [镜像名称或者ID]

[root@docker~]# docker kill centos76
centos76
容器导出-export命令

将一个容器导出一个镜像为压缩文件
docker export -o 导出后镜像文件名 [容器名称或者ID]

[root@docker~]# docker export -o docker_centos.tar centos76

[root@docker~]# ls

anaconda-ks.cfg  centos_base.tar  Docker  docker_centos.tar
容器镜像导入到镜像库-import命令

将容器镜像导入到镜像库
docker import 镜像文件名 镜像名:tag

[root@docker ~]# docker import docker_centos.tar docker/centos7_6:latest
sha256:659fb2fca656430822627685ba4f29d09ae619cd9f2b42ef52d47003c8af8d11
将容器生成镜像-commit命令

将改变后的容器直接变成镜像,一般指的是封装好业务的容器,直接封装成镜像
docker commit [容器名称或者ID] 导出后镜像的名字:tag

[root@docker~]# docker commit  centos76   docker/centos_7_6:v1

sha256:1f078c1d94dd641c65495bd91d3e471593c5ec60ecbb4492cfa18a161448dd3a

六.docker 网络

由于容器是用于部署应用的,因此它需要频繁的被其他服务所访问,深刻理解 Docker 网络的概念和原理就显得至关重要。

6.1 docker 网络介绍

组网

对于Docker系统来说,默认有一个容器路由功能,简单的说,Docker会给每个部署好的Container生成一个内网IP地址。例如,Docker下运行了容器,Docker就自动分配了3个内网地址:

容器1 172.18.0.1
容器2 172.18.0.2
容器3 172.18.0.23

对于其中任何Container来说,都可以通过IP地址作为访问通道

端口

每个Container,都可以映射到服务器的一个端口上,以便于外部访问这个Container。 例如:172.18.0.1 上运行了MySQL,且MySQL本身开启了外部访问。这个时候,如何通过服务器的IP地址来访问这个MySQL呢?

  1. 首先,将容器1的做一个端口映射,加入映射到都服务器的3306端口
  2. 然后,通过 服务器IP:3306 就可以访问MySQL

问题:Container中的应用为什么有端口号?Container是带最简的操作系统的,有操作系统就一定会通过端口访问程序

6.2 docker network 网络管理

[root@docker~]# 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.

6.3 docker网络类型

创建容器的时候可以通过—network命令来指定容器的网络,网络类型有以下四种

  • bridge
  • host
  • none
  • 容器网络或联盟网络
bridge

桥接网络是指容器通过桥接的方式将容器网卡桥接到宿主机的docker0网桥,然后在通过宿主机防火墙的NAT表实现与外网的联系。

宿主机docker0网桥
[root@docker~]# ifconfig 
#docker0网桥
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:c7ff:fe37:8e8  prefixlen 64  scopeid 0x20<link>
        ether 02:42:c7:37:08:e8  txqueuelen 0  (Ethernet)
        RX packets 6618  bytes 277975 (271.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8152  bytes 24675021 (23.5 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

.....省略了本机的网卡信息
#容器网卡,每创建一个桥接网络的容器就会生成一个对应的网卡
vethf75a942: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::9085:f5ff:fe34:77b5  prefixlen 64  scopeid 0x20<link>
        ether 92:85:f5:34:77:b5  txqueuelen 0  (Ethernet)
        RX packets 2850  bytes 158484 (154.7 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3397  bytes 11613136 (11.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

如果想看更清楚一下  可以使用  ip  add  show命令
[root@docker~]# ip add show

4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:c7:37:08:e8 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:c7ff:fe37:8e8/64 scope link 
       valid_lft forever preferred_lft forever

容器网卡
14: vethf75a942@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 92:85:f5:34:77:b5 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::9085:f5ff:fe34:77b5/64 scope link 
       valid_lft forever preferred_lft forever

注意:
这里的vethf75a942@if13指的就是容器网卡,V代表虚拟网卡的意思,eth 以太网卡,f75a942网卡编号,if13指的是宿主机网桥(docekr0)的一个端口,对应容器的网卡编号加一。
所以容器内的网卡编号应该是 eth0@if14

通过在容器中执行命令  ip add show 也可以看到
[root@docker~]# docker exec centos1 ip add show
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
13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
防火墙的NAT表内容
[root@docker~]# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere            !loopback/8           ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        anywhere            

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere        
docker0 与容器网卡桥接
通过brctl show命令可以看到容器网卡和docker0网卡的桥接信息
[root@docker~]# brctl show
bridge name bridge id       STP enabled interfaces
docker0     8000.0242c73708e8   no      vethf75a942

创建一个网络为bridge类型的容器,不指定默认也是这个类型

[root@docker~]# docker run -d --network bridge --name centos1 baishuming2020/centos_nginx
host

容器和真机共用网卡及对应的端口,缺点就是同一个端口只能宿主机或者某个容器使用,其他容器不能用。

创建一个网络类型host的容器
[root@docker~]# docker run -d --network host --name centos2 baishuming2020/centos_nginx
none

容器仅有lo网卡,是一个不能联网的本地容器

创建一个网络类型为lo的容器
[root@docker~]# docker run -d --network none --name centos3 baishuming2020/centos_nginx

6.4 实现网桥网络

目的:不同的服务容器组应用不同的网桥,避免同一网络内容器太多,保持容器网络独立性。

关于新网桥联网问题:创建网桥后,宿主机会自动帮你做NAT,所以不用担心联网问题

查看网络-ls
[root@docker ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
80982d2613cd        bridge              bridge              local
40c179ab420a        docker1             bridge              local
04aadb7475c0        docker100           bridge              local
ce79e9d7525a        host                host                local
8f0358469e57        none                null                local

NETWORK ID     网桥ID   
NAME           名称
DRIVER         网络类型  
SCOPE                    作用范围
创建网桥-create
[root@docker~]# docker network create -d bridge --subnet 192.168.1.0/24 --gateway 192.168.1.1 mydocker0
6a410e27b66ea587142d967f7dff6f36c04ced3c27116a79831412f3743aba56

[root@docker~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
6ee1e928b710        bridge              bridge              local
ce79e9d7525a        host                host                local
6a410e27b66e        mydocker0           bridge              local
8f0358469e57        none                null                local

修改docker网桥名字
1、关闭新建网桥
[root@docker~]# ip link set dev br-6a410e27b66e down
2、修改名字
[root@docker~]# ip link set dev br-6a410e27b66e name  mydocker0
3、启动网桥
[root@docker~]# ip link set dev mydocker0 up
4、重启docker服务
[root@docker~]# systemctl restart docker
删除未使用的网桥-prune
[root@docker~]# docker network prune 
WARNING! This will remove all networks not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Networks:
docker1
删除某个网桥-rm
[root@docker~]# docker network rm docker100
docker100

注意:
不能被活动容器占用
容器连接到网桥

前提是该容器是桥接网络

[root@docker~]# docker network connect docker1 centos1
[root@docker~]# docker exec centos1 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
发现centos1容器多了一块网卡,使用的正是docker1的网段
eth2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.2  netmask 255.255.255.0  broadcast 192.168.1.255
        ether 02:42:c0:a8:01:02  txqueuelen 0  (Ethernet)
        RX packets 16  bytes 1312 (1.2 KiB)
        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
容器断开网桥
将centos1容器的网络从docker1网桥断开
[root@docker~]# docker network disconnect docker1 centos1

6.5 docker 网络常见故障

FAQ1:使用改名后的新网桥的容器可能无法解析域名

原因:没有配置新网桥的DNS

解决方法:为容器手动配置一个DNS地址即可

FAQ2:Networking will not work
[root@docker~]# docker run -d --network docker100 --name centos4 baishuming2020/centos_nginx
WARNING: IPv4 forwarding is disabled. Networking will not work.
67f2c276123c993cd66b9d7a99ba22402331a13f9ea8817e57324a934896b805

解决方案
1、打开转发
[root@docker~]# echo "net.ipv4.ip_forward=1" >>  /usr/lib/sysctl.d/00-system.conf

2、重启网络
[root@docker~]# systemctl restart network

6.6 docker 不通主机之间通信

macvlan

在 Docker 中,macvlan 是众多 Docker 网络模型中的一种,并且是一种跨主机的网络模型,作为一种驱动启用,Docker macvlan 只支持 bridge 模式

#macvlan 需要一块独立的网卡来进行使用,所以我们需要新添加一块网卡

docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1  -o parent=ens224  mtacvlan-1

-o parent=网卡名称  指定用来给 macvlan 网络使用的物理网卡

注意,要在所有需要运行 macvlan 的主机上执行这条命令,但是要记得更改网关的地址,避免造成IP冲突

docker run -itd --network macvlan-1 centos /bin/bash
overlay

在 Docker 中,overlay 是众多 Docker 网络模型中的一种,并且是一种跨主机的全局网络模型,有一个数据库专门的来存储网络分配信息,避免 IP 冲突,同时内部还有一个小型的 DNS 我们可以直接通过主机名进行访问

consul 服务端:
docker run -itd -h consul --name consul --restart=always -p 8500:8500 progrium/consul -server -bootstrap

-h              主机名
–name           容器名
–restart=always 重启策略
progrium/consul 镜像名称
-server         以服务节点启动
-bootstrap      预期的启动节点数:自举

在浏览器内输入 IP地址+端口号 可以看到 web 页面

在所有主机上编辑 daemon.json 文件:
{
"hosts": ["tcp://0.0.0.0:2375","unix:///var/run/docker.sock"], 监听相关端口
"cluster-store":"consul://192.168.1.150:8500",         集群的主机地址
"cluster-advertise":"192.168.1.150:2375”        宣告自己的地址 
}

重启 docker 服务

创建 overlay 网络(全局网络):一台主机上创建自动同步

    docker network create -d overlay overlay-1

启动容器测试:

    docker run -it --name docker-1 --network=overlay-1 centos /bin/bash

    docker run -it --name docker-2 --network=overlay-1 centos /bin/bash

验证:ping docker-1

七.dockerfile

7.1 什么是Dockerfile

Dockerfile 是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。它们简化了从头到尾的流程并极大的简化了部署工作。Dockerfile 从 FROM 命令开始,紧接着跟随着各种方法,命令和参数。其产出为一个新的可以用于创建容器的镜像。

Dockerfile 语法由两部分构成,注释和命令+参数,注释是不能少的,因为明天可能就忘记写的是什么了。说白了, Dockerfile 是告诉 docker 怎么样制作一个镜像,就像我们写代码告诉应用怎么执行一条逻辑,这样应该好理解了,所以可以在 Dockerfile 中写明,我们需要怎么个执行方式的某个镜像,最后执行 docker build 命令构建写好的Dockerfile 成镜像。

7.2 Dockerfile基础命令

FROM:
#功能为指定基础镜像,并且必须是第一条指令,如果没有选择,那么默认值为latest

MAINTAINER:
#指定作者

LABEL
#功能是为镜像指定标签
一个Dockerfile种可以有多个LABEL,如下:
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
但是并不建议这样写,最好就写成一行,如太长需要换行的话则使用\符号
如下:
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"
注意:LABEL会继承基础镜像种的LABEL,如遇到key相同,则值覆盖

RUN
##功能为运行指定的命令

​RUN命令有两种格式,两种写法比对:
​RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME
​RUN ["/bin/bash", “-c”, “echo hello”]
注意:多行命令不要写多个RUN,原因是Dockerfile中每一个指令都会建立一层. RUN书写时的换行符是 \ 多少个RUN就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。

ADD
##一个复制命令,把文件复制到镜像中
##​如果把虚拟机与容器想象成两台linux服务器的话,那么这个命令就类似于scp,只是scp需要加用户名和密码的权限验证,而ADD不用

语法如下:
ADD <src>... <dest>
<src>可以是一个本地文件或者是一个本地压缩文件,还可以是一个url
<dest>路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径
ADD test1.txt test1.txt
ADD test1.txt test1.txt.bak
ADD test1.txt /mydir/
ADD data1 data1
ADD zip.tar /myzip

有如下注意事项:
1、如果源路径是个文件,且目标路径是以 / 结尾, 则docker会把目标路径当作一个目录,会把源文件拷贝到该目录下。如果目标路径不存在,则会自动创建目标路径。
2、如果源路径是个文件,且目标路径不是以 / 结尾,则docker会把目标路径当作一个文件。
3、如果目标路径不存在,会以目标路径为名创建一个文件,内容同源文件;
4、如果目标文件是个存在的文件,会用源文件覆盖它,当然只是内容覆盖,文件名还是目标文件名。
5、如果目标文件实际是个存在的目录,则会源文件拷贝到该目录下。 注意,这种情况下,最好显示的以 / 结尾,以避免混淆。
6、如果源路径是个目录,且目标路径不存在,则docker会自动以目标路径创建一个目录,把源路径目录下的文件拷贝进来。如果目标路径是个已经存在的目录,则docker会把源路径目录下的文件拷贝到该目录下。
7、如果源文件是个归档文件(压缩文件),则docker会自动帮解压。尽量不要把<scr>写成一个文件夹,如果<src>是一个文件夹了,复制整个目录的内容,包括文件系统元数据

VOLUME
可实现挂载功能,可以将内地文件夹或者其他容器种得文件夹挂在到这个容器种
语法为:
​VOLUME ["/data"]
​说明:
​["/data"]可以是一个JsonArray ,也可以是多个值。所以如下几种写法都是正确的
​VOLUME ["/var/log/"]
​VOLUME /var/log
VOLUME /var/log /var/db
​一般的使用场景为需要持久化存储数据时, 容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失,所以当数据需要持久化时用这个命令。

EXPOSE
​##功能为暴漏容器运行时的监听端口给外部,但是EXPOSE并不会使容器访问主机的端口
​如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上 -P参数

WORKDIR
​设置工作目录
WORKDIR /usr/bin/

ENV
功能为设置环境变量

CMD
​功能为容器启动时要运行的命令

​CMD [ “echo”, “$HOME” ]
​注意:
​1、这里边包括参数的一定要用双引号,就是 " 不能是单引号, 原因是参数传递后,docker解析的是一个JSON Array
​2、不要把RUN和CMD搞混了。
​RUN:是构件容器时就运行的命令以及提交运行结果
CMD:是容器启动时执行的命令,在构件时并不运行

ENTRYPOINT
功能是启动时的默认命令
​语法如下:
​ENTRYPOINT [“executable”, “param1”, “param2”]
ENTRYPOINT ​command param1 param2
​如果从上到下看到这里的话,那么你应该对这两种语法很熟悉啦。
​第一种就是可执行文件加参数
第二种就是写shell
与 CMD 比较说明:
相同点:
只能写一条,如果写了多条,那么只有最后一条生效,容器启动时才运行,运行时机相同
不同点:
ENTRYPOINT 不会被运行的 command 覆盖,而 CMD 则会被覆盖

如果我们在 Dockerfile 时同时写了 ENTRYPOINT 和 CMD ,并且 CMD 指令不是一个完整的可执行命令,那么CMD 指定的内容将会作为 ENTRYPOINT 的参数, 如下:

FROM centos
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
如果我们在 Dockerfile 种同时写了 ENTRYPOINT 和 CMD ,并且 CMD 是一个完整的指令,那么它们两个会互相覆盖,谁在最后谁生效, 如下:
FROM centos
ENTRYPOINT ["top", "-b"]
CMD ls -al
那么将执行 ls -al , top -b 不会执行

7.2 Dockerfile 案例

1、创建目录,用于存放 dockerfile 所使用的文件
2、在此目录中创建 dockerfile 文件
3、在此目录中使用 docker build 创建镜像
4、使用创建的镜像启动容器

准备启动文件:
vim httpd-run.sh
#!/bash
rm -rf /run/httpd/*
exec /usr/sbin/httpd -D FOREGROUND

准备网页测试文件
vim index.html
hello welcome to zutuanxue!!!

准备 dockerfile 文件

FROM centos:latest

MAINTAINER "zutuanxue admin@163.com" 

ADD httpd-run.sh /httpd-run.sh

ADD index.html /var/www/html/index.html

RUN yum -y install httpd && chmod -v +x /httpd-run.sh

EXPOSE 80

WORKDIR /

CMD ["/bin/bash","/httpd-run.sh"]

创建镜像:
docker build -t centos-httpd:v1 .

 -t: 镜像的名字及标签,通常 name:tag 或者 name 格式
#定义基础镜像 FROM
FROM centos
#定义作者 MAINTAINER
MAINTAINER test_123

#上传文件到容器 COPY  or ADD
#COPY 从当前目录复制文件到容器. 只是单纯地复制文件. 格式为 COPY <src> <dest>。
#ADD 从当前目录复制文件到容器. 会自动处理目录, 压缩包等情况.格式为 ADD <src> <dest>。
ADD nginx-1.17.6.tar.gz /root

#生成镜像时运行的命令 RUN
#shell 写法
RUN yum -y install pcre-devel zlib-devel openssl lsof iproute net-tools gcc make
#exec写法
#["命令","命令选项","参数"]

#解压压缩文件
#RUN ["tar","xf","nginx-1.17.6.tar.gz"]

#创建管理用户www
RUN useradd -r -s/sbin/nologin -M www

#进入nginx源码文件WORKDIR
WORKDIR /root/nginx-1.17.6

#安装nginx
RUN ./configure --prefix=/usr/local/nginx --user=www --group=www && make && make install

#定义变量 ENV
ENV PATH /usr/local/nginx/sbin:$PATH

#业务初始化
#COPY 从当前目录复制文件到容器. 只是单纯地复制文件. 格式为 COPY <src> <dest>。
COPY nginx.conf /usr/local/nginx/conf
COPY index.html /usr/local/nginx/html

#输出端口 EXPOSE
EXPOSE 80

#挂载本地目录VOLUME
#创建一个可以从本地主机或其他容器挂载的挂载点
#一般用来存放数据库和需要保持同步的数据
VOLUME ["/data"]

#容器启动后执行的命令  CMD
#只能执行一个,如果有多个,同一时间只有最后一个生效
CMD ["nginx","-g","daemon off;"]

八.docker Compost

8.1 什么是Docker Compose

Compose 项目是 Docker 官方的开源项目,负责实现 Docker 容器集群的快速编排,开源代码在 https://github.com/docker/compose 上

​我们知道使用 Dockerfile 模板文件可以让用户很方便的定义一个单独的应用容器,其实在工作中,经常会碰到需要多个容器相互配合来完成的某项任务情况,例如工作中的 web 服务容器本身,往往会在后端加上数据库容器,甚至会有负责均衡器,比如 LNMP 服务

Compose 就是来做这个事情的,它允许用户通过一个单独的 docker-compose.yml 模板文件 YAML格式 来定义一组相关联的应用容器为一个项目 project

Compose 中有两个重要的概念:

服务 service :一个应用的容器,实际上可以包括若干运行相同镜像的容器实例
项目 project :由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml中定义

8.2 安装

# docker-compose版本选择:https://github.com/docker/compose/releases
# curl -L https://github.com/docker/compose/releases/download/1.25.4/docker-compose-uname -s-uname -m -o /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose

8.3 命令

Compose 大部分命令的对象即可以是项目的本身,也可以是指定为项目中的服务或者容器
执行docker-compose [COMMAND] --help 或者docker-compose help [COMMAND]可以查看命令的帮助信息
具体的使用格式
docker-compose [-f=<arg>...] [options] [COMMAND] [ARGS]
参数选项
-f,--file file指定模板文件,默认是docker-compose.yml模板文件,可以多次指定
-p,--project-name name指定项目名称,默认使用所在目录名称作为项目名称
--x-networking 使用Docker的后端可插拔网络特性
--x-networking-driver driver指定网络的后端驱动,默认使用bridge
--verbose 输入更多的调试信息
-v,--version 输出版本信息

Compose所支持的命令:

build            构建项目中的服务容器 
bundle     从Compose文件生成分布式应用程序包 
config     验证并查看Compose文件 
create     为服务创建容器 
down       停止容器并删除由其创建的容器,网络,卷和图像up 
events     为项目中的每个容器流式传输容器事件 
exec       这相当于docker exec。 
help       获得一个命令的帮助 
kill       通过发送SIGKILL信号来强制停止服务容器 
logs       查看服务容器的输出 
pause      暂停一个容器 
port       打印某个容器端口所映射的公共端口 
ps         列出项目中目前所有的容器 
pull       拉取服务依赖镜像 
push       推送服务镜像 
restart    重启项目中的服务 
rm         删除所有停止状态的服务容器 
run        在指定服务上执行一个命令 
scale      设置指定服务执行的容器个数 
start      启动已存在的服务容器 
stop       停止已存在的服务容器 
top        显示容器正在运行的进程 
unpause    恢复处于暂停状态的容器 
up         自动完成包括构建镜像、创建服务、启动服务并关联服务相关容器的一系列操作 
version    输出版本 

1.4 模板文件

排版问题,请看单独的文件。
官网链接:https://docs.docker.com/compose/compose-file/#compose-file-structure-and-examples

八.docker 镜像私有仓库

8.1 harbor镜像仓库

Harbor离线安装包下载地址:https://github.com/goharbor/harbor

docker-compose版本选择:https://github.com/docker/compose/releases

8.1 docker-compose 下载安装

容器编排工具,执行./install.sh时需要。如果不安装,一会重启docker服务,相关的harbor容器会死掉,安装后就会被随着docker重启

#####由于github在国外服务器,推荐是本地下载后上传服务器
wget https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-linux-x86_64
mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose

[root@docker-harbor harbor]# docker-compose -v
Docker Compose version v2.2.2

8.2 harbor下载安装

#####由于github在国外服务器,推荐是本地下载后上传服务器

[root@docker-harbor harbor]# tar -zxvf harbor-offline-installer-v2.4.1.tgz

[root@docker-harbor harbor]# mv harbor /opt/
mv harbor.yml.tmpl  harbor.yml
####修改hostname 内网ip
cat /opt/harbor/harbor.yml  
hostname: 192.168.232.60
###将harbor.yml 文件中  ssl 证书部分注释掉
#https:
  # https port for harbor, default is 443
  #port: 443
  # The path of cert and key files for nginx
  #certificate: /your/certificate/path
  #private_key: /your/private/key/path
[root@docker-harbor harbor]# /opt/harbor/prepare 
.......
✔ ----Harbor has been installed and started successfully.----

2.3 docker设置仓库为harbor

创建docker守护进程配置文件 
[root@centos8_manage01 harbor]# cat /etc/docker/daemon.json 
{
      "insecure-registries": ["http://192.168.232.60"]
}

修改

8.4 镜像上传到harbor

#登陆harbor
[root@centos8_manage01 harbor]# docker login http://192.168.232.60 -u admin -p Harbor12345
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
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

#修改镜像name:tag为harbor仓库名
[root@docker_harbor ~]# docker pull nginx
##打标签
[root@docker_harbor ~]# docker tag nginx:latest 192.168.232.60/jyl/jyl_nginx:v1

#上传镜像
[root@centos8_manage01 harbor]# docker push 192.168.232.60/jyl/jyl_nginx:v1

8.5 问题说明: