Dawn's Blogs

分享技术 记录成长

0%

Compose

Compose 项目负责实现对 Docker 容器集群的快速编排,用于快速部署分布式应用。

Compose 定位是 「定义和运行多个 Docker 容器的应用(Defining and running multi-container Docker applications)」

介绍

Compose 允许用户通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。 Compose 中有两个重要概念:

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

一个项目可以由多个服务(容器)关联而成,Compose 面向项目进行管理。

Machine

Docker Machine 是 Docker 官方编排(Orchestration)项目之一,负责在多种平台上快速安装 Docker 环境。

Swarm mode

Swarm 提供 Docker 容器集群服务,使用它,用户可以将多个 Docker 主机封装为单个大型的虚拟 Docker 主机,快速打造一套容器云平台。

基本概念

节点

集群中的节点分为管理(manager)节点和工作(worker)节点:

  • 管理节点:用于集群的管理,一个 swarm 集群中可以有多个管理节点,但是只能有一个 leader 节点,leader 节点由 raft 算法选举出。docker swarm 命令基本只能在管理节点执行(除了 docker swarm leave 命令可以在工作节点执行)。
  • 工作节点:用于执行任务,管理节点将服务 (service) 下发至工作节点执行。管理节点也默认为工作节点。

img

服务和任务

  • 任务(Task)是 swarm中最小的调度单位,目前来说就是一个单一的容器。
  • 服务(Services)是指一组任务的集合,服务定义了任务的属性。服务有两种模式,通过 docker service create--mode 参数指定:
    • replicated services:按照一定规则在各个工作节点上运行指定个数的任务。
    • global services:每个工作节点上运行一个任务。

下图是容器、服务、任务的关系:

img

数据管理

在容器中管理数据主要有两种方式:

  • 数据卷(Volumes)
  • 挂载主机目录(Bind mounts)

数据卷

数据卷 是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:

  • 数据卷 可以在容器之间共享和重用
  • 数据卷 的修改会立马生效
  • 数据卷 的更新,不会影响镜像
  • 数据卷 默认会一直存在,即使容器被删除

数据卷的操作

  • docker volume create 命令:创建数据卷。
1
2
C:\Users\63544>docker volume create my-vol
my-vol
  • docker volume ls 命令:查看所有的数据卷。
1
2
3
C:\Users\63544>docker volume ls
DRIVER VOLUME NAME
local my-vol
  • docker volume inspect 命令:查看指定数据卷。
1
2
3
4
5
6
7
8
9
10
11
12
C:\Users\63544>docker volume inspect my-vol
[
{
"CreatedAt": "2022-05-12T13:46:43Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
"Name": "my-vol",
"Options": {},
"Scope": "local"
}
]
  • 在用 docker run 命令的时候,使用 --mount 标记来将 数据卷 挂载到容器里。在一次 docker run 中可以挂载多个 数据卷

  • 在用 docker run 命令的时候,使用 --mount 标记来将 数据卷 挂载到容器里。在一次 docker run 中可以挂载多个 数据卷

1
2
3
--mount source=数据卷名,target=容器目录
# 等价于
-v 数据卷名:容器目录
  • docker volume rm 命令:删除数据卷。docker volume prune 命令:删除所有无主的数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v 这个命令。

挂载主机目录

  • 使用 --mount 标记可以指定挂载一个本地主机的目录到容器中去。
1
2
3
--mount type=bind,source=主机目录,target=挂载点
# 等价于
-v 宿主机绝对路径目录:容器内挂载点

也可以挂载一个主机文件到容器中:

1
--mount type=bind,source=$HOME/.bash_history,target=/root/.bash_history

这样就可以记录在容器输入过的命令了。

docker 目录主机目录/数据卷出现 cannot open directory. Permission denied 错误,解决方法:

加上 –privileged=true 参数。在SELinux里面挂载目录被禁止了,如果要开启,我们一般使用–privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题。即使用该参数,container内的root拥有真正的root权限;否则,container内的root只是外部的一个普通用户权限。

读写权限设置:

  • 读写(read write,rw):容器可以对主机目录/数据卷进行读写操作,默认。

    1
    -v /宿主机绝对路径目录或者数据卷名:/容器内目录:rw
  • 只读(read only,ro):容器实例内部被限制,只能读取不能写。

    1
    -v /宿主机绝对路径目录或者数据卷名:/容器内目录:ro

网络

当 Docker 启动时,会自动在主机上创建一个 docker0 虚拟网桥。同时,Docker 随机分配一个本地未占用的私有网段中的一个地址给 docker0 接口。此后启动的容器内的网口也会自动分配一个同一网段的地址。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间一个虚拟共享网络:

Docker 网络

介绍

作用

Docker 网络的作用如下:

  • 容器间的互联通信端口映射

  • 把多个容器放在同一个 Docker 网桥下,可以通过服务名(容器名)直接网络通信,而不使用 IP 地址。

外部访问容器

容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P-p 参数来指定端口映射:

  • 当使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。
  • -p 则可以指定要映射的端口。

容器互联

  • docker network create -d bridge my-net 命令:创建网络。
  • docker run 运行容器时,可以使用 --network 加入到一个网络中。

多个容器可以加入到同一个网络中,实现容器之间的互联。

常用命令

docker 网络的常用命令如下:

  • 新建网络(网桥):docker network 网络名字

  • 查看网络:docker network ls

  • 查看网络信息:docker network inspect 网络名字

  • 删除网络:docker network rm 网络名字

网络模式

网络模式有四种,分别是:

  • bridge 模式
  • host 模式
  • none 模式
  • container 模式

bridge

使用 –network bridge 指定,默认使用 docker0。docker run 的时候,没有指定 network 的话默认使用的网桥模式就是 bridge,使用的就是 docker0。

Docker 在宿主机虚拟一个 Docker 容器网桥(默认 docker0),Docker 启动一个容器时会根据 Docker 网桥的网段分配给容器一个 IP 地址,称为 Container-IP,同时 Docker 网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的 Container-IP 直接通信

网桥创建一对对等虚拟设备接口一个叫 veth(网桥端),另一个叫 eth0(容器端),成对匹配。

image-20221228163656973

host

使用–network host 指定,该模式直接使用宿主机的 IP 地址与外界进行通信,不再需要额外进行NAT 转换。

容器将不会获得一个独立的 Network Namespace, 而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡而是使用宿主机的IP和端口。

image-20221228164308411

注意:

在使用 host 模式时,无法使用 -p 进行端口映射(会发生 warning),端口映射不起作用。

none

使用–network none 指定,在 none 模式下,并不为 Docker 容器进行任何网络配置

也就是禁用网络功能,只有lo标识(127.0.0.1,表示本地回环地址)。

container

使用 –network container:NAME或者容器ID 指定

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

image-20221228164705206

操作容器

列出容器

使用 docker ps [OPTIONS] 命令列出容器:

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

启动

启动容器有两种方式:

  • 一种是基于镜像新建一个容器并启动 docker run

    1
    docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

    OPTIONS 说明:

    • –name=”容器新名字”: 为容器指定一个名称;

    • -d:后台运行容器并返回容器ID,也即启动守护式容器;

    • -i:以交互模式运行容器,通常与 -t 同时使用;

    • -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;

    • -P:随机端口映射;

    • -p:指定端口映射;

    image-20221223100302221

    启动交互式容器:

    1
    docker run -it ubuntu /bin/bash

    使用镜像ubuntu:latest以交互模式启动一个容器,在容器内执行 /bin/bash 命令。

  • 另外一个是将在终止状态(stopped)的容器重新启动 docker start

  • 重启容器:docker restart 容器名/容器ID

后台运行

可以通过 -d 参数实现容器的后台运行:

1
2
C:\Users\63544>docker run -d ubuntu:18.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
905b8470023fe399cdc97f579cfef7def7450cf62874685ca64e7c7d223b4e78

此时容器会在后台运行并不会把输出的结果打印到宿主机的STDOUT上面(输出结果可以用 docker logs 查看):

1
2
3
4
5
6
7
8
C:\Users\63544>docker container logs 905b
hello world
hello world
hello world
hello world
hello world
hello world
hello world

使用 -d 参数启动后会返回一个唯一的 id,也可以通过 docker container ls 命令来查看容器信息(docker ps 命令也可以查看容器信息):

1
2
3
C:\Users\63544>docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
905b8470023f ubuntu:18.04 "/bin/sh -c 'while t…" About a minute ago Up About a minute stupefied_pike

终止容器

可以使用 docker stop 来终止一个运行中的容器。

此外,当 Docker 容器中指定的应用终结时,容器也自动终止。

进入容器

在使用 -d 参数时,容器会在后台运行。那么可以使用 attach 或者 exec 命令进入容器:

  • docker attach 命令:如果从这个 stdin 中 exit,会导致容器的停止。

  • docker exec 命令:如果从这个 stdin 中 exit,不会导致容器的停止。推荐使用 exec 命令

    • -i 参数:只是打开容器的 STDIN,此时没有 Linux 命令提示符。
    • -it 参数:可以看到 Linux 命令提示符。

导入和导出容器

  • docker export 命令:可以导出容器。
1
docker export 7691a814370e > ubuntu.tar
  • docker import 命令:从容器快照文件中再导入为镜像。

删除容器

  • 可以使用 docker rm 来删除一个处于终止状态的容器。
    • 如果要删除一个运行中的容器,可以添加 -f 参数。
  • docker container prune 清除所有处于终止状态的容器。

重要操作

启动守护式容器

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

1
docker run -d 容器名

启动前台交互式容器

1
2
3
$ docker run -it 容器名 bashShell
UID PID PPID C STIME TTY TIME CMD
root 5007 4987 0 02:54 ? 00:00:00 bash

查看容器日志

1
docker logs 容器ID

查看容器内运行的进程

1
docker top 容器ID

查看容器内部细节

1
docker inspect 容器ID

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

可以用两个命令:

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

两种命令的区别:

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

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

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

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

导入和导出容器

  • export:导出容器的内容留作为一个tar归档文件。

    1
    docker export 容器ID > 文件名.tar
  • import:从tar包中的内容创建一个新的文件系统再导入为镜像。

    1
    cat 文件名.tar | docker import - 镜像名:镜像版本号

访问仓库

Docker Hub

Docker 官方维护了一个公共仓库 Docker Hub:

  • docker search 命令可以查找官方仓库中的镜像。

  • docker pull 命令下载镜像到本地。

  • 在登录后,可以使用 docker push username/镜像名:标签 将自己的镜像推送到 Docker Hub 中。


若不想使用官方的 Docker Hub 仓库,也可以创建私有仓库。

使用镜像

搜索镜像

使用docker search命令可以搜索镜像:

1
2
3
4
5
6
7
8
$ docker search redis
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
redis Redis is an open source key-value store that… 11669 [OK]
bitnami/redis Bitnami Redis Docker Image 236 [OK]
redislabs/redisinsight RedisInsight - The GUI for Redis 75
redislabs/redisearch Redis With the RedisSearch module pre-loaded… 56
redislabs/rejson RedisJSON - Enhanced JSON data type processi… 51
redislabs/redis Clustered in-memory database engine compatib… 36

获取镜像

从 Docker 镜像仓库获取镜像的命令是 docker pull。其命令格式为:

1
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
  • Docker 镜像仓库地址:地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub。
  • 仓库名:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。

使用 docker run 命令可以运行容器。

阅读全文 »

Docker介绍

什么是Docker

Docker是基于Go语言开发并实现的,基于Linux内核的cgroups(control groups,控制群组,是Linux内核的一个功能,用来限制、控制与分离一个进程组的资源,如CPU、内存等)、namespace(是Linux内核用来隔离内核资源的方式,通过namespace可以让一些进程只能看到与自己相关的一部分资源,而另外一些进程也只能看到与它们自己相关的资源)以及Union FS等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术

Docker和传统虚拟化技术的不同:

传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程:

传统虚拟化

Docker容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便:

Docker

为什么使用Docker

Docker与传统虚拟化技术相比,有如下优点

  • 更高效的利用系统资源:Docker不需要对硬件虚拟化以及运行完整的操作系统等额外开销,所以Docker对系统资源的利用更有效。在相同配置下,Docker可以运行更多的应用程序。
  • 更快速的启动时间:Docker容器运行于宿主内核,启动速度可以达到秒级。
  • 一致的运行环境:Docker镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性。
  • 持续交付和部署:一次创建或配置,可以在任意地方正常运行。
  • 更轻松的迁移:Docker确保了执行环境的一致性,使得应用的迁移更加容易。
  • 更轻松的维护和扩展:Docker使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。
特性 Docker容器 传统虚拟机
启动 秒级 分钟级
硬盘使用 一般为 MB 一般为 GB
性能 接近原生 弱于
系统支持量 单机支持上千个容器 一般几十个

基本概念

Docker包括三个基本概念:

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

镜像

对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统。

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

分层存储

Docker设计时,就充分利用了Union FS(联合文件系统)技术,将其设计为分层存储的结构。

镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组(多层)文件系统组成。

镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。

分层存储使得镜像的复用、定制更加容易,可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。

docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成。

  • bootfs(boot file system)主要包含bootloader和kernel。bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是引导文件系统bootfs。这一层与典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

  • rootfs(root file system),在bootfs之上。包含的就是典型 Linux 系统中的/dev、/proc、/bin、/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,如Ubuntu、CentOS等。

image-20221223111944166

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

容器

镜像和容器的关系,就像是类和实例的关系。镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的经常运行在一个隔离的环境里,因此也更加的安全。

容器存储层

容器也使用分层存储,每一个容器运行时,以镜像为基础层,在其上创建一个当前容器的存储层用于容器运行时的读写,称为容器存储层。只有容器层是可写的,容器层下面的所有镜像层都是只读的

image-20221223112458661

容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。因此所有的文件写入操作,都应该使用数据卷(Volume),数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。

仓库

Docker Registry用于提供集中的存储、分发镜像的服务。

一个Docker Registry中可以包含多个仓库(Repository),每个仓库包含多个标签(Tag,标签用于指明镜像的版本),每个标签对应一个镜像

可以通过<仓库名>:<标签>指定哪个版本的镜像,默认标签为latest

整数反转

整数反转

解题思路

通过模10的方法取出最低位数字,通过除以10去掉最低为数字。

解题代码

1
2
3
4
5
6
7
8
9
10
11
12
13
func reverse(x int) int {
var res int
for x != 0 {
res = res*10 + x%10
x = x/10
}

if res > math.MaxInt32 || res < math.MinInt32 {
return 0
}

return res
}
阅读全文 »

聚类

非监督学习

在非监督学习中,我们的数据没有附带任何标签,我们拿到的数据如下图。在这里我们有一系列点,却没有标签。

img

也就是说,在非监督学习中,我们需要将一系列无标签的训练数据,输入到一个算法中,然后我们告诉这个算法,快去为我们找找这个数据的内在结构给定数据。我们可能需要某种算法帮助我们寻找一种结构。图上的数据看起来可以分成两个分开的点集(称为簇),一个能够找到这些点集的算法,就被称为聚类算法。

当然,非监督算法不只是用来分簇,也可以为我们找到其他类型的结构或者其他的一些模式。

阅读全文 »

支持向量机

目标函数

以下是支持向量机SVM的目标函数,其形式于逻辑回归的形式类似,其中需要注意的是:

  • 在SVM中,删除了在逻辑回归里第一项中的1/m。因为1/m仅仅是一个常量,因此,你在这个最小化问题中,无论前面是否有这一项,最终所得到的最优值θ都是一样的。
  • 对于逻辑回归的目标函数中,有两项:第一个是训练样本的代价,第二个是我们的正则化项,其形式为A+λB。但是在SVM中,我们将使用一个不同的参数替换这里使用的λ来权衡这两项,其形式为CA+B。因此,在逻辑回归中,如果给定λ一个非常大的值,意味着给予B更大的权重。在SVM中,就对应于将C设定为非常小的值,那么,相应的将会给B比给A更大的权重。
  • 在逻辑回归中,输出的是y=1的概率。而在SVM中,当θ^Tx大于等于0时,会输出1,否则输出0

img

阅读全文 »

应用及其学习的建议

决定下一步做什么

当我们运用训练好了的模型来预测未知数据的时候发现有较大的误差,我们下一步可以做什么?

  • 获得更多的训练样本
  • 尝试减少特征的数量,防止过拟合
  • 需要更多的特征
  • 尝试增加多项式特征
  • 减少/增加正则化程度λ

我们不应该随机选择上面的某种方法来改进我们的算法,而是运用一些机器学习诊断法来帮助我们知道上面哪些方法对我们的算法是有效的。

阅读全文 »

概述

模型

下面展示一个最简单的神经网络,共有三层。第一层称为输入层,最后一层称为输出层,中间层次被称为隐藏层(隐藏层不止一层)

神经网络

a表示激活项 。Θ表示权重矩阵,它控制从一层到下一层得映射:

1649386481865

以下是激活项的计算公式,其中g代表sigmoid函数。需要注意的是,对于第j层向第j+1层映射的权重矩阵而言,行的数量等于下一层j+1的单元数量,列的数量等于本层j的单元数量+1(因为需要加上偏置单元,x0=1)。

1649386883950

阅读全文 »