1.什么是docker
2.docker安装
容器安装部署
echo 'net.ipv4.ip_forward = 1' >>/etc/sysctl.conf
sysctl -p
dnf install -y docker-ce
# 查看服务器与客户端版本
docker version
#镜像加速地址可以去阿里云或华为云获取
[root@docker ~]# vim /etc/docker/daemon.json
{
"registry-mirrors": ["这里配置镜像仓库加速器地址"],
"insecure-registries":[]
}
[root@docker ~]# systemctl restart docker
# 查看 docker 服务配置信息
[root@docker ~]# docker info
... ...
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://镜像仓库加速器/
Live Restore Enabled: false
3.容器管理
镜像管理命令 | 说明 |
docker images | 查看本机镜像 |
docker pull 镜像名称:标签 | 下载镜像 |
docker save 镜像名称:标签 -o 文件名 | 备份镜像为tar包 |
docker load -i 备份文件名称 | 导入备份的镜像文件 |
docker history 镜像名称:标签 | 查看镜像的制作历史 |
3.1pull、images、history
# 下载 busybox:latest 镜像
[root@docker ~]# docker pull busybox:latest
# 查看本机镜像
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest a9d583973f65 2 years ago 1.23MB
# 查看镜像的制作历史
[root@docker ~]# docker history busybox:latest
IMAGE CREATED CREATED BY SIZE
a9d583973f65 2 years ago /bin/sh -c #(nop) CMD ["sh"] 0B
<missing> 2 years ago /bin/sh -c #(nop) ADD file:b4b40618f2… 1.23MB
3.2save、load
# 导入镜像
[root@docker ~]# docker load -i myos.tar.xz
Loaded image: rockylinux:8.5
Loaded image: myos:8.5
Loaded image: myos:php-fpm
Loaded image: myos:nginx
Loaded image: myos:httpd
Loaded image: myos:latest
# 备份镜像为 tar 包
[root@docker ~]# docker save busybox:latest -o busybox.tar
# 查看本机镜像
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
myos php-fpm f70bdfd2042c 12 months ago 275MB
myos nginx 10dc658da2fe 12 months ago 274MB
myos latest 1de38c85c2d1 13 months ago 4.67MB
myos httpd 9245e660f88f 13 months ago 299MB
myos 8.5 621bfd7f9b46 13 months ago 249MB
rockylinux 8.5 210996f98b85 2 years ago 205MB
busybox latest a9d583973f65 2 years ago 1.23MB
4.管理命令(2)
容器管理命令 | 说明 |
docker run -it(d) 镜像名称:标签 | 创建容器(d在后台运行) |
docker ps | 查看容器的信息 |
docker inspect 镜像名称|容器名称 | 查询(容器/镜像)的详细信息 |
docker [start|stop|restart] 容器id | 启动、停止、重启容器 |
docker exec -it 容器ID 启动命令 | 在容器内执行命令 |
docker logs 容器ID | 查看容器日志 |
docker cp 路径1 路径2 | 拷贝文件:路径格式(本机路径、容器ID/路径) |
4.1run
# 创建一个容器
[root@docker ~]# docker run -it myos:8.5
#进入容器内部
[root@3aa1df05b795 /]# hostname
3aa1df05b795
[root@3aa1df05b795 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 15:13 pts/0 00:00:00 /bin/bash
root 19 1 0 15:13 pts/0 00:00:00 ps -ef
[root@3aa1df05b795 /]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@3aa1df05b795 /]# exit
# 创建后台容器
[root@docker ~]# docker run -itd myos:httpd
6d6884244a995791f8171efa3ce81be1e9e51bedf25c3a5a67bac8bb7bc019b0
# 创建名为web1的后台容器
[root@docker ~]# docker run -itd --name web1 myos:nginx
14b669a75a95e9ba590c37137abc9d828d2c769d46f69c35fb0e8cc98cc544c4
4.2ps
# 查询容器状态
[root@docker ~]# docker ps
CONTAINER ID IMAGE ... ... STATUS PORTS NAMES
14b669a75a95 myos:nginx ... ... Up 25 minutes 80/tcp web1
6d6884244a99 myos:httpd ... ... Up 25 minutes 80/tcp hawking
#-a参数显示所有的容器,包含停止的
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE ... ... STATUS PORTS NAMES
14b669a75a95 myos:nginx ... ... Up 25 minutes 80/tcp web1
6d6884244a99 myos:httpd ... ... Up 25 minutes 80/tcp hawking
47ded92f442f myos:8.5 ... ... Exited (0) yonath
[root@docker ~]# docker ps -aq
14b669a75a95
6d6884244a99
47ded92f442f
4.3start、stop、restart
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE ... ... STATUS PORTS NAMES
14b669a75a95 myos:nginx ... ... Up 25 minutes 80/tcp web1
6d6884244a99 myos:httpd ... ... Up 25 minutes 80/tcp hawking
47ded92f442f myos:8.5 ... ... Exited (0) yonath
# 启动容器
[root@docker ~]# docker start web1 47ded92f442f
web1
47ded92f442f
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE ... ... STATUS PORTS NAMES
14b669a75a95 myos:nginx ... ... Up 25 minutes 80/tcp web1
6d6884244a99 myos:httpd ... ... Up 25 minutes 80/tcp hawking
47ded92f442f myos:8.5 ... ... Up 2 seconds yonath
# 停止容器
[root@docker ~]# docker stop web1
web1
# 命令替换,停止所有容器
[root@docker ~]# docker stop $(docker ps -aq)
14b669a75a95
6d6884244a99
47ded92f442f
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE ... ... STATUS PORTS NAMES
14b669a75a95 myos:nginx ... ... Exited (0) web1
6d6884244a99 myos:httpd ... ... Exited (0) hawking
47ded92f442f myos:8.5 ... ... Exited (0) yonath
# 重启容器
[root@docker ~]# docker restart web1
web1
4.4inspect
# 查询镜像的详细信息
[root@docker ~]# docker inspect myos:httpd
{ ......
"Cmd": [
"httpd",
"-DFOREGROUND"
],
......
}
# 查询容器的详细信息
[root@docker ~]# docker inspect web1 6d6884244a99
[
{ ... ...
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
... ...
"Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "",
"IPPrefixLen": 0,
... ...
}
]
4.5exec、cp、logs
# 在容器内执行非交互命令
[root@docker ~]# docker exec -it web1 ls
50x.html index.html
# 加bash会进入容器内执行命令
[root@docker ~]# docker exec -it web1 bash
[root@14b669a75a95 html]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
... ...
[root@14b669a75a95 html]# vim /usr/local/nginx/conf/nginx.conf
32: listen 80
[root@14b669a75a95 html]# exit
# 从容器内拷贝文件出来,容器的路径不能省略
[root@docker ~]# docker cp web1:/usr/local/nginx/conf ./
Successfully copied 45.6kB to /root/./
# 重启容器
[root@docker ~]# docker restart web1
web1
[root@docker ~]# docker ps -a
14b669a75a95 myos:nginx ... ... Exited (1) web1
# 查看日志拍错
[root@docker ~]# docker logs web1
nginx: [emerg] invalid parameter "server_name" in /usr/local/nginx/conf/nginx.conf:33
# 修复配置文件错误
[root@docker ~]# vim conf/nginx.conf
32: listen 80;
[root@docker ~]# docker cp conf/nginx.conf web1:/usr/local/nginx/conf/nginx.conf
Successfully copied 4.61kB to web1:/usr/local/nginx/conf/nginx.conf
[root@docker ~]# docker restart web1
web1
[root@docker ~]# docker ps
CONTAINER ID IMAGE ... ... STATUS PORTS NAMES
14b669a75a95 myos:nginx ... ... Up 2 seconds 80/tcp web1
5.管理命令(3)
管理命令 | 说明 |
docker rm 容器ID | 删除容器(-f运行中也可以强制删除) |
docker tag 镜像ID:标签 镜像名称:新的标签 | 创建新的镜像名称和标签 |
docker rmi 镜像名称:标签 | 删除镜像(必须先删除该镜像启动的所有容器) |
5.1rm、rmi、tag
# 删除容器
[root@docker ~]# docker rm 47ded92f442f
# 强制删除容器
[root@docker ~]# docker rm -f web1
# 删除所有容器(docker ps -aq显示所有容器进程号)
[root@docker ~]# docker rm -f $(docker ps -aq)
6d6884244a99
# 删除一个镜像
[root@docker ~]# docker rmi -f busybox:latest
Untagged: busybox:latest
# 已经创建了容器的镜像无法删除
[root@docker-0001 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
... ...
myos latest 1de38c85c2d1 13 months ago 4.67MB
<none> <none> a9d583973f65 2 years ago 1.23MB
# 给镜像设置一个新的名称标签
[root@docker ~]# docker tag a9d583973f65 busybox:latest
[root@docker ~]# docker images
[root@docker-0001 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
......
myos latest 1de38c85c2d1 13 months ago 4.67MB
busybox latest a9d583973f65 2 years ago 1.23MB
6.简单镜像制作
# 使用基础镜像创建一个容器
[root@docker ~]# docker run -itd --name linux rockylinux:8.5
# 删除容器内的Yum配置文件
[root@docker ~]# docker exec -it linux rm -rf /etc/yum.repos.d
# 拷贝宿主机的Yum配置文件到容器内
[root@docker ~]# docker cp /etc/yum.repos.d linux:/etc/
# 在容器内安装工具软件包
[root@docker ~]# docker exec -it linux dnf install -y net-tools vim-enhanced tree bash-completion iproute procps-ng psmisc
# 清理缓存文件
[root@docker ~]# docker exec -it linux dnf clean all
# 停止容器
[root@docker ~]# docker stop linux
# 把容器制作成镜像
[root@docker ~]# docker commit linux mylinux:latest
sha256:7a4449e20f4c59d1f6c4db838b4724cbf63c8f4195513c5f17d053c7752891d5
# 查看新制作的镜像
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mylinux latest b64da40467ae 3 seconds ago 249MB
rockylinux 8.5 210996f98b85 13 months ago 205MB
# 删除制作镜像的容器
[root@docker ~]# docker rm -f linux
linux
7.容器服务原理
8.容器部署应用
8.1部署 apache 服务
# 删除所有容器
[root@docker ~]# docker rm -f $(docker ps -aq)
# 创建一个名为 myweb 的容器
[root@docker ~]# docker run -it --rm --name myweb mylinux:latest
#-----------------------------------------------------------
# 在容器内安装部署 apache
[root@a7f9d0c3e3e2 /]# dnf install -y httpd
[root@a7f9d0c3e3e2 /]# echo "Hello World ." >/var/www/html/index.html
[root@a7f9d0c3e3e2 /]# cat /usr/lib/systemd/system/httpd.service
[root@a7f9d0c3e3e2 /]# export LANG=C
[root@a7f9d0c3e3e2 /]# /usr/sbin/httpd -DFOREGROUND
# 在另一个终端完成访问验证
/usr/sbin/httpd -DFOREGROUND注解:在容器中启动服务时,通常会使用前台运行(foreground)的方式启动服务,这样可以方便地查看服务的日志输出和终止服务。而使用systemctl来启动服务通常用于宿主机操作系统上管理系统服务,它是一个系统服务管理器,用于管理和控制系统服务的启动、停止、重启等操作。在容器中运行的服务通常是独立的进程,不需要systemctl来管理。因此在容器中启动服务时,直接使用命令启动服务是比较常见的做法。
8.2为 apache 添加解析 php 文件支持
# ctrl + c 终止 httpd 服务运行
[root@a7f9d0c3e3e2 /]# dnf install -y php
[root@a7f9d0c3e3e2 /]# vim /etc/httpd/conf.modules.d/00-mpm.conf
11: LoadModule mpm_prefork_module ... ... # 去掉注释
23: # LoadModule mpm_event_module ... ... # 注释配置
[root@a7f9d0c3e3e2 /]# /usr/sbin/httpd -DFOREGROUND
# 服务不要关闭,在其他终端完成测试
8.3验证配置
# 在另一个终端拷贝 public/info.php 到 docker 主机
[root@docker ~]# docker cp info.php myweb:/var/www/html/
[root@docker ~]# curl http://172.17.0.2/info.php
<pre>
Array
(
[REMOTE_ADDR] => 172.17.0.1
[REQUEST_METHOD] => GET
[HTTP_USER_AGENT] => curl/7.61.1
[REQUEST_URI] => /info.php
)
php_host: 616e75df56ae
1229
9.Dockerfile
9.1概述
9.2常用语法命令
指令 | 说明 |
FROM | 指定基础镜像(唯一) |
RUN | 在容器内执行命令,可以写多条 |
ADD | 把文件拷贝到容器内,如果文件是 tar.xx 格式,会自动解压 |
COPY | 把文件拷贝到容器内,不会自动解压 |
ENV | 设置启动容器的环境变量 |
WORKDIR | 设置启动容器的默认工作目录(唯一) |
CMD | 容器默认的启动参数(唯一) |
ENTRYPOINT | 容器默认的启动命令(唯一) |
USER | 启动容器使用的用户(唯一) |
EXPOSE | 使用镜像创建的容器默认监听使用的端口号/协议 |
9.3语法案例(1)
# 编写 Dockerfile
[root@docker ~]# mkdir myimg
[root@docker ~]# vim myimg/Dockerfile
FROM mylinux:latest
CMD ["/bin/ls", "-l"]
# 创建镜像
[root@docker ~]# docker build -t img1:latest myimg
......
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
img1 latest 9278f72f8cb1 5 seconds ago 249MB
mylinux latest e3b3d26bf0da 21 hours ago 249MB
rockylinux 8.5 210996f98b85 13 months ago 205MB
# 创建容器
[root@docker ~]# docker run -it --rm img1:latest
total 48
lrwxrwxrwx 1 root root 7 Oct 11 2021 bin -> usr/bin
drwxr-xr-x 5 root root 360 Feb 5 04:21 dev
drwxr-xr-x 1 root root 4096 Feb 5 04:21 etc
drwxr-xr-x 2 root root 4096 Oct 11 2021 home
......
# 传递参数命令,覆盖 CMD 执行
[root@docker ~]# docker run -it --rm img1:latest id
uid=0(root) gid=0(root) groups=0(root)
9.4语法案例(2)
# ENTRYPOINT 与 CMD 执行方式为 ${ENTRYPOINT} ${@-${CMD}}
[root@docker ~]# vim myimg/Dockerfile
FROM mylinux:latest
ENTRYPOINT ["echo"]
CMD ["/bin/ls", "-l"]
# 创建镜像
[root@docker ~]# docker build -t img2:latest myimg
......
# CMD 做为参数传递,在容器内执行了 echo '/bin/ls -l'
[root@docker ~]# docker run -it --rm img2:latest
/bin/ls -l
# CMD 被替换,在容器内执行了 echo id
[root@docker ~]# docker run -it --rm img2:latest id
id
ENTRYPOINT
ENTRYPOINT指令用于配置容器启动时运行的可执行文件,让容器以该可执行文件作为PID 1进程运行。这意味着,无论容器以什么命令启动,ENTRYPOINT指定的程序都会被执行,而传递给docker run命令的参数会被作为ENTRYPOINT指定命令的参数。
用法:
ENTRYPOINT ["executable", "param1", "param2"](推荐方式,以JSON数组格式)
ENTRYPOINT command param1 param2(shell形式,但不如JSON数组形式灵活)
特点:
容器启动时,ENTRYPOINT指定的程序会被执行,并且会成为容器的PID 1进程。
docker run命令中指定的任何参数都会被传递给ENTRYPOINT指定的程序。
如果docker run命令中指定了其他命令,这个命令会覆盖CMD指令(如果存在),但ENTRYPOINT指定的程序仍然会被执行,并且docker run中的命令及其参数会被作为ENTRYPOINT指定程序的参数。
CMD
CMD指令用于为容器提供默认的执行命令。当容器启动时,并且没有通过docker run命令指定其他命令时,CMD指定的命令会被执行。但是,如果docker run命令中指定了其他命令,CMD指定的命令就会被覆盖。
用法:
CMD ["executable","param1","param2"](推荐方式,以JSON数组格式)
CMD ["param1","param2"](作为ENTRYPOINT的默认参数)
CMD command param1 param2(shell形式)
特点:
容器启动时,如果没有通过docker run命令指定其他命令,CMD指定的命令会被执行。
如果docker run命令中指定了其他命令,CMD指定的命令会被覆盖。
当CMD和ENTRYPOINT一起使用时,CMD的内容会被作为ENTRYPOINT指定命令的参数。
9.5语法案例(3)
# 制作测试文件
[root@docker ~]# tar -cf myimg/myfile.tar -C /etc hosts issue
# 编辑Dockerfile
[root@docker ~]# vim myimg/Dockerfile
FROM mylinux:latest
COPY myfile.tar /var/tmp/#复制本地文件到容器目录下
ADD myfile.tar /tmp/#复制本地文件到容器目录下,并解压
RUN id && touch /tmp/file1#id号创建文件
USER nobody#指定用户为nobody
RUN id && touch /tmp/file2#以nobody身份创建文件
ENV mymsg="Hello World"
WORKDIR /tmp#指定工作目录
CMD ["/bin/bash"]#以交互模式运行,用户将能够在这个Bash shell中操作。
# 创建镜像
[root@docker ~]# docker build -t img3:latest myimg
......
# 运行测试
[root@docker ~]# docker run -it --rm img3:latest
# 使用 COPY 进来的文件还是 tar 包
bash-4.4$ tree /var/tmp
/var/tmp
`-- myfile.tar
# 使用 ADD 添加的文件已经被解压了
bash-4.4$ tree /tmp
/tmp
|-- hosts
`-- issue
# USER 指令设置使用 nobody 用户运行容器
bash-4.4$ id
uid=65534(nobody) gid=65534(nobody) groups=65534(nobody)
# USER 指令前创建的文件是 root 权限,之后是 USER 用户权限
bash-4.4$ ls -l /tmp/file?
-rw-r--r-- 1 root root 0 Feb 5 05:25 /tmp/file1
-rw-r--r-- 1 nobody nobody 0 Feb 5 05:25 /tmp/file2
# 环境变量可以直接调用
bash-4.4$ echo ${mymsg}
Hello World
# WORKDIR 把工作目录设置到 /tmp
bash-4.4$ pwd
/tmp
10.apache 镜像
10.1手工部署
# 创建容器
[root@docker ~]# docker run -it --name httpd mylinux:latest
# 安装软件包
[root@975fb53cb155 /]# dnf install -y httpd php && dnf clean all
# 修改配置文件
[root@975fb53cb155 /]# vim /etc/httpd/conf.modules.d/00-mpm.conf
11: LoadModule mpm_prefork_module ... ... # 去掉注释
23: # LoadModule mpm_event_module ... ... # 注释配置
[root@975fb53cb155 /]# export LANG=C
[root@975fb53cb155 /]# /usr/sbin/httpd -DFOREGROUND
# 使用快捷键 (ctrl-p, ctrl-q) 退出
[root@docker ~]#
# 添加测试页面
[root@docker ~]# echo 'Welcome to The Apache.' >index.html
[root@docker ~]# docker cp index.html httpd:/var/www/html/
[root@docker ~]# docker cp info.php httpd:/var/www/html/
10.2制作镜像
# 编写 dockerfile 文件
[root@docker ~]# mkdir httpd
[root@docker ~]# vim httpd/Dockerfile
FROM mylinux:latest
RUN dnf install -y httpd php && dnf clean all
RUN sed -ri -e 's,^Load.*,#&,' -e 's,^#(.*mod_mpm_prefork.so)$,\1,' /etc/httpd/conf.modules.d/00-mpm.conf
ENV LANG=C
ADD myweb.tar.gz /var/www/html/
WORKDIR /var/www/html/
EXPOSE 80/tcp
CMD ["/usr/sbin/httpd", "-DFOREGROUND"]
[root@docker ~]# tar -czf httpd/myweb.tar.gz index.html info.php
[root@docker ~]# docker build -t httpd:latest httpd
......
s,^Load.*,#&,
这个操作将注释掉所有以 Load 开头的行,这些行通常用于加载 Apache 的模块。
s,^#(.*mod_mpm_prefork.so)$,\1,
这个操作是取消注释掉 mod_mpm_prefork.so 模块的加载指令(假设这个指令之前被注释了)。\1 在替换字符串中表示第一个捕获组的内容,即去掉 # 后的mod_mpm_prefork.so。
10.3验证测试
ker images httpd:latest
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd latest c1e854cde1f4 About a minute ago 299MB
[root@docker ~]# docker run -itd --name apache httpd:latest
cc2b82ad0367172c344c7207def94c4c438027c60859e94883e440b53a860a93
# 查看容器地址并访问验证
[root@docker ~]# docker inspect apache |grep -i IPAddress
[root@docker ~]# curl http://172.17.0.2/info.php
<pre>
Array
(
[REMOTE_ADDR] => 172.17.0.1
[REQUEST_METHOD] => GET
[HTTP_USER_AGENT] => curl/7.61.1
[REQUEST_URI] => /info.php
)
php_host: 2fbc8c132f7f
1229
[root@docker ~]# docker rm -f $(docker ps -aq)
11.nginx 镜像
11.1手工部署
# 创建容器
[root@docker ~]# docker run -itd --name web mylinux:latest
a1448547a12c15c8b1d1defa76e96f63f0f68ccb6bdeb59958ee57fc5dfac11e
# 拷贝 nginx 源码包到容器内
[root@docker ~]# docker cp nginx-1.22.1.tar.gz web:/
Successfully copied 1.08MB to web:/
# 进入容器配置
[root@docker ~]# docker exec -it web bash
# 安装编译工具和依赖软件包
[root@a1448547a12c /]# dnf install -y openssl-devel pcre-devel gcc make
[root@a1448547a12c /]# dnf clean all
# 编译安装
[root@a1448547a12c /]# tar zxf nginx-1.22.1.tar.gz
[root@a1448547a12c /]# cd nginx-1.22.1/
[root@a1448547a12c nginx-1.22.1]# ./configure --prefix=/usr/local/nginx --with-pcre --with-http_ssl_module
[root@a1448547a12c nginx-1.22.1]# make && make install
# 设置默认首页
[root@a1448547a12c nginx-1.22.1]# echo 'Nginx is running !' >/usr/local/nginx/html/index.html
# 添加 nginx 到环境变量
[root@a1448547a12c nginx-1.22.1]# export PATH=${PATH}:/usr/local/nginx/sbin
# 启动服务
[root@a1448547a12c nginx-1.22.1]# nginx -g "daemon off;"
# 退出容器
[root@153c0df095e2 nginx-1.22.1]# exit
11.2制作镜像
# 将编译好的 nginx 拷贝出来
[root@docker ~]# mkdir nginx
[root@docker ~]# docker cp web:/usr/local/nginx /root/nginx/nginx
Successfully copied 5.82MB to /root/nginx/
# 编写 Dockerfile 文件
[root@docker ~]# vim nginx/Dockerfile
FROM mylinux:latest
RUN dnf install -y pcre openssl && dnf clean all
COPY nginx /usr/local/nginx
ENV PATH=${PATH}:/usr/local/nginx/sbin
WORKDIR /usr/local/nginx/html
EXPOSE 80/tcp
CMD ["nginx", "-g", "daemon off;"]
[root@docker ~]# docker build -t nginx:latest nginx
......
11.3验证测试
# 查看镜像并创建容器
[root@docker ~]# docker images nginx:latest
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 645dd2d9a8ec 3 minutes ago 274MB
[root@docker ~]# docker run -itd --name nginx nginx:latest
e440b53a860a93cc2b82ad0367172c344c7207def94c4c438027c60859e94883
# 查看容器地址并访问验证
[root@docker ~]# docker inspect nginx |grep -i IPAddress
[root@docker ~]# curl http://172.17.0.2/
Nginx is running !
[root@docker ~]# docker rm -f $(docker ps -aq)
11.4多阶段镜像
[root@docker ~]# rm -rf nginx/nginx
[root@docker ~]# mv /root/nginx-1.22.1.tar.gz nginx/
[root@docker ~]# vim nginx/Dockerfile
# 第一阶段编译程序
FROM mylinux:latest as builder
ADD nginx-1.22.1.tar.gz /
WORKDIR /nginx-1.22.1
RUN dnf install -y openssl-devel pcre-devel gcc make
RUN ./configure --prefix=/usr/local/nginx --with-pcre --with-http_ssl_module
RUN make && make install
RUN echo 'Nginx is running !' >/usr/local/nginx/html/index.html
# 第二阶段最终镜像
FROM mylinux:latest
RUN dnf install -y pcre openssl && dnf clean all
COPY --from=builder /usr/local/nginx /usr/local/nginx
#第一阶段制作好的镜像,将一阶段的nginx目录拷贝到二阶段
ENV PATH=${PATH}:/usr/local/nginx/sbin
WORKDIR /usr/local/nginx/html
EXPOSE 80/tcp
CMD ["nginx", "-g", "daemon off;"]
[root@docker ~]# docker build -t nginx:latest nginx
12.php-fpm 镜像
12.1手工部署
[root@docker ~]# docker run -it --name myphp mylinux:latest
[root@cbcf3d90c02e /]# dnf install -y php-fpm
# 修改配置文件
[root@cbcf3d90c02e /]# vim /etc/php-fpm.d/www.conf
38: listen = 127.0.0.1:9000
# 创建目录,并授权
[root@cbcf3d90c02e /]# mkdir /run/php-fpm
[root@cbcf3d90c02e /]# chown -R nobody.nobody /var/log/php-fpm /run/php-fpm
# 使用 sudo 且换用户
[root@cbcf3d90c02e /]# dnf install -y sudo
[root@cbcf3d90c02e /]# sudo -u nobody /bin/bash
# 使用 nobody 启动服务
bash-4.4$ /usr/sbin/php-fpm --nodaemonize
[04-Sep-2023 09:58:01] NOTICE: [pool www] 'user' directive is ignored when FPM is not running as root
[04-Sep-2023 09:58:01] NOTICE: [pool www] 'group' directive is ignored when FPM is not running as root
[04-Sep-2023 09:58:01] NOTICE: fpm is running, pid 1
[04-Sep-2023 09:58:01] NOTICE: ready to handle connections
[04-Sep-2023 09:58:01] NOTICE: systemd monitor interval set to 10000ms
12.2制作镜像
# 编写 dockerfile 文件
[root@docker ~]# mkdir php
[root@docker ~]# docker cp myphp:/etc/php-fpm.d/www.conf /root/php/www.conf
[root@docker ~]# vim php/Dockerfile
FROM mylinux:latest
RUN dnf install -y php-fpm && dnf clean all && \
mkdir -p /run/php-fpm && \
chown -R nobody.nobody /run/php-fpm /var/log/php-fpm
COPY www.conf /etc/php-fpm.d/www.conf
USER nobody
EXPOSE 9000/tcp
CMD ["/usr/sbin/php-fpm", "--nodaemonize"]
[root@docker ~]# docker build -t php-fpm:latest php
......
# 查看镜像并创建容器
[root@docker ~]# docker images php-fpm:latest
REPOSITORY TAG IMAGE ID CREATED SIZE
php-fpm latest b2404bd119b0 48 seconds ago 275MB
[root@docker ~]# docker run -itd --name php php-fpm:latest
6eeff6af4a6469c298944b2bdd2ba69f32ebcbc6cb683a0a05af4eefbf90e8c1
# 验证服务
[root@docker ~]# docker exec -it php /bin/bash
# 验证用户
bash-4.4$ id
uid=65534(nobody) gid=65534(nobody) groups=65534(nobody)
# 我们无法直接调用 php 服务,可以通过查看进程验证服务
bash-4.4$ ps -ef
UID PID PPID C STIME CMD
nobody 1 0 0 16:13 php-fpm: master process (/etc/php-fpm.conf)
nobody 7 1 0 16:13 php-fpm: pool www
nobody 8 1 0 16:13 php-fpm: pool www
nobody 17 0 0 16:13 /bin/bash
nobody 19 17 0 16:13 ps -ef
bash-4.4$ exit
[root@docker ~]# docker rm -f $(docker ps -aq)
13.docker 私有仓库
13.1仓库概述
13.2安装
主机名 | ip地址 | 最低配置 |
registry | 192.168.1.35 | 2CPU,4G内存 |
# 在 registry 上安装私有仓库
[root@registry ~]# dnf install -y docker-distribution
# 启动私有仓库,并设置开机自启动
[root@registry ~]# systemctl enable --now docker-distribution
13.3客户端配置
[root@docker ~]# vim /etc/hosts
192.168.1.35 registry
# 修改配置文件
[root@docker ~]# vim /etc/docker/daemon.json
{
"registry-mirrors": ["http://registry:5000"],
"insecure-registries":["registry:5000"]
}
# 重启服务生效
[root@docker ~]# systemctl restart docker
[root@docker ~]# docker info
# 给 nginx 镜像设置标签
[root@docker ~]# docker tag nginx:latest registry:5000/img/myimg:nginx
# 上传 nginx 镜像
[root@docker ~]# docker push registry:5000/img/myimg:nginx
The push refers to repository [registry:5000/img/myimg]
c9d01852a13b: Pushed
......
nginx: digest: sha256:3e1fc9ad1ee46ee4619c95dc9d71034d919e53abfc size: 952
# 上传 php-fpm 镜像
[root@docker ~]# docker tag php-fpm:latest registry:5000/img/myimg:php-fpm
[root@docker ~]# docker push registry:5000/img/myimg:php-fpm
The push refers to repository [registry:5000/img/myimg]
619c95dc93e1: Pushed
......
php-fpm: digest: sha256:619c95dc93e1fc9ad1ee46ee4d71034d919e53abfc size: 875
# 上传 httpd 镜像
[root@docker ~]# docker tag httpd:latest registry:5000/library/httpd:latest
[root@docker ~]# docker push registry:5000/library/httpd:latest
The push refers to repository [registry:5000/library/httpd]
95dc9d71034d: Pushed
......
latest: digest: sha256:95dc9d71034d919e53abfc3e1fc9ad1ee46ee4619c size: 968
13.4验证测试
查看镜像名称: curl http://仓库IP:5000/v2/_catalog
查看镜像标签: curl http://仓库IP:5000/v2/镜像路径/tags/list
使用易读格式: python3 -m json.tool
13.5创建容器
# 删除所有容器
[root@docker ~]# docker rm -f $(docker ps -aq)
......
# 删除所有镜像
[root@docker ~]# docker rmi -f $(docker images -q)
......
# 使用仓库中的镜像运行容器
[root@docker ~]# docker run -itd --rm registry:5000/img/myimg:nginx
2b7cd6d88a7665dbea0a4b3d99478e9f302c0a5661d7676d6d3bd3cb6d181
# library 是默认路径,可以省略路径地址
[root@docker ~]# docker run -itd --rm httpd:latest
634766f788d665dbea0a4b39709e0a2cc8624fd99478e9f302c0a5661d767
14.端口绑定
15.容器存储卷
15.1数据卷目录
# 创建卷目录,并添加测试页面
[root@docker ~]# mkdir /var/webroot
[root@docker ~]# echo "hello world" >/var/webroot/index.html
# 使用卷映射数据目录
[root@docker ~]# docker rm -f web
[root@docker ~]# docker run -itd --rm --name web -p 80:80 \
-v /var/webroot:/usr/local/nginx/html myos:nginx
[root@docker ~]# curl http://192.168.1.31/
hello world
# 修改数据卷内容可以直接在容器内体现
[root@ecs-proxy s4]# rsync -av public/info.php 192.168.1.31:/var/webroot/
[root@ecs-proxy s4]# curl http://192.168.1.31/info.php
<?PHP
15.2修改配置文件
# 获取配置文件
[root@docker ~]# docker cp web:/usr/local/nginx/conf ./conf
Successfully copied 45.1kB to /root/conf
# 编辑配置文件,添加 php 解析配置
[root@docker ~]# vim conf/nginx.conf
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
# 使用卷映射配置文件,重建 nginx 容器
[root@docker ~]# docker rm -f web
[root@docker ~]# docker run -itd --rm --name web -p 80:80 \
-v /root/conf:/usr/local/nginx/conf \
-v /var/webroot:/usr/local/nginx/html myos:nginx
# 访问验证
[root@docker ~]# curl http://192.168.1.31/info.php
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.22.1</center>
</body>
</html>
16.容器网络通信
bridge
host
容器将不会获得一个独立的 Network Namespace, 而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡而是使用宿主机的IP和端口。
container
16.1共享名称空间
# 使用 nginx 的网络名称空间
[root@docker ~]# docker run -itd --rm --name php --network=container:web myos:php-fpm
d5a02b75486ce428f02b25f869f21299387fa4f51a605f478b466656d7c85c6f
[root@docker ~]# curl http://192.168.1.31/info.php
File not found.
[root@docker ~]# docker exec -it web ss -ltun
Netid State Recv-Q Send-Q Local Address:Port
tcp LISTEN 0 128 127.0.0.1:9000
tcp LISTEN 0 128 *:80
# 为 php 增加数据卷
[root@docker ~]# docker rm -f php
[root@docker ~]# docker run -itd --rm --name php --network=container:web \
-v /var/webroot:/usr/local/nginx/html myos:php-fpm
[root@docker ~]# curl http://192.168.1.31/info.php
<pre>
Array
(
[REMOTE_ADDR] => 192.168.1.31
[REQUEST_METHOD] => GET
[HTTP_USER_AGENT] => curl/7.61.1
[REQUEST_URI] => /info.php
)
php_host: da7df895c434
1229
17.服务编排与治理
17.1概述
17.2项目管理命令
指令 | 说明 |
up | 创建项目并启动容器 |
ls | 列出可以管理的项目 |
images | 列出项目使用的镜像 |
ps | 显示项目中容器的状态 |
logs | 查看下项目中容器的日志 |
start/stop/restart | 启动项目/停止项目/重启项目 |
down | 删除项目容器及网络 |
17.3容器项目管理
# 创建项目,并启动
[root@docker ~]# docker compose -f docker-compose.yaml up -d
[+] Running 1/2
⠸ Network myweb_default Created 0.4s
✔ Container nginx Started 0.3s
# 查看项目
[root@docker ~]# docker compose ls -a
NAME STATUS CONFIG FILES
myweb running(1) /root/docker-compose.yaml
# 查看项目中的容器状态
[root@docker ~]# docker compose -p myweb ps
NAME IMAGE COMMAND SERVICE PORTS
nginx myos:nginx "nginx -g 'daemon…" nginxsvc 80/tcp
# 查看项目使用的镜像
[root@docker ~]# docker compose -p myweb images
CONTAINER REPOSITORY TAG IMAGE ID SIZE
nginx myos nginx 10dc658da2fe 274MB
# 查看项目中容器的日志
[root@docker ~]# docker compose -p myweb logs
nginx | 2023/02/13 13:55:39 [error] 7#0: *1 open() ......
# 启动、停止、重启项目
[root@docker ~]# docker compose -p myweb stop
[+] Stopping 1/1
✔ Container nginx Stopped 0.1s
[root@docker ~]# docker compose -p myweb start
[+] Running 1/1
✔ Container nginx Started 0.3s
[root@docker ~]# docker compose -p myweb restart
[+] Restarting 1/1
✔ Container nginx Started 0.3s
# 删除项目
[root@docker ~]# docker compose -p myweb down
[+] Running 2/1
✔ Container nginx Removed 0.1s
✔ Network myweb_default Removed 0.1s
17.4compose 语法
指令 | 说明 |
networks | 配置容器连接的网络 |
container_name | 指定容器名称 |
depends_on | 解决容器的依赖、启动先后的问题 |
command | 覆盖容器启动后默认执行的命令 |
environment | 设置环境变量 |
image | 指定为镜像名称或镜像 ID |
network_mode | 设置网络模式 |
restart | 容器保护策略[always、no、on-failure] |
ports | 暴露端口信息 |
volumes | 数据卷,支持 [volume、bind、tmpfs、npipe] |
17.5容器服务编排
[root@docker ~]# vim docker-compose.yaml
name: myweb
version: "3"
services:
nginxsvc:
container_name: nginx
image: myos:nginx
restart: always
volumes:
- type: bind
source: /root/conf/nginx.conf
target: /usr/local/nginx/conf/nginx.conf
- type: bind
source: /var/webroot
target: /usr/local/nginx/html
network_mode: bridge
ports:
- 80:80
environment:
- "TZ=Asia/Shanghai"
php-fpm:
container_name: php-fpm
image: myos:php-fpm
restart: always
l
depends_on:
- nginxsvc
network_mode: "container:nginx"
# 创建,并启动项目
[root@docker ~]# docker rm -f $(docker ps -aq)
[root@docker ~]# docker compose -f docker-compose.yaml up -d
[+] Running 2/2
⠿ Container nginx Started 0.3s
⠿ Container php-fpm Started 0.3s
# 查看项目
[root@docker ~]# docker compose ls -a
NAME STATUS CONFIG FILES
myweb running(2) /root/docker-compose.yaml
# 查看容器状态,验证服务
[root@docker ~]# docker compose -p myweb ps
NAME COMMAND SERVICE STATUS
nginx "nginx -g 'daemon of..." nginx running ......
php-fpm "php-fpm --nodaemoni..." php-fpm running ......
# 访问 php 页面验证
[root@docker ~]# curl -s http://127.0.0.1/info.php
<pre>
Array
(
[REMOTE_ADDR] => 172.17.0.1
[REQUEST_METHOD] => GET
[HTTP_USER_AGENT] => curl/7.61.1
[REQUEST_URI] => /info.php
)
php_host: 7e037978c775
1229
17.6嵌入式脚本
# 拓展提高
[root@docker ~]# vim docker-script.yaml
name: mycmd
version: "3"
services:
shell:
container_name: mycmd
image: myos:8.5
command:
- sh
- -c
- |
for i in {1..9}
do
sleep 1
echo "${HOSTNAME} && $${HOSTNAME}"
done
[root@docker ~]# docker compose -f docker-script.yaml up -d
[root@docker ~]# docker compose ls -a
NAME STATUS CONFIG FILES
mycmd running(1) /root/docker-script.yaml
[root@docker ~]# docker compose -p mycmd logs
mycmd | docker-0001 && af878f933612
mycmd | docker-0001 && af878f933612
mycmd | docker-0001 && af878f933612
18.harbor 仓库
18.1安装部署 docker
[root@harbor ~]# vim /etc/hosts
192.168.1.30 harbor
# 安装部署 docker 及 compose 组件
[root@harbor ~]# dnf install -y docker-ce
[root@harbor ~]# systemctl enable --now docker
18.2创建 https 证书
# 导入 harbor 项目镜像
[root@harbor ~]# tar -zxf harbor-v2.9.2.tgz -C /usr/local/
[root@harbor ~]# cd /usr/local/harbor
[root@harbor harbor]# docker load -i harbor.v2.9.2.tar.gz
# 创建 https 证书
[root@harbor harbor]# mkdir tls
[root@harbor harbor]# openssl genrsa -out tls/cert.key 2048
[root@harbor harbor]# openssl req -new -x509 -days 3650 \
-key tls/cert.key -out tls/cert.crt \
-subj "/C=CN/ST=BJ/L=BJ/O=Tedu/OU=NSD/CN=harbor"
18.3创建并启动项目
# 修改配置文件
[root@harbor harbor]# cp harbor.yml.tmpl harbor.yml
[root@harbor harbor]# vim harbor.yml
05: hostname: harbor
08: # http:
10: # port: 80
17: certificate: /usr/local/harbor/tls/cert.crt
18: private_key: /usr/local/harbor/tls/cert.key
36: harbor_admin_password: <登录密码>
# 预安装环境检查,生成项目文件
[root@harbor harbor]# /usr/local/harbor/prepare
# 创建并启动项目
[root@harbor harbor]# docker compose -f docker-compose.yml up -d
# 添加开机自启动
[root@harbor harbor]# chmod 0755 /etc/rc.d/rc.local
[root@harbor harbor]# echo "/usr/bin/docker compose -p harbor start" >>/etc/rc.d/rc.local
18.4查看验证项目
# 查看项目
[root@harbor ~]# docker compose ls -a
NAME STATUS CONFIG FILES
harbor running(9) /usr/local/harbor/docker-compose.yml
# 查看容器状态
[root@harbor ~]# docker compose -p harbor ps
NAME COMMAND SERVICE STATUS
harbor-core "/harbor/entrypoint.…" core running (healthy)
harbor-db "/docker-entrypoint.…" postgresql running (healthy)
harbor-jobservice "/harbor/entrypoint.…" jobservice running (healthy)
harbor-log "/bin/sh -c /usr/loc…" log running (healthy)
harbor-portal "nginx -g 'daemon of…" portal running (healthy)
nginx "nginx -g 'daemon of…" proxy running (healthy)
redis "redis-server /etc/r…" redis running (healthy)
registry "/home/harbor/entryp…" registry running (healthy)
registryctl "/home/harbor/start.…" registryctl running (healthy)
18.5harbor 管理
容器管理命令 | 说明 |
docker login | 登录私有镜像仓库 |
docker logout | 退出登录 |
18.5.1登录私有仓库
# 添加主机配置
[root@docker ~]# vim /etc/hosts
192.168.1.30 harbor
# 添加私有仓库配置
[root@docker ~]# vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://harbor:443", "其他镜像仓库"],
"insecure-registries":["harbor:443", "其他镜像仓库"]
}
[root@docker ~]# systemctl restart docker
# 登录 harbor 仓库
[root@docker ~]# docker login harbor:443
Username: <登录用户>
Password: <登录密码>
... ...
Login Succeeded
# 认证信息记录文件
[root@docker ~]# cat /root/.docker/config.json
{
"auths": {
"harbor:443": {
"auth": "bHVjazoqKioqKioqKg=="
}
}
}
# 退出登录
[root@docker ~]# docker logout harbor:443
Removing login credentials for harbor:443
18.5.2上传镜像
# 设置标签
[root@docker ~]# docker tag myos:httpd harbor:443/private/httpd:latest
# 没有登录上传失败
[root@docker ~]# docker push harbor:443/private/httpd:latest
65dbea0a4b39: Preparing
unauthorized: unauthorized to access repository ......
# 登录成功后才可以上传
[root@docker ~]# docker login harbor:443
Username: <登录用户>
Password: <登录密码>
Login Succeeded
# 上传成功
[root@docker ~]# docker push harbor:443/private/httpd:latest
The push refers to repository [harbor:443/private/httpd]
......
# 上传镜像到 library 项目
[root@docker ~]# docker tag myos:latest harbor:443/library/myos:latest
# 没有权限上传失败
[root@docker ~]# docker push harbor:443/library/myos:latest
The push refers to repository [harbor:443/library/myos]
65dbea0a4b39: Preparing
unauthorized: unauthorized to access repository:
......
# 赋权后重新上传镜像
[root@docker ~]# docker push harbor:443/library/myos:latest
The push refers to repository [harbor:443/library/myos]
......
19.docker高阶实战
19.1安装 mysql主从复制
新建主服务器容器实例3307,新建从服务器容器实例3308。主服务器容器同步数据到 从服务器容器
1.新建主服务器容器实例 3307
docker run -p 3307:3306 --name mysql-master \
-v /yzg/mydata/mysql-master/log:/var/log/mysql \
-v /yzg/mydata/mysql-master/data:/var/lib/mysql \
-v /yzg/mydata/mysql-master/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=101
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能
log-bin=mall-mysql-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
docker restart mysql-master
4.进入主服务器容器和mysql
docker exec -it mysql-master /bin/bash
mysql -uroot -p # 密码root
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
# slave是用户,后面创建主从关系时使用过
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%'; # 授权
docker run -p 3308:3306 --name mysql-slave \
-v /yzg/mydata/mysql-slave/log:/var/log/mysql \
-v /yzg/mydata/mysql-slave/data:/var/lib/mysql \
-v /yzg/mydata/mysql-slave/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=102
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
log-bin=mall-mysql-slave1-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
## relay_log配置中继日志
relay_log=mall-mysql-relay-bin
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## slave设置为只读(具有super权限的用户除外)
read_only=1
docker restart mysql-slave
9.在主数据库中查看主从复制
show master status;
在从数据库中配置主从复制。 要在从数据库中执行
change master to master_host='192.168.200.132', master_user='slave',
master_password='123456',
master_port=3307,
master_log_file='mall-mysql-bin.000001',
master_log_pos=617, master_connect_retry=30;
参数详解:
master_host:主数据库的IP地址【虚拟机的ip】;
master_port:主数据库的运行端口;
master_user:在主数据库创建的用于同步数据的用户账号;
master_password:在主数据库创建的用于同步数据的用户密码;
master_log_file:指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取File参数;
master_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position参数;
master_connect_retry:连接失败重试的时间间隔,单位为秒。
11.在从数据库中查询主从关系
show slave status \G;
测试:主机创建数据库,建表,查看从机的数据是否同步
19.2安装 Redis 集群
- 先关闭防火墙 + 启动 Docker 服务
- 分别启动六个redis 实例
docker run -d --name redis-node-1 --net host --privileged=true -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381
docker run -d --name redis-node-2 --net host --privileged=true -v /data/redis/share/redis-node-2:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382
docker run -d --name redis-node-3 --net host --privileged=true -v /data/redis/share/redis-node-3:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383
docker run -d --name redis-node-4 --net host --privileged=true -v /data/redis/share/redis-node-4:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6384
docker run -d --name redis-node-5 --net host --privileged=true -v /data/redis/share/redis-node-5:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6385
docker run -d --name redis-node-6 --net host --privileged=true -v /data/redis/share/redis-node-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386
参数详解:
docker run -d: 创建容器实例,并后台运行
–net host : 使用宿主机的IP和端口,默认
–privileged=true : 获取宿主机root用户权限
-v /data/redis/share/redis-node-6:/data :容器卷,宿主机地址:docker内部地址
redis:6.0.8 : redis 镜像版本号
–cluster-enabled yes : 开启redis集群
–appendonly yes : 开启持久化
–port 6386 :redis 端口号
3.进入 redis-node-1 容器,创建主从关系
redis-cli --cluster create 192.168.200.132:6381 192.168.200.132:6382 192.168.200.132:6383 192.168.200.132:6384 192.168.200.132:6385 192.168.200.132:6386 --cluster-replicas 1
redis-cli -p 6381 # 连接 redis
cluster nodes # 查询集群情况
和redis章节讲的一样,默认会将前三个节点设为主节点,后三个为从节点
数据读写存储
当我们在 6381 中存储数据时,发现有的 key 存不进去,有的 key 却能存进去。
解决方法:
使用 集群模式 启动redis
19.2.1主从扩容案例
docker run -d --name redis-node-7 --net host --privileged=true -v /data/redis/share/redis-node-7:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6387
docker run -d --name redis-node-8 --net host --privileged=true -v /data/redis/share/redis-node-8:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6388
# 进入 6387 容器内部
docker exec -it redis-node-7 bash
# 将 6387 增加到集群
redis-cli --cluster add-node 192.168.200.132:6387 192.168.200.132:6381
# 6381 就是原来集群节点里面的领路人,相当于6387拜拜6381的码头从而找到组织加入集群
redis-cli --cluster check 192.168.200.132:6381
4.重新分配槽号
命令:redis-cli --cluster reshard IP地址:端口号
redis-cli --cluster reshard 192.168.200.132:6381
重新分配的规则,并不是所有的槽点重新分配,而是将之前的三台主机匀出来一点分给 新节点, 因为重新分配成本太高
命令:redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID
redis-cli --cluster add-node 192.168.200.132:6388 192.168.200.132:6387 --cluster-slave --cluster-master-id 5bbd8a7f459a72f28b94eae468835b56c6f4fd75
# -------这个是6387的 ID ,按照自己实际情况
删掉 6387、6388 节点完成缩容,考虑俩个问题:
先删除哪个节点?
删除后节点槽号又是如何分配的?
# 命令:redis-cli --cluster del-node ip:从机端口 从机6388节点ID
redis-cli --cluster del-node 192.168.200.132:6388 e8377c7fc4170ba19ef5f410d0c67b003ebac35d
redis-cli --cluster reshard 192.168.200.132:6381
不是只能分配给一个 节点,可以多执行几次 reshard 命令,分配多个节点不同的槽位,这里只是为了方便
6381 分配了 8292 个槽位
4.删除 6387
redis-cli --cluster del-node 192.168.200.132:6387 5bbd8a7f459a72f28b94eae468835b56c6f4fd75