整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

配置Kubernetes动态存储卷遇坑记录


,配置的过程

  1. 创建RBAC授权
wget https://raw.githubusercontent.com/kubernetes-incubator/external-storage/master/nfs-client/deploy/rbac.yaml
kubectl apply -f rbac.yaml
  1. 创建StorageClass

sotrageclass.yaml:


apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-storage
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
  archiveOnDelete: "false"
reclaimPolicy: Delete
  1. 创建provisioner

该provisioner将会自动创建pv,以 −namespace−{pvcName}-${pvName} 的命名格式创建在 NFS 服务器的 /mnt/storage 目录上。

nfs-provisioner-deploy.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-provisioner
  labels:
    app: nfs-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-provisioner
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      serviceAccountName: nfs-provisioner
      containers:
        - name: nfs-provisioner
          image: quay.io/external_storage/nfs-client-provisioner:latest
          volumeMounts:
            - name: nfs-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: fuseim.pri/ifs
            - name: NFS_SERVER
              value: 10.1.36.89
            - name: NFS_PATH
              value: /mnt/storage
      volumes:
        - name: nfs-root
          nfs:
            server: 10.1.36.89
            path: /mnt/storage
  1. 创建有状态应用

nfs-statefulset.yaml:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nfs-web
spec:
  serviceName: "nginx"
  replicas: 3
  selector:
    matchLabels:
      app: nfs-web # has to match .spec.template.metadata.labels
  template:
    metadata:
      labels:
        app: nfs-web
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
      annotations:
        volume.beta.kubernetes.io/storage-class: nfs-storage
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

二,遇到的问题

启动后,发现创建的PVC状态一直处于pending状态。

排查步骤:

  1. Kubectl describe pvc,发现报错信息:waiting for a volume to be created, either by external provisioner “fuseim.pri/ifs” or manually created by system administrator
  2. Kubectl log pod,发现报错信息:unexpected error getting claim reference: selfLink was empty, can’t make reference

利用以上信息,找到相关线索:

kubernetes版本在v1.20起,默认禁止使用SelfLinks。

三,解决的方法

想办法开启SelfLinks。这里提供三种思路

  1. Yaml部署-修改 kube-apiserver.yaml 文件

一般在 /etc/kubernetes 下,可以 find / -name kube-apiserver.yaml 全局搜索,添加如下内容,然后重启kube-apiserver服务即可

  1. 二进制部署-修改kube-apiserver.service

如果没有找到kube-apiserver.yaml文件,比如通过二进制部署的,可以全局搜索 kube-apiserver.service (一般在 /etc/systemd/system/kube-apiserver.service),添加如下内容即可。修改完记得systemctl daemon-reload一下,并重启kube-apiserver服务

  1. Rancher部署-修改cluster.yml

如果是用rancher部署的,那么需要修改其cluster.yml文件如下,然后更新配置:./rke up

问题解决

四,阿里云部署

以上是基于本地部署的k8s进行的动态存储配置,如果是在阿里云上,可以参考:

https://help.aliyun.com/document_detail/204404.html#title-g3c-55i-xs6

众号:渗透师老A
专注分享渗透经验,干货技巧...
.

进入内网之后、是一种由点到线再到面的测试,先弄清楚当前机器的情况,如在域中角色、提供的服务等信息;

再以此为跳板收集其它机器的信息,当收集的信息足够多,拿下域控的可能型也就越高。

一.本机信息收集


为了后续的提权等操作,首先要尽可能拿下当前机器的权限,所以对当前机器的信息收集也是必要的。


|查看系统配置信息

ssysteminfo 查看系统信息,但是内容太多在某些时刻无法通过菜刀等工具看到返回的结果

可以将内容输出到某个文件,也可以结合findstr 查询指定内容

如查询操作系统即软件的信息 systeminfo | findstr /B /C:"OS"

该指令输入的内容是比较多的,除了使用finder选择输出外,部分信息可以使用其它指令单独显示

比如echo %processor_architecture%查看系统架构,net statistics workstation查看系统启动时间

其中的补丁信息可以使用wmic qfe get caption,description,hotfixid,installedon获取

WMIC扩展WMI(Windows Management Instrumentation,Windows管理工具) ,提供了从命令行接口和批命令脚本执行系统管理的支持。

在cmd中有些时候查到的数据不全,如某些进程的pid,这时可以使用wmic进行操作,WMIC提供了大量的全局开关、别名、动词、命令和丰富的命令行帮助增强用户接口。

wmic product get name,version,查看系统安装的软件版本等内容。

wmic /node:localhost /namespace:\root\securitycenter2 path antivirusproduct get displayname /format:list查杀软

初次之外,还可以使用netsh firewall show confignetsh advfirewall firewall show config查看防火墙配置信息

|查看系统服务信息

wmic startup get command,caption,查看启动程序信息

wmic service list brief,查询本机服务信息

还可以使用tasklist 查询进程信息
schtasks /query /fo LIST /V,查看计划任务

netstat -ano查看端口列表

注意,一般查看进程端口,先查进程pid,在根据pid查端口

|查看系统登录信息

query user,登录到系统的用户信息


net session,列出连接会话信息,但是一般需要高权限才能执行

|自动信息收集

很多后渗透模块都可以进行信息收集,这里不谈,分享个嫖到的脚本

for /f "delims=" %%A in ('dir /s /b %WINDIR%\system32\*htable.xsl') do set "var=%%A"

wmic process get CSName,Description,ExecutablePath,ProcessId /format:"%var%" >> out.html
wmic service get Caption,Name,PathName,ServiceType,Started,StartMode,StartName /format:"%var%" >> out.html
wmic USERACCOUNT list full /format:"%var%" >> out.html
wmic group list full /format:"%var%" >> out.html
wmic nicconfig where IPEnabled='true' get Caption,DefaultIPGateway,Description,DHCPEnabled,DHCPServer,IPAddress,IPSubnet,MACAddress /format:"%var%" >> out.html
wmic volume get Label,DeviceID,DriveLetter,FileSystem,Capacity,FreeSpace /format:"%var%" >> out.html
wmic netuse list full /format:"%var%" >> out.html
wmic qfe get Caption,Description,HotFixID,InstalledOn /format:"%var%" >> out.html
wmic startup get Caption,Command,Location,User /format:"%var%" >> out.html
wmic PRODUCT get Description,InstallDate,InstallLocation,PackageCache,Vendor,Version /format:"%var%" >> out.html
wmic os get name,version,InstallDate,LastBootUpTime,LocalDateTime,Manufacturer,RegisteredUser,ServicePackMajorVersion,SystemDirectory /format:"%var%" >> out.html
wmic Timezone get DaylightName,Description,StandardName /format:"%var%" >> out.html

复制为bat文件,结果为out.html保存在c盘根目录,名称路径可自行修改。

二.域内信息收集

|判断是否存在域

whoami,如果当前账户为域用户,则返回结果通常为域名\用户名


ipconfig,如果是双网卡,一般存在内网


systeminfo,如果在域中,则如图,否则为workgroup


net config workstation,在域中,通常计算机全名为计算机名.域名

不在域中如下图

net time /domain,查看时间服务器,域中机器的dns服务器和时间服务器通常为域控机。

如下图则是存在域且当前登录用户为域用户

如下图则表示不在域中

如下图则表示在域中,但当前用户非域用户


除此之外,收集其它内容的时候都能看到,比如系统信息,用户信息等

|探测域内存主机&端口

探测存活主机和端口平时最容易想到的工具是nmap,但这个工具太大,直接安装存在风险,端口转发受限于网络环境,这里聊聊其它方法

powershell

powershell可以在渗透中提供强大的助力,下面这些脚本使用的时候记得修改 ip地址

扫描存活ip,最前面的1..255是ip地址的d段,最后范围是192.168.0.1-255,判断和修改方式下同

1..255 | % {echo "192.168.0.$_"; ping -n 1 -w 100 192.168.0.$_} | Select-String ttl

判断主机类型,根据ttl值判断,范围192.168.0.1-255

1..255 | % {echo "192.168.0.$_"; ping -n 1 -w 100 192.168.0.$_} | Select-String ttl |% { if ($_ -match "ms") { $ttl = $_.line.split('=')[2] -as [int]; if ($ttl -lt 65) { $os = "linux"} elseif ($ttl -gt 64 -And $ttl -lt 129) { $os = "windows"} else {$os = "cisco"}; write-host "192.168.0.$_ OS:$os" ; echo "192.168.0.$_" >> scan_results.txt }}

扫描端口

24..25 | % {echo ((new-object Net.Sockets.TcpClient).Connect("192.168.1.119",$_)) "Port $_ is open!"} 2>$null

24..25 |% {echo "$_ is "; Test-NetConnection -Port $_ -InformationLevel "Quiet" 192.168.1.119}2>null

扫描指定端口的ip

foreach ($ip in 1..20) {Test-NetConnection -Port 80 -InformationLevel "Detailed" 192.168.0.$ip}

arp扫描

在内网里通常使用mac地址进行机器寻找,其可以通过arp协议实现

小工具

由很多免安装的小工具也可以进行扫描,比如nbtscan,直接传到目标服务器上运行即可,工具下载地址:http://www.unixwiz.net/tools/nbtscan.html

用法:nbtscan.exe 网段更多用法参考:nbgtscam.exe /?


含义如下:
|Token|含义|
|——|——|
SHARING|机器正在运行的文件和打印共享服务,但这并不一定有内容共享
DC|机器可能是Windows NT域控制器,无论是主域还是辅助域。
U=user |机器可能有一个具有指定名称的登录用户
IIS |机器可能安装了Microsoft的Internet信息服务器(IIS)
EXCHANGE |机器可能安装Microsoft Exchange
NOTES |单机器可能安装Lotus Notes电子邮件客户端
? |没有识别出NETBIOS资源

telnet

telnet常规使用是和服务器建立连接,也开业用来探测端口是否开放
用法:
telnet 主机 端口telnet dc 3389

注意:不是所有机器都安装了此服务。

|查看用户&机器&会话相关信息

查看机器相关信息

net view /domain,查询域信息,判断当前机器加入的域


net view /domain:域名,查询域内所有主机


在域中,有一类至关重要的机器叫域控制器,简称域控,机器名通常为DC,在实际环境中,域控为一主一备用两台。

netdom query pdc,查看域控名称

查看用户相关信息

net user查询当前机器所有用户net user /domain查看域用户

net user 用户名查看当前机器内的用户信息


net user 用户名 /domain查看当前机器内的域用户信息


注意对比上述结果的区别,此外net user localgroup,net user localgroup /domainnet group /domain也是有区别的

wmic useraccount get /all,获取域内用户的详细信息

、基础概念理解

1.1、镜像 image

1.2、容器 container

1.3、仓库 repository

2、docker安装

参考链接:

https://developer.aliyun.com/mirror/docker-ce?spm=a2c6h.13651102.0.0.3e221b11FUZo7g


系统环境:docker最低支持centos7且在64位平台上,内核版本在3.10以上。

可以通过命令 uname -a 查看版本情况,通过 cat /etc/issue 查看操作系统

[root@node6 ~]# uname -a
Linux node6 3.10.0-1062.4.1.el7.x86_64 #1 SMP Fri Oct 18 17:15:30 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
[root@node6 ~]# cat /etc/issue
\S
Kernel \r on an \m

安装、运行、停止

# 安装docker
yum install -y docker  或者  yum install -y docker-io
# 启动docker 
systemctl start docker 
# 重启docker
systemctl restart docker
# 停止docker 
systemctl stop docker
# 查看docker启动状态
docker version 

如果安装完成后启动报如下错误:

Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service"

按以下步骤解决:

第一步:yum remove docker-* 卸载docker。

第二步:yum update 更新linux系统内核的版本。

然后按照上面的安装步骤重新安装启动即可。

配置镜像加速器

国内从 Docker Hub 拉取镜像有时会遇到困难,此时可以配置镜像加速器。找个国内可使用的镜像加速器地址,以centos为例来看怎们进行配置,镜像加速器可以配置多个:

#国内加速地址
#Docker中国区官方镜像
https://registry.docker-cn.com
#网易
http://hub-mirror.c.163.com
#ustc
https://docker.mirrors.ustc.edu.cn
#中国科技大学
https://docker.mirrors.ustc.edu.cn
#阿里云容器服务
https://cr.console.aliyun.com/
vi /etc/docker/daemon.json
然后编辑输入:
{
  "registry-mirrors": [
    "https://hub-mirror.c.163.com"
  ]
}

3、docker容器基本操作命令

3.1、常用命令

docker search hello-world  # 搜索hello-world的镜像
docker pull hello-docker # 获取centos镜像
docker run  hello-world   #运行一个docker镜像,产生一个容器实例(也可以通过镜像id前三位运行)
docker image ls  # 查看本地所有镜像
docker images  # 查看docker镜像
docker image rmi hello-docker # 删除centos镜像
docker ps  #列出正在运行的容器(如果创建容器中没有进程正在运行,容器就会立即停止)
docker ps -a  # 列出所有运行过的容器记录
docker ps -l #查看最新创建的容器
docker ps -n=xxx #查看最新创建的n个容器
docker save centos > /opt/centos.tar.gz  # 导出docker镜像至本地
docker load < /opt/centos.tar.gz   #导入本地镜像到docker镜像库
docker stop  `docker ps -aq`  # 停止所有正在运行的容器
docker  rm `docker ps -aq`    # 一次性删除所有容器记录
docker rmi  `docker images -aq`   # 一次性删除所有本地的镜像记录

3.2、容器创建、启动、重启、停止、删除

3.2.1、先创建、在启动

创建容器如下:

docker create nginx   #创建一个nginx容器,这个时候创建的容器处于停止状态,未启动,这种创建方式容器名称随机生成,也可以自定义容器名称,如下:
docker create --name=nginx nginx

启动容器如下:

使用 `docker start` 命令结合容器 id 或者容器 name 可以启动一个容器。
一般来说,第一次可以使用 docker run 启动一个容器,以后直接使用 docker start 即可。

3.2.2、创建启动一步到位

3.2.2.1、后台型容器

docker run --name nginx1 -d -p 8080:80 nginx

--name 表示创建的容器的名字,-d 表示容器在后台运行,-p 表示将容器的 80 端口映射到宿主机的 8080 端口。

3.2.2.2、交互型容器

docker run --name ubuntu -it ubuntu /bin/bash

参数含义和后台型容器描述一致,除了 -it,-it 参数,i 表示开发容器的标准输入(STDIN),t 则表示告诉docker,为容器创建一个命令行终端。

想要退出该终端,只需要输入 exit命令即可。

3.2.3、重启容器

容器在运行过程中,会不可避免的出问题,出了问题时,需要能够自动重启,在容器启动时使用 –restart 参数可以实现这一需求。根据 docker 官网的解释,docker 的重启策略可以分为 4 种,如下图:

四种的含义分别如下:

no表示不自动重启容器,默认即此。

on:failure:[max-retries]表示在退出状态为非0时才会重启(非正常退出),有一个可选择参数:最大重启次数,可以设置最大重启次数,重启次数达到上限后就会放弃重启。

always表示始终重启容器,当docker守护进程启动时,也会无论容器当时的状态为何,都会尝试重启容器。

unless-stopped表示始终重启容器,但是当docker守护进程启动时,如果容器已经停止运行,则不会去重启它。

3.2.4、停止容器

使用 `docker stop` 命令结合容器 id 或者容器 name 可以终止一个容器。

3.2.5、删除容器

3.2.5.1、单个删除

docker rm 命令结合容器 id 或者容器 name 可以删除一个容器。删除容器时,只能删除已经停止运行的容器,不能删除正在运行的容器。
如果非要删除一个正在运行的容器,可以通过 -f 参数实现,例如 docker rm -f nginx

3.2.5.2、批量删除

容器也可以批量删除,命令如下:

docker rm $(docker ps -a -q)

docker ps -a -q 会列出所有容器的 id ,供 rm 命令删除。

如下命令也支持删除已退出的孤立的容器:

docker container prune

3.3、参考实战

摘自方志朋博客,参考地址:https://www.fangzhipeng.com/docker/2018/09/12/docker-action.html

docker run -p 80:80 -d  docker.io/nginx
docker cp index.html containerId://usr/share/nginx/html #用于主机和容器之间拷贝数据
docker exec -it containeId /bin/bash
docker images
docker ps [-a -q]
docker stop containerId
docker rm containerId
docker rmi imagesId

docker commit –m ’msg’ containerId [name] 
docker build
docker pull
docker push
docker login

4、docker容器高级操作命令

4.1、容器内执行命令

docker exec -it ubuntu /bin/bash

4.2、查看容器信息

容器创建成功后,用户可以通过 `docker inspect` 命令查看容器的详细信息,这些详细信息包括容器的id 、容器名、环境变量、运行命令、主机配置、网络配置以及数据卷配置等信息。
例如查看unbutu的容器信息, docker inspect ubuntu

使用 format 参数可以只查看用户关心的数据,例如:

#查看容器运行状态
docker inspect -f='{{.State.Running}}' ubuntu 
#查看容器IP地址
docker inspect -f='{{.NetworkSettings.IPAddress}}' ubuntu 
#查看容器名称、ID
docker inspect -f='{{.Name}} {{.ID}}' ubuntu 
#查看容器主机信息
docker inspect -f='{{.HostConfig}}' ubuntu

4.3、查看容器进程

#使用 docker top 命令可以查看容器中正在运行的进程,首先确保容器已经启动,然后执行 docker top 命令,例如:
docker top ubuntu

4.4、查看容器日志

#交互型容器查看日志很方便,因为日志就直接在控制台打印出来了,但是对于后台型容器,如果要查看日志,则可以使用docker提供的 docker logs 命令来查看,例如:
docker logs ubuntu
#默认情况下只能查看到历史日志,无法查看实时日志。使用 -f 参数后,就可以查看实时日志,使用 --tail 参数可以精确控制日志的输出行数, -t 参数则可以显示日志的输出时间,示例:
docker logs -f --tail=3 -t ubuntu 

4.5、导出容器

#参考命令,将nginx容器导出到/home/docker目录下
docker export nginx > /home/docker/nginx.tar

4.6、导入容器

#通过执行如下命令可以导入容器(如果自己重新导入,需要记得将 docker 中和 nginx 相关的容器和镜像删除):
cat nginx.tar | docker import - importednginx:ilatest
#这里需要注意nginx.tar所在目录
#导入成功后就可以使用 docker run命令进行运行了。

5、docker镜像基本操作

5.1、镜像查看

#查看本地所有镜像
docker images
#如果镜像过多,可以通过通配符进行匹配
docker images n*

5.2、镜像下载

#可以首先通过命令查找镜像,例如:
docker search nginx
#然后可以根据查询的结果,拉取镜像到本地
docker pull nginx

5.3、镜像删除

#镜像可以通过 docker rmi 命令进行删除,参数为镜像的id或者镜像名,参数可以有多个,多个参数之间用空格隔开。例如:
docker rmi nginx
#如果无法删除一个镜像,大部分原因是因为该镜像被一个容器所依赖,此时需要先删除容器,然后就可以删除镜像了

5.4、镜像创建

# 一般采用Dockerfile方式,或者使用Jib方式去构建镜像。
# 如果是用单独Dockerfile文件方式构建镜像,可以使用如下命令:
docker build -t mk/nginx1:v2 .
# -t 参数用来指定镜像的命名空间,仓库名以及 TAG 等信息。
# 最后面的 . 是指镜像构建上下文。也就是要打包的所有内容所在路径

6、DockerHub 与容器网络

6.1、简介、登录、上传、下载镜像

Docker Hub 提供镜像托管服务,类似GitHub,Docker Hub 地址为 https://hub.docker.com/

利用 Docker Hub 读者可以搜索、创建、分享和管理镜像。Docker Hub 上的镜像分为两大类,一类是官方镜像,例如nginx、mysql 等,还有一类是普通用户镜像,普通用户镜像由用户自己上传。对于国内用户,如果觉得 Docker Hub 访问速度过慢,可以使用国内一些公司提供的镜像。

例如网易:https://c.163yun.com/hub#/m/home/

接下来以Docker Hub官方镜像站来做演示如下:

# 先注册一个账户
https://hub.docker.com/
# 然后在命令行输入以下命令进行登录,提示Login Succeeded,说民登录成功
docker login
# 接下来就可以使用 push 命令上传我们自制的镜像了。注意,自制的镜像要能够上传,命名必须满足规范,即 namespace/name 格式,其中 namespace 必须是注册的用户名,例如:
docker push mk809311844265/nginx2:v2
# 然后在https://hub.docker.com/官方的Repositories中就可以看到上传的镜像了,之后可以通过pull拉下来上传的镜像文件,例如:
docker pull mk809311844265/nginx2:v2

6.2、自动化构建镜像

自动化构建,就是使用 Docker Hub 连接一个包含 Dockerfile 文件的 GitHub 仓库或者 BitBucket 仓库, Docker Hub 则会自动构建镜像,通过这种方式构建出来的镜像会被标记为 Automated Build ,也称之为受信构建 (Trusted Build) ,这种构建方式构建出来的镜像,其他人在使用时可以自由的查看 Dockerfile 内容,知道该镜像是怎么来的,同时,由于构建过程是自动的,所以能够确保仓库中的镜像都是最新的。实际意义不大,因为一般的公司环境镜像都是需要保密私有的有知识产权的,所以构建本地镜像仓库就成为一个企业应用的必选方案。

6.3、构建自己的 DockerHub

Docker 官方已经将 Docker 注册服务器做成镜像了,我们直接 pull 下来运行即可。

# 第一步:拉取镜像
docker pull registry
# 第二步:实例化容器运行起来
docker run -itd --name registry -p 5000:5000 docker.io/registry
# 第三步:标记本地镜像,以nginx为例
docker tag docker.io/nginx:latest 127.0.0.1:5000/docker.io/nginx:latest
# 第四步:上传本地镜像,以nginx为例
docker push 127.0.0.1:5000/docker.io/nginx:latest
# 第五步: 查看本地仓库中的镜像
curl 127.0.0.1:5000/v2/_catalog
# 第六步: 下载本地仓库的镜像,实现使用 docker images命令查看,发现刚才push的镜像已经在本地镜像存在了,所以需要 docker rmi 命令先去删除该镜像,然后在从本地镜像仓库中下载
docker rmi 127.0.0.1:5000/docker.io/nginx
docker pull 127.0.0.1:5000/docker.io/nginx
    
# 特别说明,如果要在外网可以访问,需要对外开放端口访问
/sbin/iptables -I INPUT -p tcp --dport 5000 -j ACCEPT

设置私有仓库的用户名、密码(该内容不完善,未完待续)

参考如下地址:https://blog.csdn.net/qq_38637558/article/details/99603071

# 第一步:挂载相关的配置,这里注意/docker/registry/auth目录在根目录下,和home目录平级
mkdir -p  /docker/registry/auth
# 第二步:生成账号密码
docker run --entrypoint htpasswd registry:latest -Bbn mk192837 mk_own_123  >> /docker/registry/auth/htpasswd
# 第三步:设置配置文件
mkdir -p  /docker/registry/config
vi  /docker/registry/config/config.yml     ,然后输入以下内容:

================================start===================================
version: 0.1
log:
  fields:
    service: registry
storage:
  delete:
    enabled: true
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
  headers:
    X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
threshold: 3
==================================end===================================    

# 第四步:启动registry容器
docker run -d -p 5000:5000 --restart=always  --name=registry \
-v /docker/registry/config/:/etc/docker/registry/ \
-v /docker/registry/auth/:/auth/ \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-v /docker/registry/:/var/lib/registry/ \
registry

# 第五步:开启 http 形式访问私有仓库模式
vi /etc/docker/daemon.json
# 然后添加如下内容:
{
  "insecure-registries": [
    "192.168.42.105:5000"
  ]
}
# 然后执行如下命令,使配置立刻生效
systemctl daemon-reload
# 重启docker
systemctl restart docker


6.3.1、暴露网络端口(补充知识)

# 暴露网络端口的参数有两个,分别是 `-p` 和 `-P` 。

# 使用 -P,Docker 会在宿主机上随机为应用分配一个未被使用的端口,并将其映射到容器开放的端口,以 Nginx 为例,例如:
docker run -itd --name nginx -P nginx
# 这个时候docker为应用分配了一个随机端口

# -p 参数则有几种不同的用法:
# 第一种: hostPort:containerPort  这种用法是将宿主机端口和容器端口绑定起来,示例:
docker run -itd --name nginx -p 80:80 nginx
# 第二种: ip:hostPort:containerPort  这种是将指定的 ip 地址的端口和容器的端口进行映射,将 192.168.42.1 地址的80端口映射到容器的80端口上,示例:
docker run -itd --name nginx -p 192.168.42.1:80:80 nginx
# 第三种:ip::containerPort  这种是将指定 ip 地址的随机端口映射到容器的开放端口上,示例:
docker run -itd --name nginx -p 192.168.42.1::80 nginx

7、Docker 数据卷操作

7.1、指定数据卷

# 运行nginx容器,并指定一个nginx数据卷
docker run -itd --name nginx -v /usr/share/nginx/html/ -p 80:80 nginx
# 查看数据卷映射目录
docker inspect nginx
# 如下结果,查看Mounts里的Source即可。
"Mounts": [
    {
        "Type": "volume",
        "Name": "eab348836a0c996cdf23aea6983cf5601ec4a571b92f9e610aa19f869d09e653",
        "Source": "/var/lib/docker/volumes/eab348836a0c996cdf23aea6983cf5601ec4a571b92f9e610aa19f869d09e653/_data",
        "Destination": "/usr/share/nginx/html",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
]

7.2、结合宿主机目录

上文中对于数据卷的用法还不是最佳方案,一般来说,我们可能需要明确指定将宿主机中的一个目录挂载到容器中,这种指定方式如下:

docker run -itd --name nginx -v /home/docker/html:/usr/share/nginx/html/ -p 80:80 nginx

这样便是将宿主机中的 /home/docker/html 目录挂载到容器的 /usr/share/nginx/html/ 目录下。接下来只需要在 /home/docker/html 目录下添加 html 文件,或者修改 html 文件,都能在 nginx 访问中立马看到效果。

这种用法对于开发测试非常方便,不用重新部署,重启容器等。

注意:宿主机地址是一个绝对路径

7.3、Dockerfile中的数据卷

如果开发者使用了 Dockerfile 去构建镜像,也可以在构建镜像时声明数据卷,例如下面这样:

FROM nginx
ADD https://www.baidu.com/img/bd_logo1.png /usr/share/nginx/html/
RUN echo "hello docker volume!">/usr/share/nginx/html/index.html
VOLUME /usr/share/nginx/html/

这样就配置了一个匿名数据卷,运行过程中,将数据写入到 /usr/share/nginx/html/ 目录中,就可以实现容器存储层的无状态变化。

7.4、查看所有数据卷

# 采用如下命令
docker volume ls

7.5、查看数据卷详情

# 根据 volume name 可以查看数据详情
docker volume inspect f38d71202a6d55234417cede029dfa465884746c2dd4d4119a40770435950829

7.6、删除数据卷

# 可以使用 docker volume rm 命令删除一个数据卷,也可以使用 docker volume prune 批量删除数据卷,如下:
docker volume rm f38d71202a6d55234417cede029dfa465884746c2dd4d4119a40770435950829
# 或者
docker volume prune
# 批量删除时,如果未能删除掉所有的数据卷,因为该数据卷还在使用中,将相关的容器停止并移除,再次删除数据卷就可以成功删除了

7.7、数据卷容器

数据卷容器是一个专门用来挂载数据卷的容器,该容器主要是供其他容器引用和使用。所谓的数据卷容器,实际上就是一个普通的容器,举例如下:

  • 创建数据卷容器
# 使用如下方式创建数据卷容器:
docker run -itd -v /usr/share/nginx/html/ --name mydata ubuntu
  • 引用容器
# 使用如下命令引用数据卷容器:
docker run -itd --volumes-from mydata -p 80:80 --name nginx1 nginx
docker run -itd --volumes-from mydata -p 81:80 --name nginx2 nginx

此时, nginx1 和 nginx2 都挂载了同一个数据卷到 /usr/share/nginx/html/ 目录下,三个容器中,任意一个修改了该目录下的文件,其他两个都能看到变化。

此时,使用 docker inspect 命令查看容器的详情,发现三个容器关于数据卷的描述都是一致的。

7.8、数据卷容器实现数据的备份与恢复

7.8.1、数据备份

docker run --volumes-from mydata --name backupcontainer -v $(pwd):/backup/ ubuntu tar cvf /backup/backup.tar /usr/share/nginx/html/
# 首先使用 --volumes-from 连接待备份容器。
# -v 参数用来将当前目录挂载到容器的 /backup 目录下。
# 接下来,将容器中 /usr/share/nginx/html 目录下的内容备份到 /backup 目录下的 backup.tar 文件中,由于已经设置将当前目录映射到容器的 /backup 目录,因为备份在容器 /backup 目录下的压缩文件在当前目录下可以立马看到。

备份完成后,在当前目录下就可以看到 /backup 文件,打开压缩文件,发现就是 /usr/share/nginx/html 目录及内容。

7.8.2、数据恢复

# 步骤一:创建容器
# 首先创建一个容器,这个容器就是要使用恢复的数据的容器,这里创建一个 nginx 容器,如下:
docker run -itd -p 80:80 -v /usr/share/nginx/html/ --name nginx3 nginx
# 创建一个名为 nginx3 的容器,并且挂载一个数据卷。

# 步骤二:恢复
# 数据恢复需要一个临时容器,如下:
docker run --volumes-from nginx3 -v $(pwd):/backup nginx tar xvf /backup/backup.tar

# 命令解释:
# 首先还是使用 --volumes-from 参数连接上备份容器,即第一步创建出来的 nginx3 。
# 然后将当前目录映射到容器的 /backup 目录下。
# 然后执行解压操作,将 backup.tar 文件解压。解压文件位置描述是一个容器内的地址,但是该地址已经映射到宿主机中的当前目录了,因此这里要解压缩的文件实际上就是宿主机当前目录下的文件。

8、Docker 容器连接

一般来说,容器启动后,我们都是通过端口映射来使用容器提供的服务,实际上,端口映射只是使用容器服务的一种方式,除了这种方式外,还可以使用容器连接的方式来使用容器服务。

例如,有两个容器,一个容器运行一个 SpringBoot 项目,另一个容器运行着 mysql 数据库,可以通过容器连接使 SpringBoot 直接访问到 Mysql 数据库,而不必通过端口映射来访问 mysql 服务。

举另外一个例子:

有两个容器,一个 nginx 容器,另一个 ubuntu ,我启动 nginx 容器,但是并不分配端口映射,然后再启动 ubuntu ,通过容器连接,在 ubuntu 中访问 nginx

具体操作步骤如下:

  • 首先启动一个 nginx 容器,但是不分配端口,命令如下:
docker run -d --name nginx1 nginx

容器启动成功后,在宿主机中是无法访问的。如下:

[root@node5 ~]# curl http://localhost:80
curl: (7) Failed connect to localhost:80; Connection refused
  • 启动ubuntu

接下来,启动一个 ubuntu ,并且和 nginx 建立连接,如下:

docker run -dit --name ubuntu --link nginx1:mylink ubuntu bash

这里使用 –link 建立连接,nginx1 是要建立连接的容器,后面的 mylink 则是连接的别名。

运行成功后,进入到 ubuntu 命令行:

docker exec -it ubuntu bash

然后,有两种方式查看 nginx 的信息:

第一种

在 ubuntu 控制台直接输入 env ,查看环境变量信息:

MYLINK_ENV_NJS_VERSION=0.3.9
HOSTNAME=96efd0f2f329
MYLINK_PORT=tcp://172.17.0.4:80
MYLINK_NAME=/ubuntu/mylink
PWD=/
MYLINK_PORT_80_TCP=tcp://172.17.0.4:80
MYLINK_PORT_80_TCP_PORT=80
HOME=/root
MYLINK_PORT_80_TCP_PROTO=tcp
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
TERM=xterm
SHLVL=1
MYLINK_PORT_80_TCP_ADDR=172.17.0.4
MYLINK_ENV_PKG_RELEASE=1~buster
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MYLINK_ENV_NGINX_VERSION=1.17.10
_=/usr/bin/env

可以看到 docker 为 nginx 创建了一系列环境变量。每个前缀变量是 MYLINK ,这就是刚刚给连接取得别名。开发者可以使用这些环境变量来配置应用程序连接到 nginx 。该连接是安全、私有的。 访问结果如下:

root@96efd0f2f329:/# curl http://172.17.0.4:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

第二种

另一种方式则是查看 ubuntu 的 hosts 文件: cat /etc/hosts,如下:

root@96efd0f2f329:/# cat  /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.4  mylink a918eb2fdfbc nginx1
172.17.0.3  96efd0f2f329

可以看到,在 ubuntu 的 hosts 文件中已经给 nginx1 取了几个别名,可以直接使用这些别名来访问 nginx1

root@96efd0f2f329:/# curl http://mylink 
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

默认情况下,ubuntu 容器中没有安装 curl 命令,需要手动安装下,安装命令如下: apt-get update apt-get install curl

9、Docker 容器编排入门案例

在实际的开发环境或者生产环境,容器往往都不是独立运行的,经常需要多个容器一起运行,此时,如果继续使用 run 命令启动容器,就会非常不便,在这种情况下,docker-compose 是一个不错的选择,使用 docker-compose 可以实现简单的容器编排,本文就来看看 docker-compose 的使用。

本文以 jpress 这样一个开源网站的部署为例,向读者介绍 docker-compose 的使用。jpress 是 Java 版的 wordPress ,不过我们不必关注 jpress 的实现,在这里我们只需要将之当作一个普通的应用即可,完成该项目的部署工作。

步骤一:编写Dockerfile文件

FROM tomcat
ADD jpress-v3.1.0.war /usr/local/tomcat/webapps/
RUN cd /usr/local/tomcat/webapps/ \
    && mv jpress-v3.1.0.war jpress.war
# 这里要特别注意:jpress-v3.1.0.war文件需要放在和Dockerfile同一个目录下才可以,否则build时候会报错。
# 命令解释如下:
# 1、容器基于 Tomcat 创建。
# 2、下载 jpress 项目的 war 包到 tomcat 的 webapps 目录下。
# 3、给 jpress 项目重命名。

步骤二:编写 docker-compose.yml

version: "3.1"
services:
  web:
    build: .
    container_name: jpress
    ports:
      - "8080:8080"
    volumes:
      - /usr/local/tomcat/
    depends_on:
      - db
  db:
    image: mysql
    container_name: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: 123
      MYSQL_DATABASE: jpress
# 这里同样要注意,需要将docker-compose.yml文件放在和Dockerfile文件相同目录下
# 命令解释如下:
# 1、首先声明了 web 容器,然后声明db容器。
# 2、build . 表示 web 容器项目构建上下文为 . ,即,将在当前目录下查找 Dockerfile 构建 web 容器。
# 3、container_name 表示容器的名字。
# 4、ports 是指容器的端口映射。
# 5、volumes 表示配置容器的数据卷。
# 6、depends_on 表示该容器依赖于 db 容器,在启动时,db 容器将先启动,web 容器后启动,这只是启动时机的先后问题,并不是说 web 容器会等 db 容器完全启动了才会启动。
# 7、对于 db 容器,则使用 image 来构建,没有使用 Dockerfile 。
# 8、restart 描述了容器的重启策略。
# 9、environment 则是启动容器时的环境变量,这里配置了数据库 root 用户的密码以及在启动时创建一个名为 jpress 的库,environment 的配置可以使用字典和数组两种形式。

步骤三:运行

# 运行命令如下:  
docker-compose up -d  # -d 表示在后台运行

步骤四:查看已运行的容器

# 运行命令如下:
docker-compose ps

步骤五:重启容器

# 运行命令如下:
docker restart jpress   # jpress为容器名称

步骤六:停止容器

# 运行命令如下:
docker-compose down
更多使用命令可以采用   docker-compose --help 来查看帮助进行使用。

特别补充:如果使用docker-compose提示“-bash: docker-compose: command not found”,那么请按照以下说明进行docker-compose安装即可

# 方式1:
curl -L https://get.daocloud.io/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
    
chmod +x /usr/local/bin/docker-compose

# 方式2:
1)先安装 pip ,检查是否已有: pip -V 
报错:
-bash: pip: command not found
安装  pip :
yum -y install epel-release
yum -y install python-pip
#升级
pip install --upgrade pip
2) 安装Docker-Compose:
pip install docker-compose
检查是是否成功:
docker-compose -version

10、Dockerfile 命令

可以参考以下链接进行详细学习:

1、Dockerfile 指令详解

https://yeasy.gitbook.io/docker_practice/image/dockerfile

2、Dockerfile指令详解 && ENTRYPOINT 指令

https://www.cnblogs.com/reachos/p/8609025.html

命令用途WORKDIRRUN ENTRYPINT CMD执行的工作目录ENV添加环境变量ADD添加文件,会解压压缩包COPY复制文件ONBUILD触发器VOLUME挂载卷FROM基础镜像ENTRYPOINT基础命令RUN执行命令CMD启动程序命令,拼接在基础命令后EXPOSE暴露端口MAINTAINER维护者


11、参考地址

1、https://www.runoob.com/docker/docker-tutorial.html

2、http://www.javaboy.org/categories/docker/