Docker入门,这一篇就够了,建议收藏 您所在的位置:网站首页 ldap_search数量太多报错 Docker入门,这一篇就够了,建议收藏

Docker入门,这一篇就够了,建议收藏

2023-02-02 09:18| 来源: 网络整理| 查看: 265

一、Docker 是什么?

Docker,翻译过来就是码头工人

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

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

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

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

docker官网:https://www.docker.comdocker中文库:https://www.docker.org.cn/

二、Docker 容器技术与虚拟机的区别

Docker 到底是个什么东西呢?我们在理解 Docker 之前,首先得先区分清楚两个概念,容器和虚拟机。

虚拟机

虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统。在实体计算机中能够完成的工作在虚拟机中都能够实现。在计算机中创建虚拟机时,需要将实体机的部分硬盘和内存容量作为虚拟机的硬盘和内存容量。每个虚拟机都有独立的CMOS、硬盘和操作系统,可以像使用实体机一样对虚拟机进行操作。

可能很多读者朋友都用过虚拟机,而对容器这个概念比较的陌生。我们用的传统虚拟机如 VMware , VisualBox 之类的需要模拟整台机器包括硬件。

每台虚拟机都需要有自己的操作系统,虚拟机一旦被开启,预分配给它的资源将全部被占用。

每一台虚拟机包括应用,必要的二进制和库,以及一个完整的用户操作系统。

容器

Docker 容器是一个开源的应用容器引擎,让开发者可以以统一的方式打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何安装了docker引擎的服务器上(包括流行的Linux机器、windows机器),也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app)。几乎没有性能开销,可以很容易地在机器和数据中心中运行。最重要的是,他们不依赖于任何语言、框架包括系统。

而容器技术是和我们的宿主机共享硬件资源及操作系统,可以实现资源的动态分配。

容器包含应用和其所有的依赖包,但是与其他容器共享内核。容器在宿主机操作系统中,在用户空间以分离的进程运行。

容器技术是实现操作系统虚拟化的一种途径,可以让您在资源受到隔离的进程中运行应用程序及其依赖关系。

通过使用容器,我们可以轻松打包应用程序的代码、配置和依赖关系,将其变成容易使用的构建块,从而实现环境一致性、运营效率、开发人员生产力和版本控制等诸多目标。

容器可以帮助保证应用程序快速、可靠、一致地部署,其间不受部署环境的影响。

容器还赋予我们对资源更多的精细化控制能力,让我们的基础设施效率更高。

对比相同点

docker和容器技术和虚拟机技术,都是虚拟化技术。

不同点

通过下面这幅图,我们可以很直观的反映出这两者的区别所在:

Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。

而 Linux 容器是 Linux 发展出的另一种虚拟化技术,简单来讲, Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离,相当于是在正常进程的外面套了一个保护层。

对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离。

Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。

程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker ,就不用担心环境问题。

总体来说,Docker 的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。

Docker 的优势

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 中记录了容器构建过程,可在集群中实现快速分发和快速部署。

我们可以从下面这张表格很清楚地看到容器相比于传统虚拟机的特性的优势所在:

Docker局限性

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

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

从上图我们可以看到,Docker 中包括三个基本的概念:

Image(镜像)Container(容器)Repository(仓库)

镜像是 Docker 运行容器的前提,仓库是存放镜像的场所,可见镜像更是 Docker 的核心。

Image(镜像)

那么镜像到底是什么呢?Docker 镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。

镜像不包含任何动态数据,其内容在构建之后也不会被改变。镜像(Image)就是一堆只读层(read-only layer)的统一视角,也许这个定义有些难以理解,下面的这张图能够帮助读者理解镜像的定义:

从左边我们看到了多个只读层,它们重叠在一起。除了最下面一层,其他层都会有一个指针指向下一层。这些层是 Docker 内部的实现细节,并且能够在主机的文件系统上访问到。

统一文件系统(Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角。

这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。我们可以在图片的右边看到这个视角的形式。

Container(容器)

容器(Container)的定义和镜像(Image)几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。

由于容器的定义并没有提及是否要运行容器,所以实际上,容器 = 镜像 + 读写层。

Repository(仓库)

Docker 仓库是集中存放镜像文件的场所。镜像构建完成后,可以很容易的在当前宿主上运行。

但是, 如果需要在其他服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry(仓库注册服务器)就是这样的服务。

有时候会把仓库(Repository)和仓库注册服务器(Registry)混为一谈,并不严格区分。

Docker 仓库的概念跟 Git 类似,注册服务器可以理解为 GitHub 这样的托管服务。

实际上,一个 Docker Registry 中可以包含多个仓库(Repository),每个仓库可以包含多个标签(Tag),每个标签对应着一个镜像。

所以说,镜像仓库是 Docker 用来集中存放镜像文件的地方,类似于我们之前常用的代码仓库。

通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。

我们可以通过:的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 Latest 作为默认标签。

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

Public(公有仓库)Private(私有仓库)

Docker Registry 公有仓库是开放给用户使用、允许用户管理镜像的 Registry 服务。

一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。

除了使用公开服务外,用户还可以在本地搭建私有 Docker Registry。Docker 官方提供了 Docker Registry 镜像,可以直接使用做为私有 Registry 服务。

当用户创建了自己的镜像之后就可以使用 Push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 Pull 下来就可以了。最大的公开仓库是 Docker Hub(https://hub.docker.com/),存放了数量庞大的镜像供用户下载。国内的公开仓库包括阿里云 、网易云等。

我们主要把 Docker 的一些常见概念如 Image,Container,Repository 做了详细的阐述,也从传统虚拟化方式的角度阐述了 Docker 的优势。

五、Docker 架构

我们从下图可以直观地看到 Docker 的架构:

Docker 使用 C/S 结构,即客户端/服务器体系结构。Docker 客户端与 Docker 服务器进行交互,Docker服务端负责构建、运行和分发 Docker 镜像。

Docker 客户端和服务端可以运行在一台机器上,也可以通过 RESTful 、 Stock 或网络接口与远程 Docker 服务端进行通信。

这张图展示了 Docker 客户端、服务端和 Docker 仓库(即 Docker Hub 和 Docker Cloud ),默认情况下 Docker 会在 Docker 中央仓库寻找镜像文件。

这种利用仓库管理镜像的设计理念类似于 Git ,当然这个仓库是可以通过修改配置来指定的,甚至我们可以创建我们自己的私有仓库。

工作原理

Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上, 然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。容器,是一个运行时环境,就是我们前面说到的集装箱。

Docker 的核心组件包括:

Docker ClientDocker DaemonDocker ImageDocker RegistryDocker Container

Docker 采用的是 Client/Server 架构。客户端向服务器发送请求,服务器负责构建、运行和分发容器。

客户端和服务器可以运行在同一个 Host 上,客户端也可以通过 Socket 或 REST API 与远程的服务器通信。

可能很多朋友暂时不太理解一些东西,比如 REST API 是什么东西等,不过没关系,在后面的文章中会一一给大家讲解清楚。

Docker Client

Docker Client ,也称 Docker 客户端。它其实就是 Docker 提供命令行界面(CLI)工具,是许多 Docker 用户与 Docker 进行交互的主要方式。

客户端可以构建,运行和停止应用程序,还可以远程与 Docker_Host 进行交互。

最常用的 Docker 客户端就是 Docker 命令,我们可以通过 Docker 命令很方便地在 Host 上构建和运行 Docker 容器。

Docker Daemon

Docker Daemon 是服务器组件,以 Linux 后台服务的方式运行,是 Docker 最核心的后台进程,我们也把它称为守护进程。

它负责响应来自 Docker Client 的请求,然后将这些请求翻译成系统调用完成容器管理操作。

该进程会在后台启动一个 API Server ,负责接收由 Docker Client 发送的请求,接收到的请求将通过 Docker Daemon 内部的一个路由分发调度,由具体的函数来执行请求。

我们大致可以将其分为以下三部分:

Docker ServerEngineJob

Docker Daemon 的架构如下所示:

Docker Daemon 可以认为是通过 Docker Server 模块接受 Docker Client 的请求,并在 Engine 中处理请求,然后根据请求类型,创建出指定的 Job 并运行。

Docker Daemon 运行在 Docker Host 上,负责创建、运行、监控容器,构建、存储镜像。

运行过程的作用有以下几种可能:

向 Docker Registry 获取镜像。通过 GraphDriver 执行容器镜像的本地化操作。通过 NetworkDriver 执行容器网络环境的配置。通过 ExecDriver 执行容器内部运行的执行工作。

由于 Docker Daemon 和 Docker Client 的启动都是通过可执行文件 Docker 来完成的,因此两者的启动流程非常相似。

Docker 可执行文件运行时,运行代码通过不同的命令行 Flag 参数,区分两者,并最终运行两者各自相应的部分。

启动 Docker Daemon 时,一般可以使用以下命令来完成:

docker --daemon = truedocker –d docker –d = true

再由 Docker 的 main() 函数来解析以上命令的相应 Flag 参数,并最终完成 Docker Daemon 的启动。

下图可以很直观地看到 Docker Daemon 的启动流程:

默认配置下,Docker Daemon 只能响应来自本地 Host 的客户端请求。如果要允许远程客户端请求,需要在配置文件中打开 TCP 监听。

我们可以照着如下步骤进行配置:

1、编辑配置文件/etc/systemd/system/multi-user.target.wants/docker.service,在环境变量 ExecStart 后面添加 -H tcp://0.0.0.0,允许来自任意 IP 的客户端连接。

2、重启 Docker Daemon:

systemctl daemon-reload systemctl restart docker.service

3、我们通过以下命令即可实现与远程服务器通信:

docker - H 服务器 IP 地址 info

-H 是用来指定服务器主机,info 子命令用于查看 Docker 服务器的信息。

Docker Image

Docker 镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。

镜像不包含任何动态数据,其内容在构建之后也不会被改变。我们可将 Docker 镜像看成只读模板,通过它可以创建 Docker 容器。

镜像有多种生成方法:

从无到有开始创建镜像下载并使用别人创建好的现成的镜像在现有镜像上创建新的镜像

我们可以将镜像的内容和创建步骤描述在一个文本文件中,这个文件被称作 Dockerfile ,通过执行 docker build命令可以构建出 Docker 镜像。

Docker Container

Docker 容器就是 Docker 镜像的运行实例,是真正运行项目程序、消耗系统资源、提供服务的地方。

Docker Container 提供了系统硬件环境,我们可以使用 Docker Images 这些制作好的系统盘,再加上我们所编写好的项目代码,Run 一下就可以提供服务啦。

Docker Registry

Docker Registry 是存储 Docker Image 的仓库,它在 Docker 生态环境中的位置如下图所示:

运行 docker push、docker pull、docker search 时,实际上是通过 Docker Daemon 与 Docker Registry 通信。

六、Docker 网络1.本机网络理解

我们使用ifconfig可以看到三组网络。首先是docker0,这是我们本节的重点,docker的网络。之后是eth0,本机的外网地址。lo口,本地环回地址,可以代表localhost。

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

brctl show

2.清空本机docker环境docker rm -f $(docker ps -aq) docker rmi -f $(docker images -aq)3.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 就是一堆的虚拟设备接口,他们都是成对出现的,一端连接着协议,一端连接着彼此。使得它充当了一个桥梁的作用。

4.docker网络详解

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

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

5.docker网络模式1)docker网络模式有以下几种:

Host:容器不会虚拟出自己的网卡,配置主机的IP等,而是使用宿主机的IP和端口 Container: 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP。(一般不用) None: 该模式关闭了容器的网络功能。(一般不用) Bridge:默认为该模式(桥接,自己创建也是用它),此模式会为每一个容器分配,设置IP等,并将容器连接到一个docker0 的虚拟网桥,通过docker 0 网桥以及iptables nat 表配置与宿主机通信。 docker network ls #列出docker网卡2)创建自定义网络的容器:

#我们直接启动命令, --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 网卡名字 #查看网卡详细信息

3)发布两个在自己创建的网络里的容器。

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的次数

七、Docker 安装

Docker 的安装和使用有一些前提条件,主要体现在体系架构和内核的支持上。

对于体系架构,除了 Docker 一开始就支持的 X86-64 ,其他体系架构的支持则一直在不断地完善和推进中。

2017年初,docker公司将原先的docker开源项目改名为moby。

moby是集成了原先的docker项目,是社区维护的开源项目,谁都可以在moby的基础打造自己的容器产品。

Docker 分为 CE 和 EE 两大版本。CE 即社区版,免费支持周期 7 个月;EE 即企业版,强调安全,付费使用,支持周期 24 个月。我们经常使用的版本当然是docker-ce啦!

我们在安装前可以参看官方文档获取最新的 Docker 支持情况,官方文档在这里:

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

Docker 对于内核支持的功能,即内核的配置选项也有一定的要求(比如必须开启 Cgroup 和 Namespace 相关选项,以及其他的网络和存储驱动等)。

Docker CE 的安装请参考官方文档:

MacOS:https://docs.docker.com/docker-for-mac/install/Windows:https://docs.docker.com/docker-for-windows/install/Ubuntu:https://docs.docker.com/install/linux/docker-ce/ubuntu/Debian:https://docs.docker.com/install/linux/docker-ce/debian/CentOS:https://docs.docker.com/install/linux/docker-ce/centos/Fedora:https://docs.docker.com/install/linux/docker-ce/fedora/其他 Linux 发行版:https://docs.docker.com/install/linux/docker-ce/binaries/

CentOS/Ubuntu安装Docker和Docker Compose,这里我们以 CentOS 7 作为演示。

环境准备:

阿里云服务器(1 核 2G,1M 带宽)CentOS 7.4 64 位

由于 Docker-CE 支持 64 位版本的 CentOS 7 ,并且要求内核版本不低于 3.10,首先我们需要卸载掉旧版本的 Docker:

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

我们执行以下安装命令去安装依赖包:

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

这里已经安装过了,所以提示Nothing to do。

配置国内yum源

这里采用的是阿里云

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

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

cat / etc / yum . repos . d / docker - ce . repo

更新yum软件包索引

yum makecache fast

列出并排序您存储库中可用的版本。此示例按版本号(从高到低)对结果进行排序。

yum list docker-ce --showduplicates | sort -rDocker 软件包已经包括在默认的 CentOS-Extras 软件源里。因此想要安装 Docker,只需要运行下面的 yum 命令进行安装:sudo yum install - y docker - ce当然在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,CentOS 系统上可以使用这套脚本安装:## 一键安装 docker curl -fsSL get.docker.com -o get-docker.sh && sh get-docker.sh # 或 curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun # 或 curl -sSL https://get.docker.com/ | sh # 或 wget -qO- https://get.docker.com/ | sh

具体可以参看 docker-install 的脚本:

https://github.com/docker/docker-install

执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker CE 的 Edge 版本安装在系统中。更多详见CentOS/Ubuntu安装Docker和Docker Compose。

安装完成后,运行下面的命令,验证是否安装成功:

启动 Docker-CE:

sudo systemctl start docker sudo systemctl enable docker #设置开机自启

验证

docker -v 或 docker version 或 docker --version # 或 docker info

返回 Docker 的版本相关信息,证明 Docker 安装成功:

Docker 的简单运用 Hello World

我们通过最简单的 Image 文件 Hello World,感受一下 Docker 的魅力吧!

我们直接运行下面的命令,将名为 hello-world 的 image 文件从仓库抓取到本地:

docker pull hello - world

docker pull images 是抓取 image 文件,library/hello-world 是 image 文件在仓库里面的位置,其中 library 是 image 文件所在的组,hello-world 是 image 文件的名字。

抓取成功以后,就可以在本机看到这个 image 文件了:

docker images

我们可以看到如下结果:

现在,我们可以运行 hello-world 这个 image 文件:

docker run hello - world

我们可以看到如下结果:

输出这段提示以后,hello world 就会停止运行,容器自动终止。有些容器不会自动终止,因为提供的是服务,比如 Nginx镜像等。

我们从上面可以看出,Docker 的功能是十分强大的,除此之外,我们还可以拉取一些 Centos,Ubuntu,Alpine等镜像,在未来的教程中我们将会一一提到。

Docker 提供了一套简单实用的命令来创建和更新镜像,我们可以通过网络直接下载一个已经创建好了的应用镜像,并通过 Docker RUN 命令就可以直接使用。

当镜像通过 RUN 命令运行成功后,这个运行的镜像就是一个 Docker 容器啦。

容器可以理解为一个轻量级的沙箱,Docker 利用容器来运行和隔离应用,容器是可以被启动、停止、删除的,这并不会影响 Docker 镜像。

我们可以看看下面这幅图:

Docker 客户端是 Docker 用户与 Docker 交互的主要方式。当您使用 Docker 命令行运行命令时,Docker 客户端将这些命令发送给服务器端,服务端将执行这些命令。

Docker 命令使用 Docker API 。Docker 客户端可以与多个服务端进行通信。

我们将剖析一下 Docker 容器是如何工作的,学习好 Docker 容器工作的原理,我们就可以自己去管理我们的容器了。

Docker 配置镜像加速器

这是使用阿里云docker镜像加速器。控制台地址:https://cr.console.aliyun.com,登录后,左侧-镜像工具-镜像加速器,加速器帮助页面会为你显示独立的加速地址,这个加速地址每个人的都不同。

针对Docker客户端版本大于 1.10.0 的用户

您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器

sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json

我们可以通过 Docker Images 可以查看到 hello-world 已经下载到本地:

我们可以通过 Docker Ps 或者 Docker Container ls 显示正在运行的容器,我们可以看到,hello-world 在输出提示信息以后就会停止运行,容器自动终止,所以我们在查看的时候没有发现有容器在运行。

我们把 Docker 容器的工作流程剖析的十分清楚了,我们大体可以知道 Docker 组件协作运行容器可以分为以下几个过程:

Docker 客户端执行 docker run 命令。Docker Daemon 发现本地没有我们需要的镜像。Daemon 从 Docker Hub 下载镜像。下载完成后,镜像被保存到本地。Docker Daemon 启动容器。

了解了这些过程以后,我们再来理解这些命令就不会觉得很突兀了,下面我来给大家讲讲 Docker 常用的一些命令操作吧。

八、Docker 常用命令

我们可以通过 docker -h 去查看命令的详细的帮助文档。在这里我只会讲一些日常我们可能会用的比较多的一些命令。

1.帮助启动类命令[ 查看版本] docker version[ 查看Docker概要信息] docker info[ 查看Docker总体帮助文档] docker--help[ 查看docker具体命令帮助文档] docker具体命令--help[ 启动Docker] systemctl start docker[ 停止Docker] systemctl stop docker[ 重启Docker] systemctl restart docker[ 查看状态] systemctl status docker[ 开机启动] systemctl enable docker2.镜像命令1)列出本地主机上的镜像docker images

参数说明:

-a:列出所有镜像(含历史镜像)-q:只显示镜像ID-f:过滤

各个选项说明:

REPOSITORY:表示镜像的仓库源TAG:镜像的标签版本号IMAGE ID:镜像IDCREATED:镜像创建时间SIZE:镜像大小2)在远程仓库中搜索镜像

执行命令,默认去docker hub中搜索

docker search 镜像名称

参数说明:

-f:过滤 --limit 数量:只列出N个镜像,默认25个

3)下载镜像docker pull 镜像名称[:tag]

不加 tag 时,默认下载最新的镜像(即tag为latest)。

4)查看占据的空间

查看镜像/容器/数据卷所占的空间:

docker system df

5)删除镜像docker rmi 镜像名称/ID

可以使用空格分隔,删除多个镜像:

docker rmi 镜像1 镜像2 镜像3

删除全部镜像:

docker rmi -f ${docker images -qa}6)虚悬镜像

仓库名、标签都是的镜像,俗称虚悬镜像(dangling image)。

3.容器命令1)新建+启动容器

新建容器,需要先下载镜像 docker pull ubuntu。

执行命令 docker run[OPTIONS]IMAGE[COMMAND][ARG...]

参数【OPTIONS】说明:

--name:为容器指定一个名称-d:后台运行容器并返回容器ID,也即启动守护式容器-i:以交互模式(interactive)运行容器,通常与-t同时使用-t:为容器重新分配一个伪输入终端(tty),通常与-i同时使用。也即启动交互式容器(前台有伪终端,等待交互)-e:为容器添加环境变量-P:随机端口映射。将容器内暴露的所有端口映射到宿主机随机端口-p:指定端口映射

-p指定端口映射的几种不同形式

-p hostPort:containerPort:端口映射,例如-p 8080:80-p ip:hostPort:containerPort:配置监听地址,例如 -p 10.0.0.1:8080:80-p ip::containerPort:随机分配端口,例如 -p 10.0.0.1::80-p hostPort1:containerPort1-p hostPort2:containerPort2:指定多个端口映射,例如-p 8080:80 -p 8888:33062)启动交互式容器(前台命令行)

执行命令,以交互方式启动ubuntu镜像

docker run - it ubuntu / bin / bash

参数说明:

-i: 交互式操作。-t: 终端。ubuntu : ubuntu 镜像。/bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。要退出终端,直接输入 exit:

两种方式退出交互模式

exit; run进去容器,exit退出,容器停止使用快捷键 ctrl+P+Q run进去容器,ctrl+p+q退出,容器不停止3)列出当前所有正在运行的容器docker ps [OPTIONS]

常用参数说明:

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

大部分情况下,我们系统docker容器服务是在后台运行的,可以通过-d指定容器的后台运行模式:

docker run -d 容器名

注意事项:如果使用 docker run-d ubuntu尝试启动守护式的ubuntu,然后 docker ps-a 进行查看, 会发现容器已经退出了。

因为Docker容器如果在后台运行,就必须要有一个前台进程。容器运行的命令如果不是那些一直挂起的命令(例如 top、 tail),就会自动退出。

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

容器内文件拷贝到宿主机:

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

宿主机文件拷贝到容器中:

docker cp 主机路径 容器ID:容器内路径6)导入和导出容器

export:导出容器的内容流作为一个tar归档文件(对应import命令);

import:从tar包中的内容创建一个新的文件系统再导入为镜像(对应export命令);

示例:

# 导出 # docker export 容器ID > tar文件名 docker export abc > aaa.tar # 导入 # cat tar文件 | docker import - 自定义镜像用户/自定义镜像名:自定义镜像版本号 docker aaa.tar | docker import - test/mytest:1.0.17)将容器生成新镜像

docker commit提交容器副本使之成为一个新的镜像。

docker 启动一个镜像容器后, 可以在里面执行一些命令操作,然后使用docker commit将新的这个容器快照生成一个镜像。docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[tag]

Docker挂载主机目录,可能会出现报错:cannot open directory.:Perissiondenied。

解决方案:在命令中加入参数 --privileged=true。

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

8)将容器生成新镜像

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

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

特点:

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

运行一个带有容器卷存储功能的容器实例:

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

可以使用docker inspect查看容器绑定的数据卷。

权限:

rw:读写ro:只读。如果宿主机写入内容,可以同步给容器内,容器内可以读取。

容器卷的继承:

# 启动一个容器 docker run -it --privileged=true /tmp/test:/tmp/docker --name u1 ubuntu /bin/bash # 使用 --volumes-from 继承 u1的容器卷映射配置 docker run -it --privileged=true --volumes-from u1 --name u2 ubuntu9)其他命令[ 启动已停止运行的容器] docker start容器ID或者容器名[ 重启容器] docker restart容器ID或容器名[ 停止容器] docker stop容器ID或容器名[ 强制停止容器] docker kill容器ID或容器名[ 删除已经停止的容器] docker rm容器ID或容器名[ 强制删除正在运行的容器] docker rm-f容器ID或容器名[ 一次删除多个容器实例] docker rm-f ${docker ps-a-q} 或者 docker ps-a-q|xargs docker rm[ 查看容器日志] docker logs容器ID或容器名,更多查看容器日志使用技巧,docker logs 查看日志[ 查看容器内部细节] docker inspect容器ID或容器名[ 进入正在运行的容器] dockerexec-it容器ID bashShell[ 重新进入] docker attach容器ID

docker exec 和 docker attach 区别

attach直接进入容器启动命令的终端,不会启动新的进程,用exit退出会导致容器的停止exec是在容器中打开新的终端,并且可以启动新的进程,用exit退出不会导致容器的停止

如果有多个终端,都对同一个容器执行了 docker attach,就会出现类似投屏显示的效果。一个终端中输入输出的内容,在其他终端上也会同步的显示。

九、实战测试:部署Nginx

Alpine介绍

社区开发的面向安全应用的轻量级Linux发行版,Alpine 的意思是“高山的”,比如 Alpine plants高山植物,Alpine skiing高山滑雪、the alpine resort阿尔卑斯山胜地。

Alpine Linux 网站首页注明“Small!Simple!Secure!Alpine Linux is a security-oriented, lightweight Linux distribution based on musl libc and busybox.”概括了以下特点:

1、小巧:基于Musl libc和busybox,和busybox一样小巧,最小的Docker镜像只有5MB;

2、安全:面向安全的轻量发行版;

3、简单:提供APK包管理工具,软件的搜索、安装、删除、升级都非常方便。

4、适合容器使用:由于小巧、功能完备,非常适合作为容器的基础镜像。

1.搜索镜像docker search nginx : alpine

2.下载镜像docker pull nginx : alpine

3.查看镜像docker images

nginx镜像不到24M。

4.启动容器

docker run -d --name nginxd -p 80:80 nginx:alpine

5.查看容器docker ps

6.测试访问curl 127.0 . 0.1 : 80

127.0.0.1是本地回环ip,就是本机啦,可以用localhost代替。

7.进入容器修改页面

docker exec -it 容器名称/容器ID/容器ID简写

docker exec -it nginxd ash #或 docker exec -it de15a5e4c614 ash #或,容器ID太长,我们用容器ID的前2位即可 docker exec -it de ash

alpine是轻量级的操作系统,默认没有安装whereis,这是使用find来查找nginx安装目录。

验证:

curl 127.0 . 0.1

十、Dockerfile 是什么

前面我们已经提到了 Docker 的一些基本概念。以 CTF 的角度来看,我们可以去使用 Dockerfile 定义镜像,依赖镜像来运行容器,可以去模拟出一个真实的漏洞场景。

因此毫无疑问的说, Dockerfile 是镜像和容器的关键,并且 Dockerfile 还可以很轻易的去定义镜像内容,说了这么多,那么 Dockerfile 到底是个什么东西呢?

Dockerfile 是自动构建 Docker 镜像的配置文件,用户可以使用 Dockerfile 快速创建自定义的镜像。Dockerfile 中的命令非常类似于 Linux 下的 Shell 命令。

我们可以通过下面这幅图来直观地感受下 Docker 镜像、容器和 Dockerfile 三者之间的关系:

我们从上图中可以看到,Dockerfile 可以自定义镜像,通过 Docker 命令去运行镜像,从而达到启动容器的目的。Dockerfile 是由一行行命令语句组成,并且支持已 # 开头的注释行。

一般来说,我们可以将 Dockerfile 分为四个部分:

基础镜像(父镜像)信息指令 FROM。维护者信息指令 MAINTAINER。镜像操作指令 RUN 、EVN 、ADD 和 WORKDIR 等。容器启动指令 CMD 、ENTRYPOINT 和 USER 等。

下面是一段简单的 Dockerfile 的例子:

FROM python:2.7 MAINTAINER 大技术 COPY . /app WORKDIR /app RUN pip install -r requirements.txt EXPOSE 5000ENTRYPOINT ["python"]CMD ["app.py"]

我们可以分析一下上面这个过程:

从 Docker Hub 上 Pull 下 Python 2.7 的基础镜像。显示维护者的信息。Copy 当前目录到容器中的 /App 目录下 复制本地主机的 ( Dockerfile 所在目录的相对路径)到容器里 。指定工作路径为 /App。安装依赖包。暴露 5000 端口。启动 App。

这个例子是启动一个 Python Flask App 的 Dockerfile(Flask 是 Python 的一个轻量的 Web 框架),相信大家从这个例子中能够稍微理解了 Dockfile 的组成以及指令的编写过程。

十一、Dockerfile 常用的指令

根据上面的例子,我们已经差不多知道了 Dockerfile 的组成以及指令的编写过程,我们再来理解一下这些常用命令就会得心应手了。

由于 Dockerfile 中所有的命令都是以下格式:INSTRUCTION argument ,指令(INSTRUCTION)不分大小写,但是推荐大写和 SQL 语句是不是很相似呢?下面我们正式来讲解一下这些指令集吧。

FROM

FROM 是用于指定基础的 images ,一般格式为 FROM or FORM :。

所有的 Dockerfile 都应该以 FROM 开头,FROM 命令指明 Dockerfile 所创建的镜像文件以什么镜像为基础,FROM 以后的所有指令都会在 FROM 的基础上进行创建镜像。

可以在同一个 Dockerfile 中多次使用 FROM 命令用于创建多个镜像。比如我们要指定 Python 2.7 的基础镜像,我们可以像如下写法一样:

FROM python : 2.7MAINTAINER

MAINTAINER 是用于指定镜像创建者和联系方式,一般格式为 MAINTAINER。

这里我设置成我的 ID 和邮箱:

MAINTAINER 大技术 < test@gmail . com >COPY

COPY 是用于复制本地主机的(为 Dockerfile 所在目录的相对路径)到容器中的。

当使用本地目录为源目录时,推荐使用 COPY 。一般格式为 COPY。

例如我们要拷贝当前目录到容器中的 /app 目录下,我们可以这样操作:

COPY . / appWORKDIR

WORKDIR 用于配合 RUN,CMD,ENTRYPOINT 命令设置当前工作路径。

可以设置多次,如果是相对路径,则相对前一个 WORKDIR 命令。默认路径为/。一般格式为 WORKDIR /path/to/work/dir。

例如我们设置 /app 路径,我们可以进行如下操作:

WORKDIR / appRUN

RUN 用于容器内部执行命令。每个 RUN 命令相当于在原有的镜像基础上添加了一个改动层,原有的镜像不会有变化。一般格式为 RUN。

例如我们要安装 Python 依赖包,我们做法如下:

RUN pip install - r requirements . txtEXPOSE

EXPOSE 命令用来指定对外开放的端口。一般格式为 EXPOSE[...]。

例如上面那个例子,开放5000端口:

EXPOSE 5000ENTRYPOINT

ENTRYPOINT 可以让你的容器表现得像一个可执行程序一样。一个 Dockerfile 中只能有一个 ENTRYPOINT,如果有多个,则最后一个生效。

ENTRYPOINT 命令也有两种格式:

ENTRYPOINT ["executable", "param1", "param2"] :推荐使用的 Exec 形式。ENTRYPOINT command param1 param2 :Shell 形式。

例如下面这个,我们要将 Python 镜像变成可执行的程序,我们可以这样去做:

ENTRYPOINT [ "python" ]CMD

CMD 命令用于启动容器时默认执行的命令,CMD 命令可以包含可执行文件,也可以不包含可执行文件。

不包含可执行文件的情况下就要用 ENTRYPOINT 指定一个,然后 CMD 命令的参数就会作为 ENTRYPOINT 的参数。

CMD 命令有三种格式:

CMD ["executable","param1","param2"]:推荐使用的 exec 形式。CMD ["param1","param2"]:无可执行程序形式。CMD command param1 param2:Shell 形式。

一个 Dockerfile 中只能有一个 CMD,如果有多个,则最后一个生效。而 CMD 的 Shell 形式默认调用 /bin/sh -c 执行命令。

CMD 命令会被 Docker 命令行传入的参数覆盖:docker run busybox /bin/echo Hello Docker 会把 CMD 里的命令覆盖。

例如我们要启动 /app ,我们可以用如下命令实现:

CMD [ "app.py" ]

当然还有一些其他的命令,我们在用到的时候再去一一讲解一下。

十二、构建 Dockerfile

我们大体已经把 Dockerfile 的写法讲述完毕,我们可以自己动手写一个例子:

vi Dockerfile 开始编辑该文件,输入 i 开始编辑。以下是我们构建的 Dockerfile 内容:

FROM nginx:alpine MAINTAINER 大技术 RUN echo 'hello docker nginx' > /usr/share/nginx/html/index.html

编辑完后按 esc 退出编辑,然后 :wq写入,退出。

我们在 Dockerfile 文件所在目录执行:

docker build - t mynginx : 1.0 .

我们解释一下:

-t 是为新镜像设置仓库和名称mynginx 为镜像名:1.0 为标签(不添加为默认 latest )

我们构建完成之后,使用 Docker Images 命令查看所有镜像,如果存在 REPOSITORY 为 Nginx 和 TAG 是 1.0 的信息,就表示构建成功。

接下来使用 docker run 命令来启动容器:

docker run --name mynginx -d -p 8080:80 mynginx:1.0

这条命令会用 Nginx 镜像启动一个容器,命名为 mynginx ,并且映射了 8080 端口。

这样我们可以用浏览器去访问这个 Nginx 服务器:

http://localhost:8080/

或者 http://本机的 IP 地址:8080/,页面返回信息:

十三、实战测试:制作镜像并且提交到镜像仓库公有云镜像仓库Docker Hub仓库

1.注册docker hub 账号

网址:https://hub.docker.com/

2.服务器上使用命令行登录

docker login -u [账号名字] #登陆命令 docker out #退出命令 docker push 账号/容器名字:版本号

看到Lgin Succeeded,就表示登录成功了。

3.构建镜像1)编写dockerfile

alpine官方默认镜像,没有vim命令,我们就基于此,创建一个镜像。

vim Dockerfile FROM alpine MAINTAINER 大技术 #更新Alpine的软件源为阿里云,默认官源拉取实在太慢 RUN echo http://mirrors.aliyun.com/alpine/v3.10/main/ > /etc/apk/repositories && echo http://mirrors.aliyun.com/alpine/v3.10/community/ >> /etc/apk/repositories RUN apk update && apk upgrade RUN apk --no-cache add vim CMD vim --version

2)构建dockerfile

docker build 命令:

docker build -t myalpine:1.0 . #或 docker build -f myDockerfile -t myalpine:1.0 .

#查看刚构建的镜像 docker images

到这里,我们就制作好了我们自己的镜像,虽然它并没有什么用。这里我们再启动我们自己制作的镜像,进去看看我们写的dockerfile都生效了没有。注:不加标签默认是latest,所以docker run的时候要带上镜像标签。

docker run - it myalpine : 1.0

#查看dockerfile的构建过程 docker history myalpine:1.0

4.推送镜像至docker hub

需要先登录(根据提示输入用户名和密码即可),已登录请忽略。

docker login

看到Lgin Succeeded,就表示登录成功了。

官方文档要求,我们推送的镜像名字必须是YOURDOCKERHUB_ID/XXXX,所以我们需要给镜像换一个名字

docker tag local-image:tagname new-repo:tagname

docker push new-repo:tagname

docker tag myalpine:1.0 dhdemo/myalpine:1.0 docker push dhdemo/myalpine:1.0

等了一会之后,就推送到docker hub

我们登陆docker hub就可以看到我们刚刚推送上去的镜像啦,这个镜像可是全世界人民都看得到的哦,是不是有点小激动呢!

阿里云仓库

国内镜像仓库有阿里云 、网易云等,这里以阿里云为例。

1.登入阿里云地址并创建镜像仓库

https://aliyun.com

搜索 “容器镜像服务”,找到镜像仓库,创建镜像仓库

进入仓库查看创建后的镜像仓库信息

2.推送镜像到阿里云仓库

登录

docker login --username=你的用户名 registry.cn-beijing.aliyuncs.com

说明:

username 你的用户名

http://registry.cn-beijing.aliyuncs.com 仓库地域,不同地区不一样,创建镜像时选择的是北京,这里就是北京地域的仓库地址。

登录成功提示如下:

使用上面的镜像myalpine:1.0,将镜像推送到Registry

docker tag [ImageId] http://registry.cn-beijing.aliyuncs.com/0101/myalpine:[镜像版本号]

docker push http://registry.cn-beijing.aliyuncs.com/0101/myalpine:[镜像版本号]

docker tag 4220608af837 registry.cn-beijing.aliyuncs.com/0101/myalpine:1.0 docker push registry.cn-beijing.aliyuncs.com/0101/myalpine:1.0

查看阿里云镜像是否上传成功

私有化部署镜像仓库Docker 仓库是用来包含镜像的位置,Docker提供一个注册服务器(Register)来保存多个仓库,每个仓库又可以包含多个具备不同tag的镜像。Docker运行中使用的默认仓库是 Docker Hub 公共仓库。

私有化部署镜像仓库,一般使用Docker Register、Nexus、Harbor,下面分别介绍一下。

Docker RegisterDocker Registry是一个集中存储与分发镜像的服务。构建完 Docker镜像后,就可在当前宿主机上运行。但如果想要在其他机器上运行这个镜像,就需要手动复制。此时可借助Docker Registry来避免镜像的手动复制。一个 Docker Registry可包含多个 Docker仓库,每个仓库可包含多个镜像标签,每个标签对应一个 Docker镜像。这跟 Maven的仓库有点类似,如果把 Docker Registry比作Maven仓库的话,那么 Docker仓库就可理解为某jar包的路径,而镜像标签则可理解为jar包的版本号。

1.Registry本地私有仓库的搭建以及上传

docker pull registry #拉取官方私有仓库容器使得其可以进行搭载 docker run -d -p 5000:5000 --restart=always --name demo registry #运行镜像--restart=always表示重启docker后仍旧运行该镜像不会被退出 docker tag nginx:latest localhost:5000/nginx:new #更改镜像的TAG标签 docekr push localhost:5000/nginx:new #上传更改过的镜像到私有仓库

2.本地Reegistry镜像仓库证书加密

yum install openssl11 -y #需要epel源将本地名令进行升级使其可以支持 openssl11 req -newkey rsa:4096 -nodes -sha256 -keyout certs/www.registry.org.key -addext "subjectAltName = DNS:www.registry.org" -x509 -days 365 -out certs/www.registry.org.crt Generating a RSA private key #使用openssl11生成软件仓库的证书使其可以进行certs/www.registry,irg,crt使用的是相对路径注意下自己的所在位置

mkdir -p /etc/docker/certs.d/www.registry.org/ #建立存放证书的使得容器运行后自动读取证书 cp certs/www.registry.org.crt /etc/docker/certs.d/www.registry.org/ca.crt #证书必须为ca.crt否则不会识别 docker run -d -p 443:443 --name registry --restart=always -v /root/certs:/certs/ -v /opt/registry:/var/lib/registry/ -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/www.registry.org.crt -e REGISTRY_HTTP_TLS_KEY=/certs/www.registry.org.key registry #运行容器使得容器可以在后台自动运行同时将证书添加上去使得容器可以进行加密访问-v表示挂载目录目录未创建则自动创建-e表示添加证书

3.Registry私有仓库http加密1)用户名和密码生成

mkdir auth #建立存放认证的目录 htpasswd -Bc auth/htpasswd uset1 #-B表示安全-c表示创建二次创建时不要加-c否则会覆盖之前的

2)运行仓库

docker run -d -p 443:443 --restart=always --name registry \ > -v /root/auth:/auth/ \ #挂载认证 > -v /root/certs:/certs/ \ #挂载证书 > -v /opt/registry:/var/lib/registry \ #挂载数据卷 > -e "REGISTRY_AUTH=htpasswd" \ > -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ > -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \ > -e "REGISTRY_HTTP_ADDR=0.0.0.0:443" \ > -e "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/www.registry.org.crt" \ > -e "REGISTRY_HTTP_TLS_KEY=/certs/www.registry.org.key" \ > registry

3)上传镜像到私服

docker tag yakexi007/game2018 www.registry.org/game2048 #更改tag标签准备上传 docker login www.registry.org #登陆私有仓库 docker push www.registry.org/game2048 #上传镜像

Nexus

nexus默认只有maven和nuget的镜像,但是他本身支持各种私有镜像,如linux软件包镜像:apt、yum,还有语言库镜像如:npm、conada、pypi、go,当然也包括docker的镜像。

前置条件:已安装docker

1.Nexus安装及配置

docker run --name nexus3 --restart=always -p 8085:8081 -p 8086:8086 -v ~/docker/nexus/data:/nexus-data --privileged=true -d sonatype/nexus3

其中8086端口是本文要使用的作为docker私有库的端口;

登录后,创建docker镜像。

镜像类型有点多,仔细观察

可以发现docker的镜像类型有三个:group、host、proxy,他们的关系

proxy:官方源的镜像代理

host:自己创建的一些源,一般是私有的不公开的,本文主要创建的就是host类型的私有镜像

group:对这些镜像进行分组

在创建docker库之前,需要做一个授权的设置,否则无法创建仓库

下面就开始创建docker的仓库了,本文选择的是host类型,下面是录入的表单界面

创建完查看仓库列表,多了刚才见的cs仓库

仓库创建完以后,就可以使用一个测试的docker镜像来执行docker push了。

说明:

1)因为我的nexus3也是通过docker容器创建的,容器所在的机器上的IP地址是172.17.0.1,那么172.17.0.1:8086就是nexus3下私有docker镜像的地址;

2)我现在已经自己做了一个镜像:172.17.0.1:8086/app:v1.0.1 说明:要通过docker tag 把172.17.0.1:8086作为镜像名称的前缀。

要先通过docker login登录,但是会有一个错误

docker login -u admin 172.17.0.1:8086 Password: Error response from daemon: Get https://172.17.0.1:8086/v2/: http: server gave HTTP response to HTTPS client

解决这个错误需要如下处理

1.打开:vi /etc/docker/daemon.json2.添加:"insecure-registries":["172.17.0.1:8086"]3.重启:systemctl restart docker

再重新登录就可以成功了

docker login -u admin 172.17.0.1:8086 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

2.上传镜像到私服

下面执行docker push

docker push 172.17.0.1:8086/app:v1.0.1 The push refers to repository [172.17.0.1:8086/app] 7eab7e4c2e5d: Pushed 0c746c7a2bd6: Pushed 9675b67121e6: Pushed f1dd685eb59e: Pushed v1.0.1: digest: sha256:1f1a27db80d7823d3dc08731732e7a935930a23e682b7ed6e2aaff2ff7d78743 size: 1153

在nexus3中查看push的镜像

Harbor

Harbor 是由 VMware 公司中国团队为企业用户设计的 Registry server 开源项目,包括了权限管理 (RBAC)、LDAP、审计、管理界面、自我注册、HA 等企业必需的功能,同时针对中国用户的特点,设计镜像复制和中文支持等功能。

作为一个企业级私有 Registry 服务器,Harbor 提供了更好的性能和安全。提升用户使用 Registry 构建和运行环境传输镜像的效率。Harbor 支持安装在多个 Registry 节点的镜像资源复制,镜像全部保存在私有 Registry 中, 确保数据和知识产权在公司内部网络中管控。另外,Harbor 也提供了高级的安全特性,诸如用户管理,访问控制和活动审计等。

基于角色的访问控制 - 用户与 Docker 镜像仓库通过 “项目” 进行组织管理,一个用户可以对多个镜像仓库在同一命名空间(project)里有不同的权限。镜像复制 - 镜像可以在多个 Registry 实例中复制(同步)。尤其适合于负载均衡,高可用,混合云和多云的场景。图形化用户界面 - 用户可以通过浏览器来浏览,检索当前 Docker 镜像仓库,管理项目和命名空间。AD/LDAP 支持 - Harbor 可以集成企业内部已有的 AD/LDAP,用于鉴权认证管理。审计管理 - 所有针对镜像仓库的操作都可以被记录追溯,用于审计管理。国际化 - 已拥有英文、中文、德文、日文和俄文的本地化版本。更多的语言将会添加进来。RESTful API - RESTful API 提供给管理员对于 Harbor 更多的操控,使得与其它管理软件集成变得更容易。部署简单 - 提供在线和离线两种安装工具, 也可以安装到 vSphere 平台 (OVA 方式) 虚拟设备。

前置条件:已安装docker、Docker Compose

1.harbor安装及配置

wget https://github.com/goharbor/harbor/releases/download/v2.3.4/harbor-offline-installer-v2.3.4.tgz tar xf harbor-offline-installer-v2.3.4.tgz -C /usr/local/ cd /usr/local/harbor #修改配置文件 [root@localhost harbor]# ll 总用量 596292 -rw-r--r-- 1 root root 3361 11月 9 2021 common.sh -rw-r--r-- 1 root root 610560420 11月 9 2021 harbor.v2.3.4.tar.gz -rw-r--r-- 1 root root 7844 6月 13 12:31 harbor.yml -rw-r--r-- 1 root root 7840 11月 9 2021 harbor.yml.tmpl -rwxr-xr-x 1 root root 2500 11月 9 2021 install.sh -rw-r--r-- 1 root root 11347 11月 9 2021 LICENSE -rwxr-xr-x 1 root root 1881 11月 9 2021 prepare cp harbor.yml.tmpl harbor.yml #修改hostname、harbor登录密码、关闭https。 vim harbor.yml hostname: www.myharbor.com harbor_admin_password: harbor12345 #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 data_volume: /data #这个路径是宿主机的路径,根据实际情况修改成空间大的地方

完成以上操作后,保存退出

#执行安装程序,只安装harbor ./install.sh (前提条件:docker需要启动) # 除了安装harbor外,还安装公正服务 notary 以及漏洞扫描器 trivy, ./install.sh --with-notary --with-trivy --with-chartmuseum [root@localhost harbor]# ll 总用量 596300 drwxr-xr-x 3 root root 20 6月 13 12:34 common -rw-r--r-- 1 root root 3361 11月 9 2021 common.sh -rw-r--r-- 1 root root 5996 6月 13 12:34 docker-compose.yml -rw-r--r-- 1 root root 610560420 11月 9 2021 harbor.v2.3.4.tar.gz -rw-r--r-- 1 root root 7844 6月 13 12:31 harbor.yml -rw-r--r-- 1 root root 7840 11月 9 2021 harbor.yml.tmpl -rwxr-xr-x 1 root root 2500 11月 9 2021 install.sh -rw-r--r-- 1 root root 11347 11月 9 2021 LICENSE -rwxr-xr-x 1 root root 1881 11月 9 2021 prepare

这时候已经安装完成了!

用docker-compose查看Harbor容器的运行状态

[root@localhost harbor]# docker-compose ps Name Command State Ports -------------------------------------------------------------------------------------------------------- harbor-core /harbor/entrypoint.sh Up (healthy) harbor-db /docker-entrypoint.sh 96 13 Up (healthy) harbor-jobservice /harbor/entrypoint.sh Up (healthy) harbor-log /bin/sh -c /usr/local/bin/ ... Up (healthy) 127.0.0.1:1514->10514/tcp harbor-portal nginx -g daemon off; Up (healthy) nginx nginx -g daemon off; Up (healthy) 0.0.0.0:80->8080/tcp,:::80->8080/tcp redis redis-server /etc/redis.conf Up (healthy) registry /home/harbor/entrypoint.sh Up (healthy) registryctl /home/harbor/start.sh Up (healthy) docker-compose基本命令 # 启动Harbor容器 docker-compose start # 停止Harbor容器 docker-compose stop # 暂停Harbor容器 docker-compose pause # 继续运行Harbor容器 docker-compose unpause # 重启Harbor容器 docker-compose restart # 停止并删除Harbor容器,加上-v参数可以同时移除挂载在容器上的目录 docker-compose down # 创建并启动Harbo容器,参数“-d”表示后台运行命令 docker-compose up -d

Harbor访问测试

浏览器输入以下地址或者域名访问Harbor的Web界面,账号密码:admin/harbor12345

本机设置hosts解析

http://www.myharbor.com

创建用户账号并测试上传镜像

创建test用户,新建项目mytest

test:Test123456

在该项目中添加成员:test,开发者角色

在docker客户端机器上设置/etc/docker/daemon.json文件,指向harbor服务器地址

修改为http方式访问(非加密方式)

"insecure-registries":["www.myharbor.com"] { "registry-mirrors": ["https://y9lmbx5j.mirror.aliyuncs.com"], "log-driver":"json-file", "log-opts":{ "max-size" :"50m", "max-file":"1" }, "insecure-registries":["www.myharbor.com"] } # 启动harbor后再修改docker配置文件添加日志,重启harbor会报错,可以在创建harbor之前,修改docker配置文件添加日志 [root@localhost harbor]# docker-compose restart Restarting harbor-jobservice ... done Restarting nginx ... done Restarting harbor-core ... error Restarting redis ... done Restarting harbor-db ... done Restarting registry ... error Restarting harbor-portal ... done Restarting registryctl ... error Restarting harbor-log ... done ERROR: for registry Cannot restart container 784741e36027bf192a4fcd7f55a87c3c46a5edb2d260bbe6c99b1539667e4b77: failed to initialize logging driver: dial tcp [::1]:1514: connect: connection refused ERROR: for registryctl Cannot restart container 1e0e79c308e72ea81a24fa3cdf8eeb38722d5fa59a9115d9ca95c37f29a7417d: failed to initialize logging driver: dial tcp [::1]:1514: connect: connection refused ERROR: for harbor-core Cannot restart container f447ea4319f63e8991efd34c6c0cff0b477321897ed8706e9dcd66ab8e2fa281: failed to initialize logging driver: dial tcp [::1]:1514: connect: connection refused

2.上传镜像到Harbor服务器(私服)

#打标签 docker tag busybox:latest www.myharbor.com/mytest/busybox:v0.1 #登录Harbor服务器 docker login www.myharbor.com #输入我们在harbor新创建的用户名密码进行登录 #上传镜像 # docker push www.myharbor.com/mytest/busybox:v0.1 The push refers to repository [www.myharbor.com/mytest/busybox] 01fd6df81c8e: Pushed v0.1: digest: sha256:62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee size: 527

在Harbor上可以看到我们上传的镜像。

3.Harbor配置HTTPS

生成TSL证书

# 创建存放证书的临时目录 mkdir -p /data/harbor/cert cd /data/harbor/cert # 创建自签名根证书 openssl genrsa -out ca.key 4096 openssl req -x509 -new -nodes -sha512 -days 3650 -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=www.myharbor.com" -key ca.key -out ca.crt # 查看创建的证书 ca.crt ca.key # 产生证书签名请求 openssl genrsa -out www.myharbor.com.key 4096 openssl req -sha512 -new -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=www.myharbor.com" -key www.myharbor.com.key -out www.myharbor.com.csr # 查看证书 # ll 总用量 16 -rw-r--r-- 1 root root 2041 6月 13 12:53 ca.crt -rw-r--r-- 1 root root 3243 6月 13 12:53 ca.key -rw-r--r-- 1 root root 1712 6月 13 12:54 www.myharbor.com.csr -rw-r--r-- 1 root root 3247 6月 13 12:54 www.myharbor.com.key # 为Registry主机产生证书 cat > v3.ext 8080/tcp, 0.0.0.0:443->8443/tcp redis redis-server /etc/redis.conf Up (healthy) registry /home/harbor/entrypoint.sh Up (healthy) registryctl /home/harbor/start.sh Up (healthy) trivy-adapter /home/scanner/entrypoint.sh Up (healthy)

问题:原先harbor.yml文件中使用的端口是80,现在把80端口给注释掉,使用443端口了,但是harbor程序还在监听80端口,原因是使用的docker-compose.yml中nginx容器中有个如下的配置:

ports: - 80:8080 - 443:8443

把80端口的注释掉,然后重启,就只监听443端口了

docker-compose down docker-compose up -d # docker-compose ps Name Command State Ports --------------------------------------------------------------------------------------------- chartmuseum ./docker-entrypoint.sh Up (healthy) harbor-core /harbor/entrypoint.sh Up (healthy) harbor-db /docker-entrypoint.sh 96 13 Up (healthy) harbor-jobservice /harbor/entrypoint.sh Up (healthy) harbor-log /bin/sh -c /usr/local/bin/ ... Up (healthy) 127.0.0.1:1514->10514/tcp harbor-portal nginx -g daemon off; Up (healthy) nginx nginx -g daemon off; Up (healthy) 0.0.0.0:443->8443/tcp redis redis-server /etc/redis.conf Up (healthy) registry /home/harbor/entrypoint.sh Up (healthy) registryctl /home/harbor/start.sh Up (healthy) trivy-adapter /home/scanner/entrypoint.sh Up (healthy)

4.上传镜像以https方式推送到私服

浏览器访问Harbor,通过HTTPS协议访问

通过Docker命令来访问

# 在harbor主机或内网其他机器上 mkdir -p /etc/docker/certs.d/www.myharbor.com scp ca.crt [email protected]:///etc/docker/certs.d/www.myharbor.com/ # 实践操作:只需要ca.crt文件就行了 #scp www.myharbor.com.cert [email protected]:///etc/docker/certs.d/www.myharbor.com/ #scp www.myharbor.com.key [email protected]:///etc/docker/certs.d/www.myharbor.com/ # 无需重启docker即可生效 docker login www.myharbor.com Authenticating with existing credentials... 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 docker tag busybox:latest www.myharbor.com/mytest/busybox:v0.2 docker push www.myharbor.com/mytest/busybox:v0.2 The push refers to repository [www.myharbor.com/mytest/busybox] 01fd6df81c8e: Layer already exists v0.2: digest: sha256:62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee size: 527

5.Harbor仓库忘记管理员密码如何重置

1)通过 dockerexec-it harbor-db/bin/bash命令进入harbor-db容器内部

2)执行如下postgresql命令行

psql -h postgresql -d postgres -U postgres # 这要输入默认密码:root123 psql -U postgres -d postgres -h 127.0.0.1 -p 5432 # 或者用这个可以不输入密码

3)然后切换到harbor所在的数据库,执行 \c registry 命令

4)执行SQL语句 select*fromharbor_user;查看harbor_user表

5)例如修改admin的密码,修改为初始化密码 Harbor12345 修改好了之后再可以从web ui上再改一次。

# 如下此方法不行 update harbor_user set password='a71a7d0df981a61cbb53a97ed8d78f3e',salt='ah3fdh5b7yxepalg9z45bu8zb36sszmr' where username='admin'; # 正确做法 update harbor_user set salt='', password='' where username='admin';

6)执行 \q 退出postgresql,再执行 exit 退出容器。

7)重启harbor服务,以配置中的默认密码进行登陆。

参考链接:https://baike.baidu.com/item/%E8%99%9A%E6%8B%9F%E6%9C%BA/104440?fr=aladdinhttps://baike.baidu.com/item/Docker%E5%AE%B9%E5%99%A8?fromModule=search-resultlemmahttp://dockone.io/article/8350https://blog.csdn.net/m061503020/article/details/125456520https://blog.csdn.net/weixin_46560589/article/details/125184387https://www.cnblogs.com/kire-cat/p/16471962.htmlhttps://www.pudn.com/news/6273ff5c8dbc4529de3d3dd7.htmlhttps://blog.csdn.net/u012632105/article/details/107110243https://www.cnblogs.com/Netsharp/p/15459481.htmlhttps://www.oschina.net/p/harbor?hmsr=aladdin1e1https://www.cnblogs.com/hahaha111122222/p/16370495.html

— THE END —

【免责声明】图文来自网络,版权归原作者所有。如侵权请联系删除;我们对文中观点保持中立,仅供参考、交流之目的。

推荐阅读

Spring Boot整合DataXJava19 正式 GA!看虚拟线程如何大幅提高系统吞吐量比Xshell更全能,更好用的SSH客户端神器,MobaXtermWINDOW定时自动关机脚本(AT和SCHTASKS两种方式)吊打 Electron?Tauri 1.1 正式发布,Rust 编写的桌面 UI 框架!JDK 19 / Java 19正式GACentOS/Ubuntu安装Docker和Docker ComposeMAC Finder在当前目录快捷打开终端MarkText是一款比Typora更简洁优雅的跨平台markdown编辑器,完全开源免费尤雨溪解读 2022 Web 前端生态趋势

微信8.0将好友放开到了一万,宝宝们可以加我大号了,先到先得。

扫描下方二维码即可加我微信啦,2022,抱团取暖,一起牛逼。

产品+技术统称为大技术。分享优秀产品,传播产品思维;专注技术分享,包含JS、CSS、 HTML5、Vue、React、Augula、View UI(iView)、Element UI、Flutter、Electron和JAVA、JVM、SpringBoot、Dubbo、Spring Cloud/Alibaba、Docker、Docker Compose、K8S等实用技术与框架。

请我

分享、

赞、在看

本文来自公众号:大技术


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有