# Docker

www.docker.com

hub.docker.com

虚拟机缺点:

1. 资源占有多

2. 冗余步骤多

3. 启动慢

image-20230328205458587

容器化技术:不是完整的操作系统,只保留了最核心的部分。直接运行在操作系统之上。容器之间相互隔离

image-20230328203952292

传统虚拟机:虚拟出一套硬件,运行一套完整的操作系统,再运行软件

容器内的应用直接运行在宿主机的内核,是没有自己内核的,也没有虚拟硬件,所以轻便。每个容器相互隔离,都有属于自己的文件系统

更高效的资源应用

更见的系统运维

更便捷的升级和扩缩容

应用更快速的交付和部署

# docker 安装

image-20230328205612777

镜像 :image 类似于模板,可以通过模板创建容器服务。镜像 run 之后就是一个容器,用于提供服务。通过这个镜像可以创建多个容器,项目运行就是在容器中

容器 :container docker 利用容器,独立运行一个或者一组应用,通过镜像来创建 ,可以启动,删除,停止等。可以把容器理解为一个简易的 linux 系统

仓库 :repository 存放镜像的地方。分为共有和私有仓库,比如 docker hub。国内需要配置镜像加速,利用阿里云容器服务器或者其他

环境:centos7 + 华为云 + xshell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@hecs-346515 ~]# uname -r
3.10.0-1160.53.1.el7.x86_64

[root@hecs-346515 ~]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

1. 卸载旧版本

1
2
3
4
5
6
7
8
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

2. 安装基本环境

1
sudo yum install -y yum-utils

3. 设置镜像仓库

1
2
3
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
1
2
更新软件包索引
yum makecache fast

4. 安装 docker 相关内容

1
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

5. 启动 docker

1
2
systemctl start docker
docker version

6. 测试 docker 安装是否成功

1
docker run hello-world

7. 查看 hello-world 镜像

1
docker images

8. 卸载 docker

1
2
3
4
5
卸载依赖
sudo yum remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
删除资源,也就是docker的默认工作路径
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

# 内核参数调优

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
内核参数修改:br_netfilter模块用于将桥接流量转发至iptables链,br_netfilter内核参数需要开启转发。
[root@xianchaomaster1 ~]# modprobe br_netfilter
[root@xianchaomaster1 ~]# cat > /etc/sysctl.d/docker.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF


#使参数生效
[root@xianchaomaster1 ~]# sysctl -p /etc/sysctl.d/docker.conf

[root@hecs-346515 ngsql]# lsmod | grep br_
br_netfilter 22256 0
bridge 151336 2 br_netfilter,ebtable_broute

重启后模块失效,下面是开机自动加载模块的脚本
在/etc/新建rc.sysinit 文件
cat /etc/rc.sysinit
#!/bin/bash
for file in /etc/sysconfig/modules/*.modules ; do
[ -x $file ] && $file
done

在/etc/sysconfig/modules/目录下新建文件如下
cat /etc/sysconfig/modules/br_netfilter.modules
modprobe br_netfilter

增加权限
[root@xianchaomaster1 ~]# chmod 755 /etc/sysconfig/modules/br_netfilter.modules

重启机器模块也会自动加载
[root@localhost ~]# lsmod |grep br_netfilter
br_netfilter 22209 0
bridge 136173 1 br_netfilter

注:
Docker 安装后出现:WARNING: bridge-nf-call-iptables is disabled 的解决办法:
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

net.ipv4.ip_forward = 1:
将Linux系统作为路由或者VPN服务就必须要开启IP转发功能。当linux主机有多个网卡时一个网卡收到的信息是否能够传递给其他的网卡 ,如果设置成1 的话 可以进行数据包转发,可以实现VxLAN 等功能。不开启会导致docker部署应用无法访问。

#重启docker
[root@xianchaomaster1 ~]# systemctl restart docker

# 镜像加速

cr.console.aliyun.com

1
2
3
4
5
6
7
8
9
10
您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://fn5y0qpk.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

# docker run 之后发生了什么

1. 本机寻找镜像

2.1 本机有镜像,使用镜像运行

2.2 去 dockerhub 上下载

3.1 dockerhub 找不到镜像 - 返回错误

3.2dockerhub 找到镜像,下载到本地

4. 运行

image-20230329195956959

docker 是一个 cs 结构的系统,docker 的守护进程运行在主机上。通过 socket 从客户端访问

docker server 接收到 client 指定,就会执行这个命令

image-20230329200521395

docker 有着比虚拟机更少的抽象层

image-20230329200736029

docker 用的是宿主机的内核,vm 需要 guest os

docker 不需要重新加载操作系统内核,避免引导。

# docker 命令

1
2
3
docker version/info    # 版本信息,系统信息
docker --help # 帮助命令

# 镜像命令

docker images # 查看所有镜像

1
2
3
4
5
6
7
8
9
10
11
12
[root@hecs-346515 ~]# docker images 
REPOSITORY TAG IMAGE ID CREATED SIZE
loadbalancejsp_lbsnode1 latest 8d19a7525948 3 months ago 240MB
loadbalancejsp_lbsnode2 latest 8d19a7525948 3 months ago 240MB
tomcat 8-jre8 f0e282263192 3 months ago 240MB

仓库源 标签 镜像ID 创建时间 镜像大小


-a 显示全部镜像

-q 只显示镜像ID

docker search # 搜索镜像

1
2
3
4
5
6
7
[root@hecs-346515 ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 13988 [OK]
mariadb MariaDB Server is a high performing open sou… 5333 [OK]
percona Percona Server is a fork of the MySQL relati… 602 [OK]

docker search mysql --filter=STARS=9000 STARS>9000

docker pull #下载镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
[root@hecs-346515 ~]# docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete # 分层下载
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
688ba7d5c01a: Pull complete
00e060b6d11d: Pull complete
1c04857f594f: Pull complete
4d7cfa90e6ea: Pull complete
e0431212d27d: Pull complete
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实地址

==
docker pull docker.io/library/mysql:latest

分层可以实现层的共用

[root@hecs-346515 ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Already exists
93619dbc5b36: Already exists
99da31dd6142: Already exists
626033c43d70: Already exists
37d5d7efb64e: Already exists
ac563158d721: Already exists
d2ba16033dad: Already exists
0ceb82207cd7: Pull complete
37f2405cae96: Pull complete
e2482e017e53: Pull complete
70deed891d42: Pull complete
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

docker rmi # 删除镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@hecs-346515 ~]# docker rmi c20
Untagged: mysql:5.7
Untagged: mysql@sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Deleted: sha256:c20987f18b130f9d144c9828df630417e2a9523148930dc3963e9d0dab302a76
Deleted: sha256:6567396b065ee734fb2dbb80c8923324a778426dfd01969f091f1ab2d52c7989
Deleted: sha256:0910f12649d514b471f1583a16f672ab67e3d29d9833a15dc2df50dd5536e40f
Deleted: sha256:6682af2fb40555c448b84711c7302d0f86fc716bbe9c7dc7dbd739ef9d757150
Deleted: sha256:5c062c3ac20f576d24454e74781511a5f96739f289edaadf2de934d06e910b92

[root@hecs-346515 ~]# docker rmi c20 321 # 删除多个镜像

#docker删除全部容器
[root@hecs-346515 ~]# docker rmi -f $(docker images -qa)

# 容器命令

1
[root@hecs-346515 ~]# docker pull centos

新建容器并启动

docker run

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 参数说明
--name="Name" 容器名字,用于区分容器
-d 以后台运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口
-p 容器端口
容器端口
-P 随机指定端口


[root@hecs-346515 ~]# docker run -it centos /bin/bash # 启动并进入容器
[root@3505a169c989 /]# exit


列出所有运行的容器

docker ps -a

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@hecs-346515 ~]# docker ps -a 
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3505a169c989 centos "/bin/bash" 2 minutes ago Exited (0) About a minute ago lucid_hypatia
efe24d96f682 hello-world "/hello" 23 hours ago Exited (0) 23 hours ago goofy_lichterman
85c7b4c3d350 nginx:1.17 "nginx -g 'daemon of…" 3 months ago Exited (1) 3 months ago loadbalancejsp_nginx_1



-a 列出历史容器和当前运行的容器
-n=? 显示最近创建的容器个数
-q 只显示容器编号

docker ps -qa

退出容器

1
2
exit  停止并退出
ctrl + q + p 容器不停止退出

删除容器

1
2
3
docker rm id
docker rm -f $(docker ps -aq) # 删除所有容器
docker ps -aq | xargs docker rm # 删除所有容器

启动和停止容器

1
2
3
4
docker start id
docker restart id
docker stop id
docker kill id

后台启动容器

1
2
3
docker run -d centos

启动完之后因为没有前台进程,容器发现没有应用,自动停止

查看日志

1
2
3
4
docker logs

[root@hecs-346515 ~]# docker logs -f -t 741
[root@hecs-346515 ~]# docker logs -f -t --tail 10 741

查看容器中的进程信息

1
2
3
4
5
[root@hecs-346515 ~]# docker top 741
UID PID PPID C STIME TTY TIME CMD
root 8024 8006 0 14:05 ? 00:00:00 nginx: master process nginx -g daemon off;
101 8075 8024 0 14:05 ? 00:00:00 nginx: worker process

查看镜像元数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@hecs-346515 ~]# docker inspect 741
[
{
"Id": "741038301edd946e2f2e193803d8e29aa31897212a310730c85f8b8194dbf45f",
"Created": "2023-03-30T06:05:28.540089191Z",
"Path": "/docker-entrypoint.sh",
"Args": [
"nginx",
"-g",
"daemon off;"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 8024,
"ExitCode": 0,
"Error": "",
"StartedAt": "2023-03-30T06:05:28.79217804Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85",

进入当前运行容器

1
2
3
4
5
6
7
8
9
10
[root@hecs-346515 ~]# docker exec -it 741 /bin/bash
root@741038301edd:/#
# 进入容器后开启新终端
-i:以交互模式运行容器
-t:为容器重新分配一个伪输入终端

[root@hecs-346515 ~]# docker attach 8cf
[root@8cf0c194eae8 /]#
# 进入容器正在执行的终端,不会启动新的进程

容器内拷贝文件到主机上

1
2
3
4
5
docker cp id:/root/ /home
docker cp id:/容器目录 /本机目录
docker 容器内命令

-v 卷可以实现自动同步

# 使用 docker

# 安装 nginx

1
2
3
4
5
6
7
docker search nginx
docker pull nginx
docker run -d --name=nginx01 -p 8991:80 nginx
curl 121.37.191.89:8991


whereis nginx 找到nginx

# 安装 tomcat

1
2
3
4
docker run -it --rm  tomcat /bin/bash   # rm用完就删,一般用于测试

docker run -d -p 8877:8080 --name=tomcat01 tomcat
docker exec -it tomcat01 /bin/bash

# 安装 es+kibana

1
2
3
4
5
6
docker run -d --name es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch


docker stats # 查看cpu状态

docker run -d --name es2 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch

image-20230330195235840

# 可视化

portainer

Rancher

portainer docker 图形化界面管理工具

1
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

image-20230331202120533

选择 local

# 联合文件系统

UnionFS

UnionFS (联合文件系统):Union 文件系统 (UnionFS) 是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来壬层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下 (unite several directories into a single virtualfilesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性∶一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

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

roots (root fle system),在 boots 之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, letc 等标准目录和文件。rootfs 就是各种不同的操作系统发行版,比如 Ubuntu,centos 等等。

image-20230331203141142

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

# 分层原理

1
2
3
4
5
6
7
8
9
10
11
12
13
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:6515074984c6f8bb1b8a9962c8fb5f310fc85e70b04c88442a3939c026dbfad3",
"sha256:4f169ae5a253d68d25f3f5fdd0deb31af20096bcffdec1fdda5cf8810d507d1f",
"sha256:edae32ac2ac2a7f24eebb4b62ad2fa0a9434f47f4b56a3739106e1da4cb1aa6a",
"sha256:f05805c5815d0394d09d3b64e3a58727f8d647f2c5a4d1fbb5e40ed5f8424e84",
"sha256:460c946f1b353b51ebb7548ea8f8127118d9bdc7be5f8f2c3c4e73fc9968d705",
"sha256:3241d073343d5c09cb9854032919de8fe88433c2867fac073a61ed5669e8cae8",
"sha256:f5c79923df4c5c22157139e199d0143e8af29ac0f11f73fd4a56759c1f080c05",
"sha256:a5d2135a0fbf3b167b687e40028e54e271588a2ece546bcdcf8da5751c4ba828"
]
},

image-20230331203518152

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含 3 个文件,而镜像包含了来自两个镜像层的 6 个文件。

image-20230331203612551

下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有 6 个文件,这是因为最上层中的文件 7 是文件 5 的一个更新版本。

image-20230331203723498

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。Docker 通过存储引擎 (新版本采用快照机制) 的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。

Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顾名思义,每种存储引擎都基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。

Docker 在 Windows 上仅支持 windowsfilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和 CoW [1]。下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。

image-20230331203816012

Docker 镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!

这一层就是我们通常说的容器层,容器之下的都叫镜像层!

# commit

1
2
3
4
5
6
7
8
9
docker commit # 提交容器称为新的副本
docker commit -m="descriptor" -a="author" id name:tag


docker run -it -p 8898:8080 tomcat
docker exec -it ffcc /bin/bash

docker commit -a="shabi" -m="webapp/" ffccc tomcatshabi:1.22

image-20230331205200662

通过 commit 提交后,在原始 tomcat 上面又增加了一层,所以文件会稍微变大一些

# 容器数据卷

如果数据都在容器中,容器删除数据就会丢失,不能持久化

容器之间需要一个数据共享技术。docker 容器中产生的数据同步到本地,防止数据丢失

其实就是目录挂载。将我们容器内的目录,挂载到虚拟机上

1
2
3
4
5
1.数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,这些数据会被拷贝到新初始化的数据卷中
2.数据卷可以在容器之间共享和重用
3.可以对数据卷里的内容直接进行修改
4.数据卷的变化不会影像镜像的更新
5.卷会一直存在,即使挂载数据卷的容器已经被删除

image-20230331210323928

容器间数据也是可以共享的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker run -it -v 主机目录:容器目录 -p 8767:8080

docker run -it -v /home/testing:/home -p 8767:8080 tomcat /bin/bash

"Mounts": [
{
"Type": "bind",
"Source": "/home/testing", //主机地址
"Destination": "/home", //docker内地址
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],

同步不受容器停止影响

1
docker run -it -v  /usr/local/nginx/conf/nginx.conf:/usr/local/nginx/conf/nginx.conf -p 80:80 nginx /bin/bash

以后只需要本地修改即可,容器自动同步

安装 mysql,并挂载数据卷

1
2
3
docker run -d -v /home/mysql_conf:/etc/mysql/conf.d/ -v /home/mysql_data:/var/lib/mysql  -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 --name=mysql002  mysql

mysql -uroot -p123456 -h121.37.191.89 -p3307

删除容器也不会丢失数据,但会占用两倍内存

这就实现了容器持久化功能

具名挂载、匿名挂载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
-v 容器内路径 
docker run -d -P --name nginx01 -v /etc/nginx nginx

# 查看卷的情况
[root@hecs-346515 ~]# docker volume ls
DRIVER VOLUME NAME
local 879266c77b0964e9bca1b3a1f6cf4d6089eb18d9b9c9e549d0c41357f6dc5a35
local dirtycow-vdso
local ee9d314e1c5f3010b8d64108293246853c90d3d820c20332c338ed9bdd3f168b
local f3924de885d11729faa0c5869488fd0aefca9e3f6bcaddc36c9ce95f4e891603
local fd3d617a1c288349a4717e3a73e63dbbcf900c51f2d69fe30f9fa726ac82a08d
没有名称的就是匿名挂载

# 具名挂载
docker run -d -P --name nginx01 -v juming_nginx:/etc/nginx nginx

[root@hecs-346515 ~]# docker volume inspect juming_nginx
[
{
"CreatedAt": "2023-04-02T21:42:24+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming_nginx/_data",
"Name": "juming_nginx",
"Options": null,
"Scope": "local"
}
]
# 所有docker内的卷,没有指定目录的情况下都在/var/lib/docker/volumes/

我们通过具名挂载可以方便的找到一个卷

如何区分指定路径和匿名挂载

1
2
3
-v 容器内路径   匿名
-v 卷名:容器内路径 具名
-v /usr/local:/etc/nginx/ 路径
1
2
3
4
5
6
-v 容器内路径:rw/ro 改变读写权限
docker run -d -P --name nginx01 -v juming_nginx:/etc/nginx:ro nginx
readonly readwrite

一旦设置了容器容器权限,对我们挂载出来的内容有限定
默认是rw,ro说明只能通过宿主机操作,容器内部无法操作

# Dockerfile 挂载

dockerfile 就是用来构建 docker 镜像的文件

镜像是一层层的,命令也是一层层的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
FROM centos

VOLUME ["voume01","volume02"]

CMD echo "---------------"
CMD /bin/bash

[root@hecs-346515 docker-test]# docker build -f ./dockerfile1 -t hahaha .
[+] Building 0.1s (5/5) FINISHED
=> [internal] load build definition from dockerfile1 0.1s
=> => transferring dockerfile: 123B 0.0s
=> [internal] load .dockerignore 0.1s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/centos:latest 0.0s
=> [1/1] FROM docker.io/library/centos 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:29755edf1ce7d5c71c2c7cbbf8b0bd54f02ce72a4ebcaccdfd857aa0dcb99e 0.0s
=> => naming to docker.io/library/hahaha 0.0s

# 这里的每个命令都是镜像的一层

[root@hecs-346515 docker-test]# docker run -it hahaha /bin/bash
[root@74ee4cc3e927 /]# ls
bin etc lib lost+found mnt proc run srv tmp var voume01
dev home lib64 media opt root sbin sys usr volume02


"Mounts": [
{
"Type": "volume",
"Name": "eb0e7a226b19aa2e8811eabaf339cf3cee05f3fec433af62212607e0010bda2e",
"Source": "/var/lib/docker/volumes/eb0e7a226b19aa2e8811eabaf339cf3cee05f3fec433af62212607e0010bda2e/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "8b52d9050ada34758bacfe403a63a5b6a06e0c96cadb86830fa16aa9533a6fc8",
"Source": "/var/lib/docker/volumes/8b52d9050ada34758bacfe403a63a5b6a06e0c96cadb86830fa16aa9533a6fc8/_data",
"Destination": "voume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],

构建镜像的时候没有挂载均,需要手动 - v 挂载

# 数据卷容器

实现容器之间同步数据

image-20230402220831342

1
2
3
4
5
docker run -it --name docker01 hahaha 

docker run -it --name docker02 --volumes-from docker01 hahaha


父容器删除,其他容器的文件依然在

所有父容器和子容器都挂载在宿主机的文件中,如果宿主机挂载目录没了,三个容器都没了

数据卷的声明周期一直到没有容器使用位置

1
2
3
4
rm -rf /etc/yum.repos.d/*
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo
yum install wget -y
yum install nginx -y

# docker 数据卷备份与还原

1
2
3
4
5
6
7
8
9
10
docker run  --volumes-from [container name] -v $(pwd):/backup centos tar czvf /backup/backup.tar [container data volume]

例子:备份datavolume6 到/backup
docker run --volumes-from data-volume2 -v /root/backup:/backup --name datavolume-copy centos tar zcvf /backup/data-volume2.tar.gz /datavolume6

还原备份
docker run --volumes-from [container name] -v $(pwd):/backup centos tar xzvf /backup/backup.tar.gz [container data volume]

例:
docker run --volumes-from data-volume2 -v /root/backup/:/backup centos tar zxvf /backup/data-volume2.tar.gz -C /datavolume6

# Dockerfile

dockerfile 是用来构建 dockerfile 的镜像文件,命令参数脚本

一个基本 dockerfile

1
2
3
4
5
6
7
8
9
10
FROM centos
MAINTAINER xianchao
RUN rm -rf /etc/yum.repos.d/*
COPY Centos-vault-8.5.2111.repo /etc/yum.repos.d/
RUN yum install wget -y
RUN yum install nginx -y
COPY index.html /usr/share/nginx/html/
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]
# nginx时钟前台运行,避免容器自动退出

1. 编写 dockerfile

2.docker build 构建成为镜像

3.docker run 运行镜像

4.docker push 发布镜像

image-20230402224507380

每个关键字都是大写字母

执行从上到下

#表示注释

每一个指令都会创建一个新的镜像层,并提交

发布项目都要发布 dockerfile

dockerfile 构建文件,定义了一切的步骤,源代码

dockerimages 通过 dockerfile 生成的镜像,最终发布和运行的版本

docker 容器:容器就是镜像运行起来提供服务

# dockerfile 指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
FROM     	# 基础镜像

MAINTAINER # 维护者信息

RUN # 镜像构建的时候需要运行的命令
包含两种模式
1、Shell
RUN <command> (shell模式,这个是最常用的,需要记住)
RUN echo hello
2、exec模式
RUN [“executable”,“param1”,“param2”](exec模式)
RUN [“/bin/bash”,”-c”,”echo hello”]
等价于/bin/bash -c echo hello
RUN yum install wget -y等价于
RUN [“/bin/bash”,”-c”,”yum install wget -y”]

WORKDIR # 镜像工作目录
进容器之后的目录
docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

volume # 设置容器卷,挂载到那个位置
1、避免重要的数据,因容器重启而丢失,这是非常致命的。
2、避免容器不断变大。
VOLUME ["/data"]
物理机随机生成一个目录映射到容器中/data
在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点

EXPOSE # 指定暴露端口
1、帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
2、在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
3、可以是一个或者多个端口,也可以指定多个EXPOSE

CMD # 指定容器启动的时候要运行的命令,只有最后一个会生效,可被替代
1、CMD 在docker run 时运行。
2、RUN 是在 docker build构建镜像时运行的

ENTRYPOINT # 指定容器启动的时候要运行的命令,可以追加命令
类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。
但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 entrypoint指令指定的程序。
优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。
可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参
不传参运行会 运行nginx -c /etc/nginx/nginx.conf
参参运行 docker run --name nginx nginx:test /etc/nginx/new.conf 会运行nginx -c /etc/nginx/new.conf

ONBUILD # 当构建一个被继承Dockerfile,这个时候就会运行ONBUILD指令
用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。
ONBUILD COPY index.html /usr/share/nginx/html/
docker build -t="onbuild-nginx:v1" . --load
只有当某一个dockerfile把onbuild-nginx作为基础镜像时ONBUILD才会执行


CPOY # 将文件拷贝到镜像中
COPY [--chown=<user>:<group>] <源路径1>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
COPY hom* /mydir/
COPY hom?.txt /mydir/

ADD # 步骤:如果搭建tomcat,压缩包就需要add
ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
ADD 指令和 COPY 的使用格式一致

ENV # 构建的时候设置环境变量
ENV <key> <value>
ENV <key>=<value>...
ENV NODE_VERSION 6.6.6
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"

USER
用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。
格式:
USER <用户名>[:<用户组>]


dockerhub 中大部分镜像都是从 FROM scratch 来的,然后配置需要的软件和配置来进行构建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 创建一个centos
FROM centos:7
MAINTAINER shabi<21111@qq.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum install epel* -y
RUN yum install -y vim
RUN yum install -y net-tools

EXPOSE 80

CMD echo $MYPATH
CMD /bin/bash

# 构建镜像
docker build -f dockerfile -t centoshaha:0.5 .

[root@hecs-346515 dockerfile]# docker build -f dockerfile -t centoshaha:0.5 .
[+] Building 199.4s (5/7)
[+] Building 200.1s (5/7)
[+] Building 200.6s (5/7)
[+] Building 200.9s (5/7)
[+] Building 228.0s (8/8) FINISHED
=> [internal] load build definition from dockerfile 0.0s
=> => transferring dockerfile: 219B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/centos:7 16.0s
=> [1/4] FROM docker.io/library/centos:7@sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426a630e0 50.2s
=> => resolve docker.io/library/centos:7@sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426a630e09 0.0s
=> => sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426a630e0987 1.20kB / 1.20kB 0.0s
=> => sha256:dead07b4d8ed7e29e98de0f4504d87e8880d4347859d839686a31da35a3b532f 529B / 529B 0.0s
=> => sha256:eeb6ee3f44bd0b5103bb561b4c16bcb82328cfe5809ab675bb17ab3a16c517c9 2.75kB / 2.75kB 0.0s
=> => sha256:2d473b07cdd5f0912cd6f1a703352c82b512407db6b05b43f2553732b55df3bc 76.10MB / 76.10MB 46.3s
=> => extracting sha256:2d473b07cdd5f0912cd6f1a703352c82b512407db6b05b43f2553732b55df3bc 3.6s
=> [2/4] WORKDIR /usr/local 0.0s
=> [3/4] RUN yum install -y vim 156.1s
=> [4/4] RUN yum install -y net-tools 2.9s
=> exporting to image 2.7s
=> => exporting layers 2.7s
=> => writing image sha256:1c525b4438024495ebbbf1f19a3e3ea730826dfcab5cb8337ea0fa0a0de853ad 0.0s
=> => naming to docker.io/library/centoshaha:0.5

image-20230404110343127

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@hecs-346515 dockerfile]# docker history 1c5
IMAGE CREATED CREATED BY SIZE COMMENT
1c525b443802 4 minutes ago CMD ["/bin/sh" "-c" "/bin/bash"] 0B buildkit.dockerfile.v0
<missing> 4 minutes ago CMD ["/bin/sh" "-c" "echo $MYPATH"] 0B buildkit.dockerfile.v0
<missing> 4 minutes ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0
<missing> 4 minutes ago RUN /bin/sh -c yum install -y net-tools # bu… 176MB buildkit.dockerfile.v0
<missing> 4 minutes ago RUN /bin/sh -c yum install -y vim # buildkit 259MB buildkit.dockerfile.v0
<missing> 7 minutes ago WORKDIR /usr/local 0B buildkit.dockerfile.v0
<missing> 7 minutes ago ENV MYPATH=/usr/local 0B buildkit.dockerfile.v0
<missing> 7 minutes ago MAINTAINER shabi<21111@qq.com> 0B buildkit.dockerfile.v0
<missing> 18 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 18 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 18 months ago /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4… 204MB

[root@hecs-346515 dockerfile]# docker history 5d0
IMAGE CREATED CREATED BY SIZE COMMENT
5d0da3dc9764 18 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 18 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 18 months ago /bin/sh -c #(nop) ADD file:805cb5e15fb6e0bb0… 231MB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
FROM centos:7
CMD ["ls","-a"]


[root@hecs-346515 dockerfile]# docker build -f cmd -t cmd:0.5 .
[+] Building 0.3s (5/5) FINISHED
=> [internal] load build definition from cmd 0.0s
=> => transferring dockerfile: 60B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/centos:7 0.2s
=> CACHED [1/1] FROM docker.io/library/centos:7@sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:3ced42c5b7de1bbe7659ef7bd2349ebf83eb13eab6d1afe69f029ef65a88f9ab 0.0s
=> => naming to docker.io/library/cmd:0.5 0.0s
[root@hecs-346515 dockerfile]# docker run -it cmd:0.5
. .dockerenv bin etc lib media opt root sbin sys usr
.. anaconda-post.log dev home lib64 mnt proc run srv tmp var

CMD # 指定容器启动的时候要运行的命令,只有最后一个会生效,可被替代

docker run 3e -l # -l不是命令所以报错

docker run 3e ls -al ls -al 替换了ls -a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
vim entry
FROM centos:7
ENTRYPOINT ["ls","-a"]

[root@hecs-346515 dockerfile]# docker run entry:0.5
.
..
.dockerenv
anaconda-post.log
bin
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var


[root@hecs-346515 dockerfile]# docker run entry:0.5 -l
total 64
drwxr-xr-x 1 root root 4096 Apr 4 03:18 .
drwxr-xr-x 1 root root 4096 Apr 4 03:18 ..
-rwxr-xr-x 1 root root 0 Apr 4 03:18 .dockerenv
-rw-r--r-- 1 root root 12114 Nov 13 2020 anaconda-post.log
lrwxrwxrwx 1 root root 7 Nov 13 2020 bin -> usr/bin
drwxr-xr-x 5 root root 340 Apr 4 03:18 dev
drwxr-xr-x 1 root root 4096 Apr 4 03:18 etc
drwxr-xr-x 2 root root 4096 Apr 11 2018 home
lrwxrwxrwx 1 root root 7 Nov 13 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 13 2020 lib64 -> usr/lib64
drwxr-xr-x 2 root root 4096 Apr 11 2018 media
drwxr-xr-x 2 root root 4096 Apr 11 2018 mnt
drwxr-xr-x 2 root root 4096 Apr 11 2018 opt
dr-xr-xr-x 134 root root 0 Apr 4 03:18 proc
dr-xr-x--- 2 root root 4096 Nov 13 2020 root
drwxr-xr-x 11 root root 4096 Nov 13 2020 run
lrwxrwxrwx 1 root root 8 Nov 13 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Apr 11 2018 srv
dr-xr-xr-x 13 root root 0 Apr 4 03:18 sys
drwxrwxrwt 7 root root 4096 Nov 13 2020 tmp
drwxr-xr-x 13 root root 4096 Nov 13 2020 usr
drwxr-xr-x 18 root root 4096 Nov 13 2020 var

ENTRYPOINT # 指定容器启动的时候要运行的命令,可以追加命令

entrypoint 是追加,CMD 是覆盖

# 制作 nginx 镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FROM centos
MAINTAINER xianchao
RUN rm -rf /etc/yum.repos.d/*
COPY Centos-vault-8.5.2111.repo /etc/yum.repos.d/
RUN yum install wget -y
RUN yum install nginx -y
COPY index.html /usr/share/nginx/html/
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]


# 构建
docker build -t="shinya/shabi:v1" .

docker run -d -p 80 --name html2 shinya/shabi:v1

# 制作 tomcat 镜像

1、准备安装包

2、Dockerfile 是官方命名,构建时会自动寻找,就不需要 - f 指定了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
FROM centos:7
MAINTAINER shshshs<110@110.com>

COPY readme.txt /usr/local/readme.txt

ADD apache-tomcat-10.1.7.tar.gz /usr/local/
ADD jdk-20_linux-x64_bin.tar.gz /usr/local/

RUN yum install -y vim

ENV MYPATH /usr/local/
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk-20
ENV CLASS_PATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-10.1.7/
ENV CATALINA_BASE /usr/local/apache-tomcat-10.1.7/
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-10.1.7/bin/startup.sh && tail -F /usr/local/apache-tomcat-10.1.7/logs/catalina.out

3. 构建镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[root@hecs-346515 dockerfile]# docker build -t ddcat:1.0 .
[+] Building 61.4s (11/11) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 690B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/centos:7 15.3s
=> CACHED [1/6] FROM docker.io/library/centos:7@sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426 0.0s
=> [internal] load build context 2.3s
=> => transferring context: 203.75MB 2.3s
=> [2/6] COPY readme.txt /usr/local/readme.txt 0.5s
=> [3/6] ADD apache-tomcat-10.1.7.tar.gz /usr/local/ 0.4s
=> [4/6] ADD jdk-20_linux-x64_bin.tar.gz /usr/local/ 4.6s
=> [5/6] RUN yum install -y vim 34.4s
=> [6/6] WORKDIR /usr/local/ 0.0s
=> exporting to image 3.8s
=> => exporting layers 3.8s
=> => writing image sha256:620e725ff485b1cae36720ea191ba0692cc5f2a857e516528e5b65653e752913 0.0s
=> => naming to docker.io/library/ddcat:1.0 0.0s


4.启动镜像
[root@hecs-346515 dockerfile]# docker run -d -p 8877:8080 --name=catcatcat -v /root/dockerfile/build/tomcat/test:/usr/local/apache-tomcat-10.1.7/webapps/test -v /root/dockerfile/build/tomcat/logs:/usr/local/apache-tomcat-10.1.7/logs ddcat:1.1
4357a9cda1d960125ac7d4ab052902ec04848c0dbbce3beb26bccf4eaff84fa4

5、访问测试

image-20230404124622232

6. 发布项目

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
</web-app>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<%-- <meta charset="UTF-8">--%>
<%-- <meta http-equiv="X-UA-Compatible" content="IE=edge">--%>
<%-- <meta name="viewport" content="width=device-width, initial-scale=1.0">--%>
<title>Title</title>
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/bootstrap.min.css.map">
<script type="text/javascript" src="js/jquery-3.5.1.js"></script>
<script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript">
$(function () {
$.ajax({
url: "${pageContext.request.contextPath}/type?method=findAllType",
type: "GET",
dataType: "json",
success: function (data) {
for (var i in data) {
var a = "<li><a href='${pageContext.request.contextPath}/product?method=show&tid=" + data[i].tid + "'>" + data[i].tname + "</a></li>";
$("#goodsType").append(a);
}
},
error: function () {
alert("失败");
}
})
})
</script>
</head>
<body>

<div>
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">myShop商城</a>
</div>

<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="${pageContext.request.contextPath}/Login.jsp">登录<span class="sr-only">(current)</span></a>
</li>
<li><a href="${pageContext.request.contextPath}/Register.jsp">注册</a></li>
<li><a href="${pageContext.request.contextPath}/user?method=loginOut">注销</a></li>
</ul>
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="搜索一下">
</div>
<button type="submit" class="btn btn-default">搜索</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">购物车</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<nav class="navbar navbar-default">
<p>
<ul id="goodsType">
</ul>
</p>
</nav>
</div>
</body>
</html>

[root@hecs-346515 test]# pwd
/root/dockerfile/build/tomcat/test
[root@hecs-346515 test]# ls
index.jsp WEB_INF


# go 代码 dockerfile 做成镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
yum install go -y

cat main.go
import (
"net/http"

"github.com/gin-gonic/gin"
)

func statusOKHandler(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "success~welcome to study"})
}

func versionHandler(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"version": "v1.1版本"})
}

func main() {
router := gin.New()
router.Use(gin.Recovery())
router.GET("/", statusOKHandler)
router.GET("/version", versionHandler)
router.Run(":8080")
}

go mod init test # test为当前目录
#设置代理
go env -w GOPROXY=https://goproxy.cn,direct
go mod tidy
#构建源码
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o k8s-demo main.go
./k8s-demo


# 编写dockerfile
FROM alpine
WORKDIR /data/app
ADD k8s-demo /data/app/
CMD ["/bin/sh","-c","./k8s-demo"]

docker build -t dashabi:v1 .
docker run -d --name go2 -p 30188:8083 dashabi:v1
curl localhost:30188/version

# python dockerfile 构建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
tar zxvf hello-python.tar.gz
# 得到main.py,requirements.txt

# dockerfile
FROM python:3.7
RUN mkdir /app
WORKDIR /app
ADD . /app/
RUN /usr/local/bin/python -m pip install --upgrade pip
RUN pip install -r requirements.txt
EXPOSE 5000
CMD ["python","/app/main.py"]

docker build -t hello-python:v1 .
docker run -d --name python -p 30050:5000 hello-python:v1

# 发布镜像

dockerhub

1
2
3
4
5
6
#登录dockerhub
[root@hecs-346515 test]# docker login -u kbshire -p

[root@hecs-346515 test]# docker build -t kbshire/avcat:2.333 .
[root@hecs-346515 test]# docker push kbshire/avcat:2.333

阿里云

1. 创建命名空间

image-20230404132912975

2. 创建容器镜像

image-20230404133112291

image-20230404134421264

image-20230404134504442

# Docker 网络

1
2
3
4
bridge模式:使--net =bridge指定,默认设置;
host模式:使--net =host指定;
none模式:使--net =none指定;
container模式:使用--net =container:NAME orID指定。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@hecs-346515 dockerfile]# ip a 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether fa:16:3e:8b:e2:28 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.69/24 brd 192.168.0.255 scope global noprefixroute dynamic eth0
valid_lft 67882sec preferred_lft 67882sec
inet6 fe80::f816:3eff:fe8b:e228/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:27:32:a6:49 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:27ff:fe32:a649/64 scope link
valid_lft forever preferred_lft forever

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
docker run -d -P --name tomcat01 tomcat 

docker exec -it tomcat01 ip addr

# yum install iproute
[root@29ede5d03d63 local]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
161: eth0@if162: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever


linux是可以ping通容器内部的

每启动一个 docker 容器,docker 就会给 docker 容器分配一个 ip,我们只要安装了 docker 就会有一个网卡 docker0

桥接模式,就是 evth-pair 技术

1
2
3
4
162: vetha5d997c@if161: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
link/ether 82:60:95:bc:a3:22 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::8060:95ff:febc:a322/64 scope link
valid_lft forever preferred_lft forever

容器带来的网卡都是一对一对的

evth-pair 就是一队虚拟设备接口,他们是成对出现的,一端连着协议,一端彼此相连

evth-pair 连接各种网络设备

OpenStack,docker 容器之间,ovs 的连接都是使用 evth-pair

容器和容器之间可以互相通信

容器之间通信共用的 docker0,可以理解为一个路由器

不指定容器网络的情况下,都是 docker0 路由的,docker 回给我们的容器分配一个默认 ip

/16 的掩码最多可以有 65535 个地址

docker 使用 linux 桥接,宿主机中是一个 docker 网络的网桥 docker0

image-20230404142456521

docker 中所有网络接口都是虚拟的,转发效率高

容器删除,veth-pair 也就被删除了

1
2
yum install bridge-utils
brctl show
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@hecs-346515 dockerfile]# docker run -it  -P --name centos05 --link gallant_poincare centoshaha:0.5
[root@hecs-346515 ~]# docker exec -it centos05 ping gallant_poincare
通过link实现可以通过服务名ping

[root@hecs-346515 ~]# docker exec -it gallant_poincare ping centos05
ping: centos05: Name or service not known

docker network inspect id

[root@5e0c29c45f15 local]# 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.3 gallant_poincare cef544877c1d
172.17.0.4 5e0c29c45f15

–link 就是在 hosts 中增加了 gallant_poincare 的映射

不建议使用–link

docker0 的问题,他不支持容器名进行连接访问

# 自定义网络

1
2
3
4
5
6
[root@hecs-346515 dockerfile]# docker network ls 
NETWORK ID NAME DRIVER SCOPE
ef281869253b bridge bridge local
81efa88be64b host host local
57ffa6ffd57d loadbalancejsp_default bridge local
55243546bae4 none null local

网络模式

bridge:docker 之间搭桥,自己创建也使用桥接

none:不配置网络,一般不用

​ Docker 网络 none 模式是指创建的容器没有网络地址,只有 lo 网卡

host:和宿主机共享网络

container:容器内网络连通,局限很大

​ 创建新容器的时候,通过–net container 参数,指定其和已经存在的某个容器共享一个 Network Namespace。两个容器的进程通过 lo 网卡设备通信。

​ docker run --name container2 --net=container:none -it --privileged=true centos

1
2
docker run -it --net=none --privileged=true centos 
特权模式下才是真正的root 在容器内部
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
直接启动的命令默认--net bridge  这就是docker0
docker0是默认的,不能通过域名访问

[root@hecs-346515 dockerfile]# docker network create --driver bridge --subnet 10.1.0.0/16 --gateway 10.1.0.1 sbnet
82c4a8b68c66715f88003b8ba4ef65de670286de1c73abee49ab26f9fceb063a
[root@hecs-346515 dockerfile]# docker network ls
NETWORK ID NAME DRIVER SCOPE
ef281869253b bridge bridge local
81efa88be64b host host local
57ffa6ffd57d loadbalancejsp_default bridge local
55243546bae4 none null local
82c4a8b68c66 sbnet bridge local

[root@hecs-346515 dockerfile]# docker network inspect sbnet
[
{
"Name": "sbnet",
"Id": "82c4a8b68c66715f88003b8ba4ef65de670286de1c73abee49ab26f9fceb063a",
"Created": "2023-04-04T18:25:48.537296679+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "10.1.0.0/16",
"Gateway": "10.1.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]

docker run -it -P --name=centos11 --net sbnet centos
docker run -it -P --name=centos12 --net sbnet centos
docker exec -it centos11 ping centos12
不使用--link也能ping通


我们自定义的网络 docker 已经帮我们维护好了关系

可以使不同集群使用不同的网络,保证集群的安全和健康

# 网络连通

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
docker netowrk connect sbnet centos13


[root@hecs-346515 ~]# docker network connect sbnet centos13

[root@hecs-346515 ~]# docker network inspect sbnet
[
{
"Name": "sbnet",
"Id": "82c4a8b68c66715f88003b8ba4ef65de670286de1c73abee49ab26f9fceb063a",
"Created": "2023-04-04T18:25:48.537296679+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "10.1.0.0/16",
"Gateway": "10.1.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"872404abcfc68d09a65ec820c986aa2003737629a0bdf83406152793dc72f228": {
"Name": "centos12",
"EndpointID": "e393d20c796d4c081b726787210dc5a05d645d33c1a75fd6da529ac11db6e0c1",
"MacAddress": "02:42:0a:01:00:03",
"IPv4Address": "10.1.0.3/16",
"IPv6Address": ""
},
"974c928cc0854549c5cf9b8e257adf025bf9e1499b1169b46bf56c1632565bbe": {
"Name": "centos13",
"EndpointID": "a571e55079a80a2f36ff6e181194cadc1ec49b76bd51bb4485be030201a718c7",
"MacAddress": "02:42:0a:01:00:04",
"IPv4Address": "10.1.0.4/16",
"IPv6Address": ""
},
"ed93b6d1202d8953cd9ae12450e44538d1647620423a7cbf63d1bcd9f023e7a6": {
"Name": "centos11",
"EndpointID": "820d037e8faaad9c8a19cd0a58629c1ec1881cc2b9e5e26a21420a1bb8724ccd",
"MacAddress": "02:42:0a:01:00:02",
"IPv4Address": "10.1.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]

将centos13放到了bridge下,一个容器此时有两个地址

要跨网络操作容器,需要 docker connect 连通

# Redis 集群

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
docker run -p 6376:6379 -p 16376:16379 --name redis-6 -v /mydata/redis/node-6/data:/data -v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf 

redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:637
9 172.38.0.16:6379 --cluster-replicas 1

/data # redis-cli -c
127.0.0.1:6379> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:82
cluster_stats_messages_pong_sent:82
cluster_stats_messages_sent:164
cluster_stats_messages_ping_received:77
cluster_stats_messages_pong_received:82
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:164
127.0.0.1:6379> CLUSTER NODES
b75997d0df1dafbbf8db3642f424eedc0cd9695f 172.38.0.15:6379@16379 slave 73a37cfa8c760c3069bd4fb69f9b2a411f556124 0 1680661677823 5 connected
73a37cfa8c760c3069bd4fb69f9b2a411f556124 172.38.0.11:6379@16379 myself,master - 0 1680661677000 1 connected 0-5460
51c02482b19b9ab5dc20ff1852f375ada2f68986 172.38.0.12:6379@16379 master - 0 1680661677522 2 connected 5461-10922
ba2557b0959bed1cc5a446bcd0403721bcb8d002 172.38.0.14:6379@16379 slave 3794de303a95a3718988f3d313f332241b364d7c 0 1680661677000 4 connected
3794de303a95a3718988f3d313f332241b364d7c 172.38.0.13:6379@16379 master - 0 1680661676822 3 connected 10923-16383
73007d040ed6ca3c093fb5061a3358d1ae47a18a 172.38.0.16:6379@16379 slave 51c02482b19b9ab5dc20ff1852f375ada2f68986 0 1680661676000 6 connected

127.0.0.1:6379> set a b
-> Redirected to slot [15495] located at 172.38.0.13:6379
OK
172.38.0.13:6379> get a
^C
/data # redis-cli -c
127.0.0.1:6379> get a
-> Redirected to slot [15495] located at 172.38.0.14:6379
"b"
172.38.0.14:6379> CLUSTER NODES
b75997d0df1dafbbf8db3642f424eedc0cd9695f 172.38.0.15:6379@16379 slave 73a37cfa8c760c3069bd4fb69f9b2a411f556124 0 1680661856417 5 connected
73a37cfa8c760c3069bd4fb69f9b2a411f556124 172.38.0.11:6379@16379 master - 0 1680661856517 1 connected 0-5460
ba2557b0959bed1cc5a446bcd0403721bcb8d002 172.38.0.14:6379@16379 myself,master - 0 1680661855000 7 connected 10923-16383
73007d040ed6ca3c093fb5061a3358d1ae47a18a 172.38.0.16:6379@16379 slave 51c02482b19b9ab5dc20ff1852f375ada2f68986 0 1680661856016 6 connected
51c02482b19b9ab5dc20ff1852f375ada2f68986 172.38.0.12:6379@16379 master - 0 1680661855415 2 connected 5461-10922
3794de303a95a3718988f3d313f332241b364d7c 172.38.0.13:6379@16379 master,fail - 1680661784244 1680661782238 3 connected


# springboot 微服务打包 docker 镜像

1. 构建 springboot 项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
创建package controller
创建class HelloControllerpackage com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello() {
return "hello,shabi";
}
}


package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;

public class HelloController {
@RequestMapping("/hello")
public String hello() {
return "hello,shabi";
}
}

2. 打包应用

image-20230405110530946

image-20230405110610159

3. 编写 dockerfile

1
2
3
4
5
6
7
8
9
10
FROM hzkjhub/java17:17.0.4

COPY *.jar /app.jar

CMD ["--server.port=8080"]

EXPOSE 8080

ENTRYPOINT ["java","-jar","/app.jar"]
~

4. 构建镜像

1
2
3
4
5
docker build -t shabi .
docker run -P -it --name docker333 shabi


curl 127.0.0.1:32778/hello

5. 发布运行

https://www.bilibili.com/video/BV1og4y1q7M4

# docker 资源配额

Docker 通过 cgroup 来控制容器使用的资源限制,可以对 docker 限制的资源包括 CPU、内存、磁盘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker run --help | grep cpu-shares
-c, --cpu-shares int CPU shares (relative weight)

CPU shares (relative weight) 在创建容器时指定容器所使用的CPU份额值。cpu-shares的值不能保证可以获得1个vcpu或者多少GHz的CPU资源,仅仅只是一个弹性的加权值。
默认每个docker容器的cpu份额值都是1024。在同一个CPU核心上,同时运行多个容器时,容器的cpu加权的效果才能体现出来。
cgroups只在多个容器同时争抢同一个cpu资源时,cpu配额才会生效。因此,无法单纯根据某个容器的cpu份额来确定有多少cpu资源分配给它,资源分配结果取决于同时运行的其他容器的cpu分配和容器中进程运行情况。

docker run -it --cpu-shares 512 centos /bin/bash
[root@df176dd75bd4 /]# cat /sys/fs/cgroup/cpu/cpu.shares
512

container_A 的 cpu share 1024,是 container_B 的两倍。当两个容器都需要 CPU 资源时,container_A 可以得到的 CPU 是 container_B 的两倍。

需要注意的是,这种按权重分配 CPU只会发生在 CPU资源紧张的情况下。如果 container_A 处于空闲状态,为了充分利用 CPU资源,container_B 也可以分配到全部可用的 CPU。
docker run --name "container_B" -c 512 ubuntu

对多核 CPU 的服务器,docker 还可以控制容器运行限定使用哪些 cpu 内核和内存节点,即使用–cpuset-cpus 和–cpuset-mems 参数。对具有 NUMA 拓扑(具有多 CPU、多内存节点)的服务器尤其有用,可以对需要高性能计算的容器进行性能最优的配置。如果服务器只有一个内存节点,则–cpuset-mems 的配置基本上不会有明显效果。

1
2
3
4
docker run -itd --name docker10 --cpuset-cpus 0,1 --cpu-shares 512 centos  /bin/bash 
docker run -itd --name docker20 --cpuset-cpus 0,1 --cpu-shares 1024 centos /bin/bash

指定docker20只能在cpu0和cpu1上运行,而且docker20的使用cpu的份额1024,比dcker10多一倍
1
2
3
4
5
6
7
Docker提供参数-m, --memory=""限制容器的内存使用量。

docker run -it -m 128m centos

cat /sys/fs/cgroup/memory/memory.limit_in_bytes

docker run -it --cpuset-cpus 0,1 -m 128m centos
1
2
3
4
5
6
7
8
9
10
--device-write-bps value      Limit write rate (bytes per second) to a device (default [])  
#限制此设备上的写速度(bytes per second),单位可以是kb、mb或者gb。
--device-read-bps value
#限制此设备上的读速度(bytes per second),单位可以是kb、mb或者gb。

情景:防止某个 Docker 容器吃光你的磁盘 I / O 资源

docker run -it -v /var/www/html/:/var/www/html --device /dev/sda:/dev/sda --device-write-bps /dev/sda:2mb centos /bin/bash

time dd if=/dev/sda of=/var/www/html/test.out bs=2M count=50 oflag=direct,nonblock
1
2
docker run -it --rm --name xianchao centos  sleep 6
当容器命令运行结束后,自动删除容器,自动释放资源
1
2
3
4
5
6
总结:
# --cpu-shares 指定容器所使用的CPU份额值
# --cpuset-cpus 控制容器运行限定使用哪些cpu内核和内存节点
# --memory 限制容器的内存使用量
# --device-write-bps value 限制此设备上的写速度(bytes per second),单位可以是kb、mb或者gb
# --device-read-bps value #限制此设备上的读速度(bytes per second),单位可以是kb、mb或者gb

# Harbor

Harbor 是由 VMware 公司开源的企业级的 Docker Registry 管理项目,它包括权限管理 (RBAC)、LDAP、日志审核、管理界面、自我注册、镜像复制和中文支持等功能。

https://github.com/goharbor/harbor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
openssl genrsa -out ca.key 3072
#生成一个3072位的key,也就是私钥
openssl req -new -x509 -days 3650 -key ca.key -out ca.pem
#生成一个数字证书ca.pem,3650表示证书的有效时间是3年

生成域名的证书:
openssl genrsa -out harbor.key 3072

#生成一个3072位的key,也就是私钥
openssl req -new -key harbor.key -out harbor.csr

# 签发证书
openssl x509 -req -in harbor.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out harbor.pem -days 3650

yum install -y wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo ntp libaio-devel wget vim ncurses-devel autoconf automake zlib-devel  python-devel epel-release openssh-server socat  ipvsadm conntrack

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

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

yum install docker-ce -y

内核参数修改:br_netfilter模块用于将桥接流量转发至iptables链,br_netfilter内核参数需要开启转发。
[root@ harbor~]# modprobe br_netfilter
[root@ harbor~]# cat > /etc/sysctl.d/docker.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

sysctl -p /etc/sysctl.d/docker.conf

https://github.com/goharbor/harbor/releases/tag/v2.8.0

tar xzvf harbor-offline-installer-v2.8.0.tgz
cp harbor.yml.tmpl harbor.yml

vim harbor.yml
hostname: 192.168.13.155

# http related config
http:
# port for http, default is 80. If https enabled, this port will redirect to https port
port: 80

# https related config
https:
# https port for harbor, default is 443
port: 443
# The path of cert and key files for nginx
certificate: /data/ssl/harbor.pem
private_key: /data/ssl/harbor.key

admin/Harbor12345

# 安装docker-compose

./prepare
./install.sh
[+] Running 10/10
✔ Network harbor_harbor Created 0.2s
✔ Container harbor-log Started 0.5s
✔ Container registryctl Started 2.0s
✔ Container harbor-db Started 2.0s
✔ Container harbor-portal Started 1.3s
✔ Container registry Started 1.9s
✔ Container redis Started 1.9s
✔ Container harbor-core Started 2.3s
✔ Container nginx Started 3.3s
✔ Container harbor-jobservice Started 3.0s
✔ ----Harbor has been installed and started successfully.----

image-20230423153911479

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 创建项目

vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://fn5y0qpk.mirror.aliyuncs.com"],
"insecure-registries": ["121.37.191.89"]
}

[root@master ~]# systemctl daemon-reload
[root@master ~]# systemctl restart docker

[root@master ~]# docker login 121.37.191.89
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

docker tag hello-world:latest 121.37.191.89/test/hello-world:v1
docker push 121.37.191.89/test/hello-world:v1

docker pull 121.37.191.89/test/hello-world:v1

image-20230423155448444

# Docker Compose

高效的管理容器。定义运行多个容器。使用 yaml 配置

编写 dockerfile 保证我们的项目在任何地方可以运行

定义服务在 docker-compose.yml 中

docker-compose up

批量容器编排

docker-compose 是 docker 的开源项目,需要安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: "3.9"  # optional since v1.27.0
services:
web:
build: .
ports:
- "8000:5000"
volumes:
- .:/code
- logvolume01:/var/log
depends_on:
- redis
redis:
image: redis
volumes:
logvolume01: {}

service 容器,应用

项目 project。一组关联的容器

# 安装 docker compose

1
2
3
4
5
6
7
8
9
curl -SL https://github.com/docker/compose/releases/download/v2.17.2/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose

sudo curl -L "https://get.daocloud.io/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose


chmod +x /usr/local/bin/docker-compose

docker-compose -version
docker-compose version 1.29.2, build 5becea4c

1. 应用 app.py

2.dockerfile 将应用打包为镜像

3.docker-compose yaml 文件 定义整个服务,需要的环境

4. 启动 compose

流程

1. 创建网络

2. 执行 dockercompose.yaml

3. 启动服务

默认的服务名 文件名_服务名_num

_num 代表副本数量

docker-compose 自动维护一个网络,项目中的内容都在同个网络下,实现域名访问

启动 docker-compose up -d

停止 docker-compose down ctrl+c

image-20230405201151236

# yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
version: ''   # 版本
services: # 服务
服务1:web
# 服务配置
images
build
network
服务2:redis
...

# 其他配置 网络,容器卷,全局规则
volumes:
networks:
configs:

# 三层 - version - service - other


Compose file version 3 reference (docker.com)

# docker-compose 搭建 WordPress

awesome-compose/compose.yaml at master · docker/awesome-compose (github.com)

1. 下载项目 (docker-compose.yml)

2. 如果需要 dockerfile

3. 文件准备齐全,一键启动

# 实战

1. 编写微服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.example.demo.controller;

import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

@Autowired
StringRedisTemplate stringRedisTemplate;

@GetMapping("/hello")
public String hello() {
Long views = stringRedisTemplate.opsForValue().increment("views");
return "hello" + views;
}
}

2.dockerfile 构建镜像

1
2
3
4
5
6
7
8
9
10
FROM hzkjhub/java17:17.0.4

COPY *.jar /app.jar

CMD ["--server.port=8080"]

EXPOSE 8080

ENTRYPOINT ["java","-jar","/app.jar"]

3.docker-compose.yml 编排项目

1
2
3
4
5
6
7
8
9
10
11
12
version: "3.9"
services:
web:
build: .
image: haha
depends_on:
- redis
ports:
- "8080:8080"
redis:
image: "redis:alpine3.8"

4. 服务器 up 启动

使用 docker-compose 搭建 nextcloud+Nginx+MySQL+Redis | Case of Xeon (chensmallx.top)

docker-compose 搭建 nginx+php+redis+mysql 环境 - 腾讯云开发者社区 - 腾讯云 (tencent.com)

(66 条消息) Docker-compose 部署 nginx+mysql 模板_docker 部署 nginx mysql_仓鼠 小白的博客 - CSDN 博客

# docker-compose network

# 类型

# default

当我们运行 docker-compose up 时,将会执行以下几步:

  • 创建一个名为 myapp_default 的网络;
  • 使用 web 服务的配置创建容器,它以 “web” 这个名称加入网络 myapp_default;
  • 使用 db 服务的配置创建容器,它以 “db” 这个名称加入网络 myapp_default。

默认情况下 docker-compose 会建立一个默认的网络,名称为 docker-compose.yml 所在目录名称小写形式加上 “_default”,我们的 TFLinux 环境就是 “tflinux_default”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@hecs-346515 ~]# cd ngsql/
[root@hecs-346515 ngsql]# ls
app cache db docker-compose.yml proxy

[root@hecs-346515 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
5ed45bf78d6f app_default bridge local
2eea384bdd95 bridge bridge local
73c5128a4cfc com-nginx_default bridge local
362bcfa74398 composetest_default bridge local
a919986fdc8c host host local
a1c8315f1897 my_wordpress_default bridge local
d1e6b687dcd0 ngsql_default bridge local
a0d53da9cf10 none null local

这个默认网络会对所有 services 下面的服务生效,所以 services 下面的各个服务之间才能够通过 service 名称互相访问。

如果要自定义默认网络可以针对 “default” 网络进行设置,这样就会影响导默认网络了。

1
2
3
4
networks:

default:
driver: bridge
# 自定义

除了默认网络之外,我们也可以建立自定义的网络,这个网络名称就比较随意了。

1
2
3
4
networks:

persist:
driver: bridge

# 已存在网络

通过 docker network create 创建好的网络,而不是让 docker-compose 创建一个新的,这个时候就需要用到 “external” 关键字了。

1
2
3
4
5
networks:

persist:
external:
name: bridge2

Docker Compose 网络设置 - 掘金 (juejin.cn)

docker-compose 的网络 networks 的使用技巧 - 知乎 (zhihu.com)

使用 docker-compose 搭建 nextcloud+Nginx+MySQL+Redis | Case of Xeon (chensmallx.top)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
version: '3.4'
services:

db: # 这里只是给每个容器单独配置一个名称
image: mariadb # 具体的镜像名称,可以使用“:”指定镜像的版本
restart: unless-stopped # 重启的选项,分为no、on-failure、on-failure:x、always、unless-stopped,具体可以自行搜索查看区别
expose:
# expose仅将指定的端口暴露给links的容器,而不对宿主机开放。
# 和ports的区别在于,ports可以映射宿主机别的端口到容器中。
- "3306"
volumes:
# volumes指的是将宿主机的路径映射到容器中的指定位置
- ./db:/var/lib/mysql
environment:
# environment可以对容器创建指定多个环境变量
- MYSQL_ROOT_PASSWORD=root_password # 这里配置root密码
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=user_name # 这里配置一个非root账户给nextcloud使用
- MYSQL_PASSWORD=user_password # 这里配置上面那个账号的密码

cache:
image: redis
restart: unless-stopped
expose:
- "6379"
volumes:
- ./cache:/data
command: redis-server --requirepass 'redis_password' # 这里的redis_password换成你要配置的redis密码
# command指的是启动容器后代替默认启动指令来启动服务的指令

app:
image: nextcloud:fpm
restart: unless-stopped
expose:
- "9000"
volumes:
- ./app/html:/var/www/html
- ./app/data:/var/www/html/data
- ./app/config:/var/www/html/config
- ./app/custom_apps:/var/www/html/custom_apps
links:
# links将容器与当前容器链接起来,以使得当前容器可以访问目标容器expose的端口
# 格式为 容器的原名:映射到当前容器中的名称
- db:db
- cache:cache
depends_on:
# 依赖的容器列表,只有这些容器都成功启动了,才会启动当前容器
- db
- cache

proxy: # 叫做proxy是因为是作为代理来提供服务
image: nginx
restart: unless-stopped
expose:
- "80"
ports:
# ports可将容器内的端口映射到宿主机上
# 这里是将容器的443端口映射到宿主机的7788端口
- 7788:443
volumes:
- ./app/html:/var/www/html
- ./proxy/conf.d:/etc/nginx/conf.d:ro
- ./proxy/ssl_certs:/etc/nginx/ssl_certs:ro
links:
- app:app
depends_on:
- app

# docker swarm

集群的方式部署

Swarm mode cluster

操作都在 manager

# 搭建集群

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
初始化管理节点

[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker swarm init --advertise-addr 172.26.35.5
Swarm initialized: current node (amsigufjp7n6t878um697rtxx) is now a manager.

To add a worker to this swarm, run the following command:

docker swarm join --token SWMTKN-1-378os4pztqynptic0b8kdsgysg21lq6x1u7ru4nxrv99ym9mgc-1hwbeetgvza2ympnj0s9kep3l 172.26.35.5:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.


加入节点
docker swarm join

获取令牌
docker swarm join-token manager
docker swarm join-token worker

[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
amsigufjp7n6t878um697rtxx * iZuf6dzrpxpwleuxiysmvrZ Ready Active Leader 23.0.3
cg0dbg0k739u58yybwwlowr3z iZuf6dzrpxpwleuxiysmvsZ Ready Active 23.0.3


systemctl stop firewalld
systemctl disable firewalld

1. 生成主节点 inti

2. 加入 (manager , worker)

# raft

保证大多数节点存活才可以用,集群至少 > 3 台主节点,必须保证大多数节点存活才可以使用,>1

双主双从的情况下:

manager 停止一个,另一个 manager 也不能用了

其他 worker 随便离开

work 只是工作,需要在管理节点操作

三主一从

至少有两个主存活集群还能使用

# 弹性创建服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker service --help 

Usage: docker service COMMAND

Manage Swarm services

Commands:
create Create a new service
inspect Display detailed information on one or more services
logs Fetch the logs of a service or task
ls List services
ps List the tasks of one or more services
rm Remove one or more services
rollback Revert changes to a service's configuration
scale Scale one or multiple replicated services
update Update a service

灰度发布:金丝雀发布 升级不影响使用

1
2
3
4
5
6
[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker service create -p 8888:80 --name=nginx001  nginx 
vrs4gx1m5dyydclezt4bbwnkj
overall progress: 1 out of 1 tasks
1/1: running
verify: Service converged

1
2
docker run #容器启动,不具有扩缩容
docker service #具有扩缩容,滚动更新
1
2
3
4
5
6
7
8
9
10
11
12
[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker service ps nginx001 
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
2eewg8do04rd nginx001.1 nginx:latest iZuf6dzrpxpwleuxiysmvrZ Running Running about a minute ago
[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
vrs4gx1m5dyy nginx001 replicated 1/1 nginx:latest *:8888->80/tcp
[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker service create -p 8888:80 --name=nginx001 nginx
[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker service update --replicas 3 nginx001
# 服务,集群中的任意节点都可以被访问,服务可以有多个副本动态扩缩容实现高可用
[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker service scale nginx001=5
[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker service rm nginx001
[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker service ls

swarm

集群的管理和编排,docker 可以初始化一个集群,其他节点可以加入

加入时由 manager 和 worker 角色

node

就是一个 docker 节点,多个节点组成了网络集群

service

任务,可以在管理节点或工作节点运行。用户访问的就是他

task

容器内的命令

命令 -> 管理 ->api -> 调度 -> 工作节点 (创建 task 容器维护)

调整 service 以什么方式运行

1
2
3
4
5
6
--mode string 

global server / replicated service

[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker service create --mode global --name haha centos
[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker service create --mode replicated --name haha centos

global 能在任何节点运行,replicated 只能在 worker 运行,默认 replicated

image-20230407140542074
1
[root@iZuf6dzrpxpwleuxiysmvrZ ~]# yum install bridge-utils.x86_64 

swarm 中有三个网络,ingress,overlay,

ingress:特殊的 overlay,具有负载均衡功能

# Docker Stack

集群部署项目,相当于集群版的 docker-compose

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
docker stack deploy 111.yml

[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker stack --help

Usage: docker stack COMMAND

Manage Swarm stacks

Commands:
config Outputs the final config file, after doing merges and interpolations
deploy Deploy a new stack or update an existing stack
ls List stacks
ps List the tasks in the stack
rm Remove one or more stacks
services List the services in the stack

# docker secret

安全,证书,配置密码

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker secret --help 

Usage: docker secret COMMAND

Manage Swarm secrets

Commands:
create Create a secret from a file or STDIN as content
inspect Display detailed information on one or more secrets
ls List secrets
rm Remove one or more secrets


# docker config

配置

1
2
3
4
5
6
7
8
9
10
11
12
[root@iZuf6dzrpxpwleuxiysmvrZ ~]# docker config --help

Usage: docker config COMMAND

Manage Swarm configs

Commands:
create Create a config from a file or STDIN
inspect Display detailed information on one or more configs
ls List configs
rm Remove one or more configs

# ctr && crictl

image-20230626205442159

image-20230626205458946

Containerd 也有 namespaces 的概念,对于上层编排系统的支持,主要区分了 3 个命名空间分别是 k8s.iomobydefault ,以上我们用 crictl 操作的均在 k8s.io 命名空间完成如查看镜像列表就需要加上 -n 参数

1
ctr -n k8s.io images list
Edited on

Give me a cup of [coffee]~( ̄▽ ̄)~*

John Doe WeChat Pay

WeChat Pay

John Doe Alipay

Alipay

John Doe PayPal

PayPal