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
# 如截图
从图中,可以看出来内存已经被限制
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,截图:
特定指明使用那个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
如截图:
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 访问验证
浏览器访问,如截图:
4.3 构建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端口,如截图:
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/
浏览器访问,如截图:
再启动一个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
浏览器访问,如截图:
两个容器,启动的时候映射本地同一个目录,所以访问的结果一样,容器销毁的时候,本地目录不会被删除
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项目
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
验证
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服务器,分别在两台仓库管理,分别创建对方的信息
配置复制规则,选择推送模式,触发条件(事件驱动)
# 修改客户端
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
基于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仓库,截图:
通过后台详情分析,客户端传到了harbor-2仓库上,然后harbor-2仓库触发事件往harbor-1仓库同步上传的两个镜像,如截图: