Docker进阶

1. 前言

docker容器本质上是宿主机的进程,Docker通过namespace实现了资源隔离,通过cgroups实现了资源限制,通过写时复制机制(copy-on-write)实现了高效的文件操作。
容器=namespace+cgroup+rootfs+容器引擎(用户态工具)
其中各项的功能分别为:

  • Namespace:访问隔离
  • Cgroup:资源控制
  • rootfs:文件系统隔离
  • 容器引擎:生命周期控制

目前市场上所有的Linux容器都包含了以上组件,一般来说,容器技术主要包括Namespace和Croup这两个内核特性。

2. Namespace

namespace又称命名空间,它主要做访问隔离。其原理是针对一类资源进行抽象,并将其封装在一起提供给一个容器使用,对于这类资源,因为每个容器都有自己的抽象,而它们彼此之间是不可见的,所有就可以做到访问隔离。

namespace是将内核的全局资源做封装,使得每个namespace都有一份独立的资源,因此不同的进程在各自的namespace内对同一种资源的使用不会互相干扰。

目前Linux内核总共实现了6种namespace。

2.1 IPC:隔离System V IPC和POSIX消息队列

IPC是Inter-Process Communication的简写,也就是进程间通信。Linux提供了很多种进程间通信的机制,IPC Namespace针对的是SystemV IPC和Posix消息队列。这些IPC机制都会用到标识符,例如用标识符来区别不同的消息队列,然后两个进程通过标识符找到对应的消息队列进行通信等。

IPC Namespace能做到的事情是,是相同的标识符在两个Namespace中代表不同的消息队列,这样也就使得两个Namespace中的进程不能通过IPC进程通信了

2.2 Network:隔离网络资源

这个Namespace会对网络相关的系统资源进行隔离,每个Network Namespace都有自己的网络设备、IP地址、路由表、/proc/net目录、端口号等。网络隔离的必要性是很明显的,举一个例子,在没有隔离的情况下,如果两个不同的容器都想要运行同一个Web应用,而这个应用有需要使用80端口,那就会有冲突了。

2.3 Mount:隔离文件系统挂载点

Mount Namespace用来隔离文件系统挂载点,每个进程能看到的文件系统都记录在/proc/$$/mounts里。在创建了一个新的Mount Namespace后,进程系统对文件系统挂载/卸载的动作就不会影响到其他Namespace。

2.4 PID:隔离进程ID

PID Namespace用于隔离进程PID号,这样一来,不同的Namespace里的进程PID号就可以是一样的了

2.5 UTS:隔离主机名和域名

UST Namespace用于对主机名和域名进行隔离,为什么要使用UTS Namespace做隔离?这是因为主机名可以用来代替IP地址,因此,业绩可以使用主机名在网络上访问某台机器了,如果不做隔离,这个机制在容器里就会出问题

2.6 User:隔离用户ID和组ID

User Namespace用来隔离用户和组ID,也就是说一个进程在Namespace里的用户和组ID与它在host里的ID可用不一样,User Namespace最有用的地方在于,host的普通用户进程在容器里可以是0号用户,也就是root用户。这样,进程在容器内可以做各种特权操作,但是它的特权被限定在容器内,离开了这个容器它就只有普通用户的权限了。

容器内的这类root用户,实际上还是有很多特权不能执行,基本上如果这个特权操作会影响到其他容器或者host,就不会被允许。

3. Cgroup

cgroup是control group 的简称,又称控制组,它主要是做资源控制。其原理是将一组进程放在一个控制组里,通过给这个控制组分配指定的可用资源,达到控制这一组进程可用资源的目的。

Cgroup的具体作用如下:

限制资源的使用:Cgroup可以对进程组使用的资源总额进行限制;
优先级控制:通过分配CPU时间片数量及磁盘IO带宽大小,实际上就是相当于控制子进程运行的优先级。
资源统计:Cgroup可以统计系统资源使用量,比如CPU使用时间,内存使用量等。可用于按量计费。
进程控制:恢复执行进程

3.1 查询系统中已经挂载的cgroup的文件系统

root@ubuntu-template:~# mount -t cgroup
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,name=systemd)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)

3.2 cgroup子系统介绍

blkio – 这个子系统为块设备设定输入/输出限制,比如物理设备(磁盘,固态硬盘,USB 等等)。
cpu – 这个子系统使用调度程序提供对 CPU 的 cgroup 任务访问。
cpuacct – 这个子系统自动生成 cgroup 中任务所使用的 CPU 报告。
cpuset – 这个子系统为 cgroup 中的任务分配独立 CPU(在多核系统)和内存节点。
devices – 这个子系统可允许或者拒绝 cgroup 中的任务访问设备。
freezer – 这个子系统挂起或者恢复 cgroup 中的任务。
memory – 这个子系统设定 cgroup 中任务使用的内存限制,并自动生成由那些任务使用的内存资源报告。
net_cls – 这个子系统使用等级识别符(classid)标记网络数据包,可允许 Linux 流量控制程序(tc)识别从具体 cgroup 中生成的数据包。
ns – 名称空间子系统

3.3 内存资源限制

默认启动一个 容器,是没有限制内存使用率,可以使用系统内存的最大值

# 下载一个测试镜像
root@ubuntu-template:~# docker pull lorel/docker-stress-ng
Using default tag: latest
latest: Pulling from lorel/docker-stress-ng
Image docker.io/lorel/docker-stress-ng:latest uses outdated schema1 manifest format. Please upgrade to a schema2 image for better future compatibility. More information at https://docs.docker.com/registry/spec/deprecated-schema-v1/
c52e3ed763ff: Pull complete 
a3ed95caeb02: Pull complete 
7f831269c70e: Pull complete 
Digest: sha256:c8776b750869e274b340f8e8eb9a7d8fb2472edd5b25ff5b7d55728bca681322
Status: Downloaded newer image for lorel/docker-stress-ng:latest
docker.io/lorel/docker-stress-ng:latest

# 查看参数信息
root@ubuntu-template:~# docker run -it --rm lorel/docker-stress-ng -help

Memory限制:

0OME(内存溢出),一旦发生OOME,任何进程都可能被杀死,包括docker daemon在内。
内存资源限制无非就两种:一种物理内存,一种交换内存(swap)
-m or --memory=表示设置容器能使用的物理机内存可接受K,M,B
--memory-swap* 表示设置容器使用物理交换内存的限制,注意:先设置ROM这项才有效。
--oom-kill-disable这项参数表示设置容器不想被OOME kill掉,必须与-m一块用
--memory-swappiness表示使用交换分区的倾向性,"0"表示能不用就不用,"100"表示有一点能用也要用。
--oom-score-adj int调整这个参数int范围为(-1000 to 1000)越小越好。

内存大小硬限制

启动两个工作进程,每个工作进程最大允许使用256M,且宿主不限制当前容器最大值

root@ubuntu-template:~# docker run -it --rm --name pop-c1 lorel/docker-stress-ng -vm 2 --vm-bytes 256M

root@ubuntu-template:~# docker stats
# 如截图
image.png

从图中,可以看出来内存已经被限制

3.4 CPU资源限制

默认启动一个容器都是没有限制CPU使用率,可以使用系统CPU的最大值

CPU资源限制参数:

CFS scheduler:完全公平调度器
CPU处理进程根据进程的优先级来调度处理的
普通进程120 非实时进程有效范围优先级为100-139需要调整nice值来调整进程的优先级
nice值为-20到19
实时进程优先级为0-99
--CPU=<value>这个参数设置容器使用CPU的核数
--CPUset-CPUS 这个参数设置容器进程固定运行在那个CPU上

使用--cpu指定两个都工作,并且使用--cpus指定每个CPU使用率只有25%

root@ubuntu-template:~# docker run -it --rm --name pop-c1 --cpus 0.5 lorel/docker-stress-ng stress --cpu 2
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 2 cpu

root@ubuntu-template:~# docker stats
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT     MEM %     NET I/O     BLOCK I/O   PIDS
d77aeeb8229c   pop-c1    49.93%    14.11MiB / 1.946GiB   0.71%     906B / 0B   0B / 0B     3

系统命令top,截图:


image.png

特定指明使用那个cpu来运行

# 使用--cpuset-cpus指定0号CPU来运行
root@ubuntu-template:~# docker run -it --rm --name pop-c1 --cpuset-cpus 0 lorel/docker-stress-ng stress --cpu 2

如截图:


image.png

4. Docker构建镜像

docker构建镜像的方法: commit、dockerfile

  • 使用commit来构建镜像:
    commit是基于原有镜像基础上构建的镜像,使用此方法构建镜像的目的:保存镜像里的一些配置信息和修改的信息。相当于一个镜像的快照。
  • 使用dockerfile来构建镜像:
    dockerfile是快速构建所需(自定义)镜像。

4.1 Dockerfile指令

FROM:指定基础镜像(FROM是必备的指令,并且必须为第一条指令)。

MAINTAINER:维护者信息。

LABEL:标签信息,自定义信息,多标签放一行
    格式:LABEL app.version="版本号" app.host='主机名' description="描述信息"

RUN: 用来执行命令行命令。其基本格式:
    shell格式: RUN  <命令>  ,输入在bash环境中的命令即可,一个dockerfile允许使用RUN不得超过127层,所以,使用一次RUN, 使用 ‘ \ ’ 换行,使用‘ && ’执行下一条命令。一般使用此种格式;
    exec格式: RUN  <"可执行文件", "参数1", "参数2">,此种方式像是函数调用中的格式;

COPY:  复制文件。 其基本格式:
    格式1:COPY <源路径>...<目标路径>
    格式2:COPY [“<源路径1>”,....."<目标路径>"]

ADD: 更高级的复制文件,在COPY的基础上增加了一些功能,如果复制的是压缩包的话,会直接解压,而不需要在使用RUN解压;

CMD:容器启动命令。其基本格式:
    shell格式: CMD <命令>
    exec格式: CMD ["可执行文件", "参数1", "参数2"...]
    参数列表格式: CMD [“参数1”, “参数2”...],在指定了ENTRYPOINT指令后,用CMD指定具体的参数

ENTRYPOINT: 入口点。其基本格式分为exec和shell,
    ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数。ENTRYPOINT在运行中可以替代,不过比CMD繁琐,需要通过docker run 的参数--entrypoint 来指定。当指定了ENTRYPOINT后,CMD的含义就发生了改变,不在是直接运行其命令,而是将CMD的内容作为参数传递给ENTRYPOINT指令。其执行时就变成了:  <ENTRYPOINT> "<CMD>"

ENV: 设置环境变量。(都可以使用这里使用的变量)其基本格式:
    格式1:ENV <key> <value>
    格式2:ENV <key1>=<value1> <key2>=<value>...

ARG: 构建参数。构建参数和ENV的效果一样,都是设置环境变量,所不同的是ARG所构建的环境变量在将来容器运行时是不存在的。其基本格式:
    格式1: ARG <参数名> [=<默认值>]
    格式2: 该默认值可以在构建命令 docker build  中用 --build-arg <参数名>=<值> 来覆盖

VOLUME: 定义匿名卷。 其基本格式:
    格式1: VOLUME ["<路径1>", "<路径2>"...]
    格式2: VOLUME <路径>

EXPOSE:  暴露端口。EXPOSE指令是声明运行时容器所提供的端口,在启动容器时不会在因为这个声明而开启端口。 其基本格式:
    格式1: EXPOSE <端口1> [<端口2>...]

WORKDIR: 指定工作目录。其基本格式:
    格式1: WORKDIR <工作目录路径>

USER: 指定当前用户。USER是帮助你切换到指定用户。 其基本格式:
    格式1: USER <用户名>

HEALTCHECK: 健康检查,判断容器的状态是否正常。 其基本格式:
    格式1: HEALTCHECK [选项] CMD <命令> :设置检查容器健康状况的命令
    格式2: HEALTCHECK NONE: 如果基础镜像有健康检查指令,使用此格式可以屏蔽掉其健康检查指令

4.2 构建NGINX镜像

# 创建目录
root@ubuntu-template:~# mkdir -p /data/docker/dockerfile/nginx
# 下载NGINX源码包
root@ubuntu-template:/data/docker/dockerfile/nginx# wget http://nginx.org/download/nginx-1.14.2.tar.gz
# 编辑dockerfile文件
root@ubuntu-template:/data/docker/dockerfile/nginx# vim dockerfile
FROM centos:7.9.2009

MAINTAINER pop

RUN yum -y install gcc make pcre-devel zlib-devel tar zlib
ADD nginx-1.14.2.tar.gz /usr/local/src/
RUN cd /usr/local/src/nginx-1.15.2 \
    && mkdir /usr/local/nginx \
    && ./configure --prefix=/usr/local/nginx && make && make install \
    && ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/ \
    && nginx
  
RUN rm -rf /usr/local/src/nginx-1.15.2
  
EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

# 构建
root@ubuntu-template:/data/docker/dockerfile/nginx# docker build -t nginx:v1 .
Sending build context to Docker daemon  1.018MB
Step 1/8 : FROM centos:7.9.2009
 ---> 8652b9f0cb4c
Step 2/8 : MAINTAINER pop
 ---> Using cache
 ---> 0ec2687f93bc
Step 3/8 : RUN yum -y install gcc make pcre-devel zlib-devel tar zlib
 ---> Using cache
 ---> 56413decdbc7
Step 4/8 : ADD nginx-1.14.2.tar.gz /usr/local/src/
 ---> Using cache
 ---> 305d5c809f36
Step 5/8 : RUN cd /usr/local/src/nginx-1.14.2     && mkdir /usr/local/nginx     && ./configure --prefix=/usr/local/nginx && make && make install     && ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/     && nginx
 ---> Running in 627c1c39b2a2
checking for OS
...
Removing intermediate container 627c1c39b2a2
 ---> 1f84182a87f7
Step 6/8 : RUN rm -rf /usr/local/src/nginx-1.14.2
 ---> Running in c534e1820d30
Removing intermediate container c534e1820d30
 ---> cf1fc7f28e7f
Step 7/8 : EXPOSE 80
 ---> Running in acf672de9f70
Step 8/8 : CMD ["nginx", "-g", "daemon off;"]
 ---> Running in 879427228d87
Removing intermediate container 879427228d87
 ---> 8cab8e8a5162
Successfully built 8cab8e8a5162
Successfully tagged nginx:v1

# 查看本地镜像
root@ubuntu-template:/data/docker/dockerfile/nginx# docker images
REPOSITORY               TAG        IMAGE ID       CREATED         SIZE
nginx                    v1         8cab8e8a5162   2 minutes ago   437MB
nginx-202109090130       latest     1cec4595e1a1   45 hours ago    133MB
nginx                    latest     822b7ec2aaf2   6 days ago      133MB
hello-world              latest     d1165f221234   6 months ago    13.3kB
centos                   7.9.2009   8652b9f0cb4c   9 months ago    204MB
lorel/docker-stress-ng   latest     1ae56ccafe55   5 years ago     8.1MB

4.2.1 启动NGINX镜像

启动nginx镜像,并映射本地80端口到镜像80端口

root@ubuntu-template:/data/docker/dockerfile/nginx# docker run -dit -p 80:80 --name nginx-202109092246 nginx:v1
d1083609972a481e5cd405189e3595e1875f6416aa668b316083c6745a0935ac
root@ubuntu-template:/data/docker/dockerfile/nginx# docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS         PORTS                               NAMES
d1083609972a   nginx:v1   "nginx -g 'daemon of…"   4 seconds ago   Up 4 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   nginx-202109092246

4.2.2 访问验证

浏览器访问,如截图:


image.png

4.3 构建Tomcat镜像

需要jdk安装包(官网),Tomcat安装包(下载

# 创建目录
root@ubuntu-template:~# mkdir -p /data/docker/dockerfile/tomcat
root@ubuntu-template:/data/docker/dockerfile/tomcat# ls
apache-tomcat-8.5.70.tar.gz  jdk-8u121-linux-x64.tar.gz

# 编辑dockerfile
root@ubuntu-template:/data/docker/dockerfile/tomcat# vim dockerfile
FROM centos:7.9.2009

MAINTAINER pop

ADD jdk-8u121-linux-x64.tar.gz /usr/local/jdk1.8

ADD apache-tomcat-8.5.70.tar.gz /usr/local/tomcat8.5

ENV JAVA_HOME /usr/local/jdk1.8

ENV CATALINA_HOME /usr/local/tomcat8.5

ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin

EXPOSE 8080

CMD ["/usr/local/tomcat8.5/bin/catalina.sh","run"]

# 构建
root@ubuntu-template:/data/docker/dockerfile/tomcat# docker build -t tomcat:v1 .
Sending build context to Docker daemon  193.8MB
Step 1/9 : FROM centos:7.9.2009
 ---> 8652b9f0cb4c
Step 2/9 : MAINTAINER pop
 ---> Using cache
 ---> 0ec2687f93bc
Step 3/9 : ADD jdk-8u121-linux-x64.tar.gz /usr/local/jdk1.8
 ---> 65a32ce7bb8e
Step 4/9 : ADD apache-tomcat-8.5.70.tar.gz /usr/local/tomcat8.5
 ---> df3a574774db
Step 5/9 : ENV JAVA_HOME /usr/local/jdk1.8
 ---> Running in 1a1fe73db6d1
Removing intermediate container 1a1fe73db6d1
 ---> 9d25eeb89525
Step 6/9 : ENV CATALINA_HOME /usr/local/tomcat8.5
 ---> Running in 4fac78e0cb20
Removing intermediate container 4fac78e0cb20
 ---> 732709ee344d
Step 7/9 : ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin
 ---> Running in f93a932685c5
Removing intermediate container f93a932685c5
 ---> cda4aca40ff9
Step 8/9 : EXPOSE 8080
 ---> Running in c4ceffe6bf0e
Removing intermediate container c4ceffe6bf0e
 ---> b36ac2bb9150
Step 9/9 : CMD ["/usr/local/tomcat8.5/bin/catalina.sh","run"]
 ---> Running in bad51a2f0a0f
Removing intermediate container bad51a2f0a0f
 ---> 5b368c99e689
Successfully built 5b368c99e689
Successfully tagged tomcat:v1

# 查看本地镜像库
root@ubuntu-template:/data/docker/dockerfile/tomcat# docker images
REPOSITORY               TAG        IMAGE ID       CREATED          SIZE
tomcat                   v1         5b368c99e689   48 seconds ago   589MB
nginx                    v1         8cab8e8a5162   31 minutes ago   437MB
nginx-202109090130       latest     1cec4595e1a1   46 hours ago     133MB
nginx                    latest     822b7ec2aaf2   6 days ago       133MB
hello-world              latest     d1165f221234   6 months ago     13.3kB
centos                   7.9.2009   8652b9f0cb4c   9 months ago     204MB
lorel/docker-stress-ng   latest     1ae56ccafe55   5 years ago      8.1MB

4.3.1 启动Tomcat镜像

启动Tomcat镜像,并映射本地8080端口到镜像8080端口

root@ubuntu-template:/data/docker/dockerfile/tomcat# docker run -dit -p 8080:8080 --name tomcat-202109092324 tomcat:v1
6051c9b276dabb3725a95626d05153c263bd50ac629a9babcd0058f80eec794d
root@ubuntu-template:/data/docker/dockerfile/tomcat# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS          PORTS                                       NAMES
6051c9b276da   tomcat:v1   "/usr/local/apache-t…"   4 seconds ago    Up 3 seconds    0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   tomcat-202109092324
d1083609972a   nginx:v1    "nginx -g 'daemon of…"   40 minutes ago   Up 40 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp           nginx-202109092246

4.3.2 访问验证

浏览器访问8080端口,如截图:


image.png

4.4 docker 数据的持久化

在docker中实现数据持久化有两种方式:Bind mount和Docker Manager Volume。

Bind mount和Docker Manager Volume的区别:

1. Bind mount数据持久化的方式,如果是挂载本地的一个目录,则容器内对应的目录下的内容会被本地的目录覆盖掉,而Docker Manager Volume这种方式则不会,不管哪种方式的持久化,在容器被销毁后,本地的数据都不会丢失。
2. 使用“-v”选项挂载时,Bind mount明确指定了要挂载docker host本地的某个目录到容器中,而Docker Manager Volume则只指定了要对容器内的某个目录进行挂载,而挂载的是docker host本地的哪个目录,则是由docker来管理的。

数据持久化的特点:

1. Data Volume是目录或文件,不能是没有格式化的磁盘(块设备)。
2. 若要挂载一个文件到容器中,那么该文件必须是已经存在,否则,会被当成一个目录挂载到容器中。
3. 默认挂载到容器内的文件或目录,容器是有读写权限。可以在运行容器时-v指定完挂载目录后面加“:ro” 限制容器的写入权限(:ro来限制)。
4. volume数据可以永久保存,即使使用它的容器已经被销毁。

4.4.1 Bind mount

数据卷容器:–volumes-from方式实现数据持久化

# 基于centos:7.9.2009镜像来做数据卷容器
root@ubuntu-template:/data/docker/dockerfile/tomcat# docker run -tid --name data -v /data/web01/:/dbdata -v /data/web02:/index centos:7.9.2009
16bb7e2cedcb9a7c2402d553cfe21476cf7b0e3e0a3992ddb11bab27de11dcad

# 运行两个nginx容器
root@ubuntu-template:/data/docker/dockerfile/tomcat# docker run -d --name web01 --volumes-from data -P nginx
2a780a74afb35b92de3e90eb00dfb2d96499d9d6ab7f068240d6a90abb1b086d
root@ubuntu-template:/data/docker/dockerfile/tomcat# docker run -d --name web02 --volumes-from data -P nginx
243f674df1c1b5e26f6ee02f20d5af940566954e0bb50c8764bddc439b66c52e

数据卷容器data查看到的mount信息如下:

root@ubuntu-template:/data/docker/dockerfile/tomcat# docker inspect data
...
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/data/web01",
                "Destination": "/dbdata",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Type": "bind",
                "Source": "/data/web02",
                "Destination": "/index",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
...

容器web01查看到的mount信息如下:

root@ubuntu-template:/data/docker/dockerfile/tomcat# docker inspect web01
...
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/data/web01",
                "Destination": "/dbdata",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Type": "bind",
                "Source": "/data/web02",
                "Destination": "/index",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
...

**容器web02查看到的mount信息如下: **

root@ubuntu-template:/data/docker/dockerfile/tomcat# docker inspect web02
...
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/data/web01",
                "Destination": "/dbdata",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Type": "bind",
                "Source": "/data/web02",
                "Destination": "/index",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
...

数据卷容器使用场景
在需要运行的容器都运行完成后,–volumes-from指定的容器,停止或被删除,都不会影响基于nginx镜像运行的容器数据持久化。

  • 多个容器需要实现数据持久化的目录是一致的,可以采用这种方式。
  • 如果不使用这种方式,并且还要对多个目录实现数据持久化,那么每运行个容器都要指定很多"-v"选项来指定目录,并且出现指定错误的几率比较大。

4.4.2 Docker Manager Volume实现数据持久化

root@ubuntu-template:/data/docker/dockerfile/tomcat# docker run -tid -v /data/nginx/html:/usr/share/nginx/html -P --name web03 nginx
e37c2e275b0de5da0a41e2345516770c6fcb7856b0647428b986c50e277b62b4

root@ubuntu-template:/data/docker/dockerfile/tomcat# docker ps
CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS          PORTS                                       NAMES
e37c2e275b0d   nginx             "/docker-entrypoint.…"   4 seconds ago    Up 3 seconds    0.0.0.0:49155->80/tcp, :::49155->80/tcp     web03
243f674df1c1   nginx             "/docker-entrypoint.…"   9 minutes ago    Up 9 minutes    0.0.0.0:49154->80/tcp, :::49154->80/tcp     web02
2a780a74afb3   nginx             "/docker-entrypoint.…"   9 minutes ago    Up 9 minutes    0.0.0.0:49153->80/tcp, :::49153->80/tcp     web01
16bb7e2cedcb   centos:7.9.2009   "/bin/bash"              10 minutes ago   Up 10 minutes                                               data
6051c9b276da   tomcat:v1         "/usr/local/apache-t…"   18 minutes ago   Up 18 minutes   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   tomcat-202109092324
d1083609972a   nginx:v1          "nginx -g 'daemon of…"   59 minutes ago   Up 59 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp           nginx-202109092246

# 查看mount字段信息
root@ubuntu-template:/data/docker/dockerfile/tomcat# docker inspect web03
···
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/data/nginx/html",
                "Destination": "/usr/share/nginx/html",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
···
# 创建一个 index.html
root@ubuntu-template:/data/nginx/html# cat index.html 
http://192.168.20.247:49155/

浏览器访问,如截图:


image.png

再启动一个nginx容器

root@ubuntu-template:/var/lib/docker# docker run -tid -v /data/nginx/html:/usr/share/nginx/html -P --name web04 nginx
5a663588c6080b6551daa2f57b6004a46473c28622033afa47d641499225f26e
root@ubuntu-template:/var/lib/docker# docker ps
CONTAINER ID   IMAGE             COMMAND                  CREATED             STATUS             PORTS                                       NAMES
5a663588c608   nginx             "/docker-entrypoint.…"   8 seconds ago       Up 8 seconds       0.0.0.0:49156->80/tcp, :::49156->80/tcp     web04
e37c2e275b0d   nginx             "/docker-entrypoint.…"   6 minutes ago       Up 6 minutes       0.0.0.0:49155->80/tcp, :::49155->80/tcp     web03
243f674df1c1   nginx             "/docker-entrypoint.…"   15 minutes ago      Up 15 minutes      0.0.0.0:49154->80/tcp, :::49154->80/tcp     web02
2a780a74afb3   nginx             "/docker-entrypoint.…"   16 minutes ago      Up 16 minutes      0.0.0.0:49153->80/tcp, :::49153->80/tcp     web01
16bb7e2cedcb   centos:7.9.2009   "/bin/bash"              17 minutes ago      Up 17 minutes                                                  data
6051c9b276da   tomcat:v1         "/usr/local/apache-t…"   25 minutes ago      Up 25 minutes      0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   tomcat-202109092324
d1083609972a   nginx:v1          "nginx -g 'daemon of…"   About an hour ago   Up About an hour   0.0.0.0:80->80/tcp, :::80->80/tcp           nginx-202109092246

浏览器访问,如截图:


image.png

两个容器,启动的时候映射本地同一个目录,所以访问的结果一样,容器销毁的时候,本地目录不会被删除

4.5 harbor镜像仓库部署

harbor-1的Ubuntu系统机器部署,需要有Docker环境

# 运行此命令下载docker compose的当前稳定版本
root@ubuntu-template:~# curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 对二进制文件应用可执行权限
root@ubuntu-template:~# chmod +x /usr/local/bin/docker-compose

#下载harbor包
root@ubuntu-template:/usr/local/src# wget https://github.com/goharbor/harbor/releases/download/v2.3.2/harbor-offline-installer-v2.3.2.tgz

# 解压包
root@ubuntu-template:/usr/local/src# tar -zxvf harbor-offline-installer-v2.3.2.tgz
harbor/harbor.v2.3.2.tar.gz
harbor/prepare
harbor/LICENSE
harbor/install.sh
harbor/common.sh
harbor/harbor.yml.tmpl

4.5.1 配置harbor.yml文件

root@ubuntu-template:/usr/local/src/harbor# cp harbor.yml.tmpl harbor.yml
root@ubuntu-template:/usr/local/src/harbor# vim harbor.yml
hostname: 192.168.20.148 #服务器IP或域名
http:
  port: 80 
harbor_admin_password: Harbor12345  #Harbor超级管理员密码
database:
  password: root123  #数据库管理员密码

data_volume: /data   #配置harbor数据文件,也就是未来镜像文件的存储位置(这个应该是可以挂载到硬盘,就是下午说得500G硬盘)
把https注释

## https related config
#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

4.5.2 启动安装Harbor

root@ubuntu-template:/usr/local/src/harbor# ./install.sh 

[Step 0]: checking if docker is installed ...

Note: docker version: 20.10.8

[Step 1]: checking docker-compose is installed ...

Note: docker-compose version: 1.24.1

[Step 2]: loading Harbor images ...
...
[Step 5]: starting Harbor ...
Creating network "harbor_harbor" with the default driver
Creating harbor-log ... done
Creating redis         ... done
Creating harbor-portal ... done
Creating registry      ... done
Creating registryctl   ... done
Creating harbor-db     ... done
Creating harbor-core   ... done
Creating harbor-jobservice ... done
Creating nginx             ... done
✔ ----Harbor has been installed and started successfully.----

4.5.3 登录验证

访问:192.168.20.148,登录帐号和密码:admin Harbor12345


创建pop项目

image.png

4.6 客户端配置并推送镜像

4.6.1 配置docker客户端

# 修改/etc/docker/daemon.json
root@ubuntu-template:/var/lib/docker# cat /etc/docker/daemon.json 
{
    "insecure-registries": ["192.168.20.148"],
    "storage-driver": "overlay2"
}
# 重启Docker
root@ubuntu-template:/var/lib/docker# systemctl restart docker
# 验证
root@ubuntu-template:/var/lib/docker# docker info
...
 Experimental: false
 Insecure Registries:
  192.168.20.148
  127.0.0.0/8
 Live Restore Enabled: false

# 登录harbor
root@ubuntu-template:/var/lib/docker# docker login 192.168.20.148
Username: admin
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

4.6.2 推送镜像

# 修改tag
root@ubuntu-template:/var/lib/docker# docker tag tomcat:v1 192.168.20.148/pop/tomcat:v1

# 推送镜像到harbor镜像仓库
root@ubuntu-template:/var/lib/docker# docker push 192.168.20.148/pop/tomcat:v1
The push refers to repository [192.168.20.148/pop/tomcat]
96cf6a0f199b: Pushed 
527274d44a98: Pushed 
174f56854903: Pushed 
v1: digest: sha256:9886ee12ec3cbd8cfd5cb68b2bf1eaf0a089da62fb30eb7cd9b06158fbe05385 size: 954

验证

image.png

4.6.3 拉取镜像

# 先删除本地镜像
root@ubuntu-template:/var/lib/docker# docker images
REPOSITORY                  TAG        IMAGE ID       CREATED        SIZE
<none>                      <none>     fef6345eb70d   2 hours ago    589MB
192.168.20.148/pop/tomcat   v1         6a777a636530   2 hours ago    589MB
tomcat                      v1         6a777a636530   2 hours ago    589MB
<none>                      <none>     a9e432f4e416   2 hours ago    589MB
<none>                      <none>     5b368c99e689   2 hours ago    589MB
nginx                       v1         8cab8e8a5162   2 hours ago    437MB
nginx-202109090130          latest     1cec4595e1a1   2 days ago     133MB
nginx                       latest     822b7ec2aaf2   6 days ago     133MB
hello-world                 latest     d1165f221234   6 months ago   13.3kB
centos                      7.9.2009   8652b9f0cb4c   9 months ago   204MB
lorel/docker-stress-ng      latest     1ae56ccafe55   5 years ago    8.1MB
root@ubuntu-template:/var/lib/docker# docker rmi -f 6a777a636530
Untagged: 192.168.20.148/pop/tomcat:v1
Untagged: 192.168.20.148/pop/tomcat@sha256:9886ee12ec3cbd8cfd5cb68b2bf1eaf0a089da62fb30eb7cd9b06158fbe05385
Untagged: tomcat:v1
Deleted: sha256:6a777a63653041a762ebd83f5fa2c641b5d6a38b0bfef660cf86adbfa1a9671b
root@ubuntu-template:/var/lib/docker# docker images
REPOSITORY               TAG        IMAGE ID       CREATED        SIZE
<none>                   <none>     fef6345eb70d   2 hours ago    589MB
<none>                   <none>     a9e432f4e416   2 hours ago    589MB
<none>                   <none>     5b368c99e689   2 hours ago    589MB
nginx                    v1         8cab8e8a5162   2 hours ago    437MB
nginx-202109090130       latest     1cec4595e1a1   2 days ago     133MB
nginx                    latest     822b7ec2aaf2   6 days ago     133MB
hello-world              latest     d1165f221234   6 months ago   13.3kB
centos                   7.9.2009   8652b9f0cb4c   9 months ago   204MB
lorel/docker-stress-ng   latest     1ae56ccafe55   5 years ago    8.1MB

# 拉取镜像
root@ubuntu-template:/var/lib/docker# docker pull 192.168.20.148/pop/tomcat:v1
v1: Pulling from pop/tomcat
2d473b07cdd5: Already exists 
82d56fd54640: Already exists 
082d4031e64e: Already exists 
Digest: sha256:9886ee12ec3cbd8cfd5cb68b2bf1eaf0a089da62fb30eb7cd9b06158fbe05385
Status: Downloaded newer image for 192.168.20.148/pop/tomcat:v1
192.168.20.148/pop/tomcat:v1
root@ubuntu-template:/var/lib/docker# docker images
REPOSITORY                  TAG        IMAGE ID       CREATED        SIZE
<none>                      <none>     fef6345eb70d   2 hours ago    589MB
192.168.20.148/pop/tomcat   v1         6a777a636530   2 hours ago    589MB
<none>                      <none>     a9e432f4e416   2 hours ago    589MB
<none>                      <none>     5b368c99e689   2 hours ago    589MB
nginx                       v1         8cab8e8a5162   2 hours ago    437MB
nginx-202109090130          latest     1cec4595e1a1   2 days ago     133MB
nginx                       latest     822b7ec2aaf2   6 days ago     133MB
hello-world                 latest     d1165f221234   6 months ago   13.3kB
centos                      7.9.2009   8652b9f0cb4c   9 months ago   204MB
lorel/docker-stress-ng      latest     1ae56ccafe55   5 years ago    8.1MB

4.7 配置harbor高可用

4.7.1 harbor镜像仓库高可用

安装一台harbor-2服务器,分别在两台仓库管理,分别创建对方的信息


image.png

配置复制规则,选择推送模式,触发条件(事件驱动)


image.png
# 修改客户端
root@ubuntu-template:/var/lib/docker# cat /etc/docker/daemon.json 
{
    "insecure-registries": ["192.168.20.148", "192.168.20.201"],
    "storage-driver": "overlay2"
}
root@ubuntu-template:/var/lib/docker# systemctl restart docker
root@ubuntu-template:/var/lib/docker# docker info
...
 Insecure Registries:
  192.168.20.201
  192.168.20.148
  127.0.0.0/8
 Live Restore Enabled: false

注:可以往任意一台harbor上传镜像,可以发现,两个镜像仓库相互同步

4.7.2 配置haproxy

image.png

基于haproxy实现harbor镜像仓库高可用

# 安装haproxy
root@ubuntu-template:~# apt install haproxy
# 编辑haproxy
root@ubuntu-template:~# vim /etc/haproxy/haproxy.cfg 
...
listen harbar_80
        bind 192.168.20.63:80
        mode tcp
        balance source
        server harbor1 192.168.20.148:80 check inter 3s rise 2 fall 3
        server harbor2 192.168.20.201:80 check inter 3s rise 2 fall 3

# 启动haproxy
root@ubuntu-template:~# systemctl restart haproxy

# 验证
root@ubuntu-template:~# ss -natl
State    Recv-Q    Send-Q         Local Address:Port         Peer Address:Port    
LISTEN   0         128            192.168.20.63:80                0.0.0.0:*       
LISTEN   0         128            127.0.0.53%lo:53                0.0.0.0:*       
LISTEN   0         128                  0.0.0.0:22                0.0.0.0:*       
LISTEN   0         128                     [::]:22                   [::]:* 

4.7.1 客户端修改配置

# 添加haproxy ip
root@ubuntu-template:/var/lib/docker# cat /etc/docker/daemon.json 
{
    "insecure-registries": ["192.168.20.148", "192.168.20.201", "192.168.20.63"],
    "storage-driver": "overlay2"
}
root@ubuntu-template:/var/lib/docker# systemctl restart docker
root@ubuntu-template:/var/lib/docker# docker info
...
 Insecure Registries:
  192.168.20.63
  192.168.20.148
  127.0.0.0/8
 Live Restore Enabled: false

# 登录
root@ubuntu-template:/var/lib/docker# docker login 192.168.20.63
Username: admin
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

4.7.2 往ha的ip推送镜像

# 打tag
root@ubuntu-template:/var/lib/docker# docker tag nginx-202109090130 192.168.20.63/pop/nginx-202109090130:v1
root@ubuntu-template:/var/lib/docker# docker tag lorel/docker-stress-ng 192.168.20.63/pop/docker-stress-ng:v1

# 推送镜像
root@ubuntu-template:/var/lib/docker# docker push 192.168.20.63/pop/nginx-202109090130:v1
The push refers to repository [192.168.20.63/pop/nginx-202109090130]
1853e87c604d: Pushed 
d47e4d19ddec: Pushed 
8e58314e4a4f: Pushed 
ed94af62a494: Pushed 
875b5b50454b: Pushed 
63b5f2c0d071: Pushed 
d000633a5681: Pushed 
v1: digest: sha256:fb52dc5216db46fdec40f30f072169444ae21210107d3197f82a5de2799fad34 size: 1777
root@ubuntu-template:/var/lib/docker# docker push 192.168.20.63/pop/docker-stress-ng:v1
The push refers to repository [192.168.20.63/pop/docker-stress-ng]
5f70bf18a086: Pushed 
ea580b0285fe: Pushed 
6102f0d2ad33: Pushed 
v1: digest: sha256:5768a5d8e196be8c8fabbda04d937aabe1407f397b2f12e1fea2573e4b9d9bef size: 1563

4.7.3 验证

harbor-1仓库,截图:


harbor-2仓库,截图:


image.png

通过后台详情分析,客户端传到了harbor-2仓库上,然后harbor-2仓库触发事件往harbor-1仓库同步上传的两个镜像,如截图:


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容