前言
Mysql容器化安装
下载
以前是apt来安装
现在用容器来
去hub.docker.com找一下mysql的镜像
这个就是具体的命令
docker run --name mysql -e MYSQL_ROOT_PASSWORD=xxxxxx -p 8200:3306 -d mysql:5.7
这个就是设定密码和端口号了
进入mysql
docker ps
可以看到mysql在正常运行
docker exec -it mysql bash
这样就可以进入了
输入这个之后马上就要登录
但是是让我们自己主动去登录
mysql -u root -p
然后就是输入密码
这样我们就成功登录了mysql了
可以写sql语句了
show database;
create database test_db;
show database;
use test_db;
create table test_user(name varchar(50),age int);
insert into test_user values(‘bit’,‘99’);
select * from test_user;
输入exit就是退出的mysql
再次输入exit就是退出的容器
就算退出了容器还是在运行的
因为是后台运行的
exec命令是在正在运行的容器内启动一个新的进程,当你使用exit退出这个通过exec启动的进程时,只会结束该进程,而不会影响容器本身的运行状态。容器会继续保持后台运行,除非容器内的主进程出现故障或被手动停止、删除容器等操作,才会导致容器停止运行。
用可视化工具,远程操控mysql
直接这样就可以链接了
注意要开放端口哦
这样就可以链接了
这样就真的成功了
Redis容器化安装
Redis 出现的原因
在Web应用发展的初期,那时关系型数据库受到了较为广泛的关注和应用,原因是因
为那时候Web站点基本上访问和并发不高、交互也较少。而在后来,随着访问量的提
升,使用关系型数据库的Web站点多多少少都开始在性能上出现了一些瓶颈,而瓶颈
的源头一般是在磁盘的I/O上。而随着互联网技术的进一步发展,各种类型的应用层
出不穷,这导致在当今云计算、大数据盛行的时代,对性能有了更多的需求,主要体
现在以下几个方面:
低延迟的读写速度:应用快速地反应能极大地提升用户的满意度
支撑海量的数据和流量:对于搜索这样大型应用而言,需要利用PB级别的数据和
能应对百万级的流量
为了克服这一问题,NoSQL应运而生,它同时具备了高性能、可扩展性强、高可用等
优点,受到广泛开发人员和仓库管理人员的青睐
NoSQL就是非关系型数据库,解决海量数据并发的问题
Redis 是什么
Redis 全称 Remote Dictionary Server,中文名为远程字典服务器。
Redis 是现在最受欢迎的 NoSQL数据库之一,Redis是一个使用 ANSI C编写的开源、
包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库,其具备
如下特性:
• 基于内存运行,性能高效
• 支持分布式,理论上可以无限扩展
• key-value存储系统
• 开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久
化的日志型、Key-Value数据库,并提供多种语言的API
就是缓存的键值对数据库,只记住经常使用的
基于内存运行—》很快
Redis 的应用场景
几乎所有的大厂都在使用Redis。Redis 提供了多种数据类型,String类型、哈希类型、
列表类型、集合类型和顺序集合类型,借助这些类型可以方便的实现多种应用,如缓
存系统(“热点”数据:高频读、低频写)、计数器、消息队列系统、实时排行榜、社交
网络
Redis 容器创建
直接去官网搜索
docker run --name redis -d -p 8300:6379 redis:7
进入容器使用
docker exec -it redis bash
redis-cl
输入这个,默认链接的就是本机的端口6379
set sellcount 1
这个就是设置一个键值对的意思
get sellcount
就是根据键获取值
输入两个exut就可以退出redis和容器了
可视化工具远程链接
我们先下载可视化工具
redis可视化工具
安装完之后,直接进去,左上角new一个新的链接
默认是没有密码和用户名的
然后点击这个
显示出这个说明就连接成功了
sellcount也是可以查看值的
最下边输入代码
set sellcount 100
或者在命令行那里get sellcount也是可以的
C++容器制作
下载操作系统镜像centos
docker pull ubuntu:22.04
docker run --name mygcc -it ubuntu:22.04 bash
下载gcc
中科大源
在这个里面配置gcc源站
配置国内镜像源加速
sed -i ‘s@//.*archive.ubuntu.com@//mirrors.ustc.edu.cn@g’ /etc/apt/sources.list
安装gcc vim
apt update
apt install gcc vim -y
然后就是编辑源代码了
vi demo.c
gcc demo.c -o app
./app
就可以运行了
SpringBoot容器制作
创建springboot项目
就是创建一个Springboot的程序
我们直接用以前的就可以了
找到jar包就可以了
制作容器
docker run -p 8880:8080 --name myjava -it ubuntu:22.04 bash
国内源加速jdk下载
安装jdk,我们采用镜像源加速
sed -i ‘s@//.*archive.ubuntu.com@//mirrors.ustc.edu.cn@g’ /etc/apt/sources.list
更新
apt update
apt install -y openjdk-8-jdk
apt list | grep jdk
看一下有哪些jdk版本
然后就是搞目录
传输jar包就可以了
传输文件我们可以点击这个按钮
看的出来左边是windows,右边是linux
这样拖动就可以成功了
但是这样拷贝到的地方不是容器里面,只是宿主机
docker cp ./xxxxxxx.jar myjava:/
这样就可以拷贝到容器里面了
java -jar xxxx.jar
这样就可以启动了
反正和以前没什么区别
区别就是跑到容器里面了
我们还可以直接找jdk的镜像
如果在容器里面ctrl+c
就直接就退出容器了
我们可以原先镜像后台运行的
先制作出这个镜像,有jar包的
然后再-d后台运行
现在还不能后台运行的同时保证java项目能够执行
容器资源更新
内存资源更新
docker pull java:8
我们这个是直接使用的jdk的镜像
意思就是如果我们的jar包没有使用数据库的话,直接就可以用这个镜像来启动jar包了
docker run -it --name myjava2 java:8 bash
然后我们把jar包拷贝到这个里面去
直接在这个容器里面
java -jar xxxxx.jar
在另一个shell中
docker stats myjava2
docker update -m 10m --memory-swap 10m myjava2
指定内存为10m,–memory-swap是交换内存
–memory-swa与-m是一样的话,就只能使用物理内存,不能使用交换内存
但是更新失败了
因为这个jar包太大了
docker update -m 200m --memory-swap 200m myjava2
这样就可以了
把应用停掉
然后把内存改小
看容器能不能起来
在容器里面 ctrl+c
然后另一个shell
docker update -m 10m --memory-swap 10m myjava2
在启动
java -jar xxxxx.jar
直接就失败了,因为太小了
cpu资源更新
docker run -it --name myjava3 java:8 bash
然后我们执行一个命令,打满cpu
另一个shell
docker stats myjava3
这个就是不停做文件的转换,但是不消耗io,因为null是空的
所以这个是消耗了cpu的,在容器中执行
for i in seq 1 $(cat /proc/cpuinfo |grep "physical id" |wc -l)
do
dd if=/dev/zero of=/dev/null &
done
这样就打满了
然后我们来限制容器占用cpu的比例
再来一个shell
docker update --help
这个可以看参数
占用的比例就是,–cpu-quota与–cpu-period的比
–cpu-quota是分子,–cpu-period是分母,默认值是100000
docker update --cpu-period 100000 --cpu-quota 10000 myjava3
这样就是10%占用的cpu
其实内存和cpu的docker run的时候就可以确定了
常见问题
docker create、docker start 和 docker run 有什么区别?
docker create 命令从 Docker 映像创建一个全新的容器。但是,它不会立即运行它。
docker start 命令将启动任何已停止的容器。如果使用 docker create命令创建容器,
则可以使用此命令启动它。
docker run 命令是创建和启动的组合,因为它创建了一个新容器并立即启动它。实际
上,如果docker run命令在您的系统上找不到上述映像,它可以从 Docker Hub 中提
取映像。
docker import 和 docker load 有什么区别?
想要了解docker load与docker import 命令的区别,还必须知道docker save
与docker export 命令:
• docker save images_name:将一个镜像导出为文件,再使用docker load命
令将文件导入为一个镜像,会保存该镜像的的所有历史记录。比docker export命令
导出的文件大,很好理解,因为会保存镜像的所有历史记录。
• docker export container_id:将一个容器导出为文件,再使用docker
import 命令将容器导入成为一个新的镜像,但是相比docker save命令,容器文件
会丢失所有元数据和历史记录,仅保存容器当时的状态,相当于虚拟机快照。
既可以使用docker load命令来导入镜像库存储文件到本地镜像库,也可以使用
docker import 命令来导入一个容器快照到本地镜像库。
两者的区别在于容器快照将会丢弃所有的历史记录和元数据信息,而镜像存储文件将
保存完整记录,体积也会更大。
docker rm & docker rmi & docker prune 的差异?
docker rm : 删除一个或多个容器
docker rmi : 删除一个或多个镜像
docker prune: 用来删除不再使用的 docker 对象
Docker Volume(存储卷)
什么是存储卷?
存储卷就是将宿主机的本地文件系统中存在的某个目录直接与容器内部的文件系统上
的某一目录建立绑定关系。这就意味着,当我们在容器中的这个目录下写入数据时,
容器会将其内容直接写入到宿主机上与此容器建立了绑定关系的目录。
在宿主机上的这个与容器形成绑定关系的目录被称作存储卷。卷的本质是文件或者目
录,它可以绕过默认的联合文件系统,直接以文件或目录的形式存在于宿主机上。
宿主机的/data/web目录与容器中的/container/data/web目录绑定关系,然后容器中的
进程向这个目录中写数据时,是直接写在宿主机的目录上的,绕过容器文件系统与宿
主机的文件系统建立关联关系,使得可以在宿主机和容器内共享数据库内容,让容器
直接访问宿主机中的内容,也可以宿主机向容器写入内容,容器和宿主机的数据读写
是同步的。
存储卷就是容器和宿主机目录之间建立了一个绑定关系
容器和宿主机读写同步,本质指向同一个位置
容器销毁了,存储卷里面的数据不会变
为什么需要存储卷?
数据丢失问题
容器按照业务类型,总体可以分为两类:
• 无状态的(数据不需要被持久化)
• 有状态的(数据需要被持久化)
显然,容器更擅长无状态应用。因为未持久化数据的容器根目录的生命周期与容器的
生命周期一样,容器文件系统的本质是在镜像层上面创建的读写层,运行中的容器对
任何文件的修改都存在于该读写层,当容器被删除时,容器中的读写层也会随之消失。
虽然容器希望所有的业务都尽量保持无状态,这样容器就可以开箱即用,并且可以任
意调度,但实际业务总是有各种需要数据持久化的场景,比如 MySQL、Kafka 等有状
态的业务。因此为了解决有状态业务的需求,Docker 提出了卷(Volume)的概念。
2.
性能问题
UnionFS对于修改删除等,一般效率非常低,如果对一于I/O要求比较高的应用,如
redis 在实现持化存储时,是在底层存储时的性能要求比较高。
3.
宿主机和容器互访不方便
宿主机访问容器,或者容器访问要通过docker cp来完成,应用很难操作
4.
容器和容器共享不方便 ,只能用宿主机作为媒介,用docker cp
容器删除了,数据也就丢失了 ,所以要存储卷,相当于u盘,和windows文件系统,存储卷就是u盘
第二就是存储卷直接作用于宿主机 ,性能高,绕过了楼层
存储卷分类
存储卷就是一个挂载的类型,比如插了一个u盘,就会自动增加一个盘—》有了目录
目前Docker提供了三种方式将数据从宿主机挂载到容器中
• volume docker管理卷,默认映射到宿主机的**/var/lib/docker/volumes 目录**
下,只需要在容器内指定容器的挂载点是什么,而被绑定宿主机下的那个目录,是由
容器引擎daemon自行创建一个空的目录,或者使用一个已经存在的目录,与存储卷
建立存储关系,这种方式极大解脱用户在使用卷时的耦合关系,缺陷是用户无法指定
那些使用目录,临时存储比较适合;
容器和宿主机目录之间建立了一个绑定关系,但是宿主机的目录不用管,管好容器的目录就可以了,宿主机的目录的管理由docker引擎自己创建
就是相当于插了一个U盘,自动弹出了一个盘符,系统自己创建的盘符
缺点就是无法精准的控制哪个目录给谁用
• bind mount绑定数据卷,映射到宿主机指定路径下,在宿主机上的路径要人工的
指定一个特定的路径,在容器中也需要指定一个特定的路径,两个已知的路径建立关
联关系
宿主机的目录由用户创建了,不是由docker引擎来创建了
能精准的控制哪个目录给谁用,这个使用多
• tmpfs mount临时数据卷,映射到于宿主机内存中,一旦容器停止运行,tmpfs
mounts 会被移除,数据就会丢失,用于高性能的临时数据存储。
宿主机不在使用文件系统,使用的是内存 ,容器的目录绑定到内存上
优点就是速度快,安全,内存上看不见
缺点就是容器停了,数据就又丢失了
管理卷Volume
创建卷
了解即可,用得少
方式一:Volume命令操作
命令清单如下
docker volume inspect
显示存储卷详细信息
docker volume ls
docker volume list
列出存储卷
docker volume prune
清理所有无用数据卷
docker volume rm
删除卷,使用中的无法删除
docker_volume_create_421">docker volume create
可以生成一个随机名字的卷
功能
○ 创建存储卷
• 语法
docker volume create [OPTIONS] [VOLUME]
• 关键参数
○ -d, --driver:指定驱动,默认是local
○ --label:指定元数据 --》描述数据的·数据,就是描述卷的数据
docker volume create
这样创建的就是一个匿名卷,就是一个随机的名字
docker volume ls
就可以查看创建的卷了
docker volume inspect 卷的名称
这个就可以查看某个卷的具体信息了
我们就可以看到具体挂载的地址了,就是卷的根目录
然后就是这个卷的目录是空的
以前没有容器往里面写入东西·
docker volume create myvoltest1
这样创建的就是指定名字的了
docker volume ls
docker volume inspect myvoltest1
这个目录下面还是空的
docker volume create --label MYTEST=1 myvoltest2
docker volume inspect myvoltest2
–label MYTEST=1 说明是加上我们想要描述的数据 是什么
docker_volume_inspect_466">docker volume inspect
功能
○ 查看卷详细信息
• 语法
docker volume inspect [OPTIONS] VOLUME [VOLUME…]
我们这个可以一次查看多个存储卷
• 关键参数
○ -f:指定相应个格式,如json
docker volume create myvoltest3
docker volume create myvoltest4
docker volume inspect myvoltest3 myvoltest4
docker_volume_ls_482">docker volume ls
功能
○ 列出卷
• 语法
Shell
docker volume ls [OPTIONS]
• 关键参数
○ --format:指定相应个格式,如json,table
○ --filter,-f: 过滤
○ -q: 仅显示名称
docker volume create --label MYTEST2=1 myvoltest5
docker volume ls
docker volume ls --format json
docker volume ls -f label=MYTEST2
docker volume ls -q
docker_volume_rm_502">docker volume rm
功能
○ 删除卷,需要容器不使用。
• 语法
docker volume rm [OPTIONS] VOLUME [VOLUME…]
• 关键参数
○ -f,–force:强制删除
docker volume create myvoltest7
docker volume create myvoltest8
docker inspect myvoltest7
echo “123” > /data/var/lib/docker/volumes/myvoltest7/_data/1.txt
ll /data/var/lib/docker/volumes/myvoltest7/_data/1.txt
docker volume rm myvoltest7 myvoltest8
ll /data/var/lib/docker/volumes/myvoltest7/_data/1.txt
然后就是删除卷之后,对应的目录也不存在了,也被删除了
docker_volume_prune_523">docker volume prune
功能
○ 批量删除不使用的本地卷
• 语法
Shell
docker volume prune [OPTIONS]
• 关键参数
○ --filter:过滤
○ -f, --force :不提示是否删除
我们先来创建一个匿名卷和命名卷
docker volume create myvoltest6
docker volume create
docker volume prune
输入y
我们发现只删除了刚刚创建的匿名卷
发现清理不使用的卷,而且是不使用的匿名卷
方式二:-v或者–mount指定
-v参数
这下就关联容器了
-v 和-mount都可以完成管理卷的创建 -v 参数 ---->管理卷,绑定卷
• 功能:
完成目录映射
• 语法
Shell
docker run -v name:directory[:options] …
• 参数
○ 第一个参数:卷名称
○ 第二个参数:卷映射到容器的目录
○ 第三个参数:选项,如ro表示readonly—》对目录起了保护的作用,就不能修改了,不能删除首页了
docker images nginx
docker run -d --name myvolnginx1 -v volnginx1:/usr/share/nginx/html/ nginx:1.224.0
就是把这个容器的目录/usr/share/nginx/映射到卷
docker ps
docker volume ls
docker inspect volnginx1
ll /data/var/lib/docker/volums/volnginx1/_data
默认是以var开头的
我们发现,我们用-v指定一个卷的时候,会把我们容器里面的内容拷贝到我们的宿主机
我们进入这个容器,看能不能把这个首页删除
docker exec -it myvolnginx1 bash
cd /usr/share/nginx/html
ll
rm index.html
exit
ll /data/var/lib/docker/volums/volnginx1/_data
我们发现这个 这个目录下的首页也被删除了
docker run -d --name myvolnginx2 -v volnginx2:/usr/share/nginx/html/:ro nginx:1.224.0
ro就是指定不能删除目录了
ll /data/var/lib/docker/volums/volnginx2/_data、
这个里面还是有首页的
docker exec -it myvolnginx2 bash
cd /usr/share/nginx/html
ll
rm index.html
直接就是删除失败了
–mount 参数
功能:
完成目录映射 ,创建卷–》管理卷,绑定卷,临时卷(bind, volume, or tmpfs )
• 语法
–mount ‘=,=’
• 关键参数
○ type : 类型表示bind, volume, or tmpfs
○ source ,src :对于命名卷,这是卷的名称。对于匿名卷,省略此字段。
○ destination,dst,target:文件或目录挂载在容器中的路径
○ ro,readonly: 只读方式挂载
完成目录映射
docker run -d --name mynginxvol3 --mount ‘src=nginxvol3,dst=/usr/share/nginx/html’ nginx:1.24.0
/usr/share/nginx/html是容器的目录,宿主机的目录是不能变的
nginxvol3就是卷
docker volume inspect nginxvol3
ll /data/var/lib/docker/volums/nginxvol3/_data
可以发现这个里面还是有值的
docker run -d --name mynginxvol4 --mount ‘dst=/usr/share/nginx/html’ nginx:1.24.0
这样创建的就是匿名卷了
docker volume ls
docker inspect mynginxvol4
这里就可以查看容器对应的匿名卷了
方式三:Dockerfile匿名卷
通过Dockerfile的VOLUME可以创建docker管理卷。这个我们后续在Dockerfile
中详细讲解。
我们也可以通过dockerfile的 VOLUME指令在镜像中创建Data Volume,这样只要
通过该镜像创建的容器都会存在挂载点,但值得注意的是通过 VOLUME指令创建的挂
载点,无法指定主机上对应的目录,而是由docker随机生成的。
操作案例
Docker命令创建管理卷
宿主机做了修改,也会同步到容器里面
docker volume create test1
docker volume inspect test1
ll /data/var/lib/docker/volums/test1/_data
这个就是先创建一个管理卷
然后就是创建一个容器
docker run -d --name mynginx1 -p 8045:80 -v test1:/usr/share/nginx/html mynginx:1.24.0
这样就把卷和我们的容器的一个目录进行了绑定了
ll /data/var/lib/docker/volums/test1/_data
这样这个宿主机目录里面就有内容了
docke inspect mynginx1
这里还可以看到我们宿主机的目录,和容器的目录
然后我们在宿主机上修改首页,看容器里面会不会变化
cd /data/var/lib/docker/volums/test1/_data
我们修改一下index.html
然后我们进去容器
docker exec -it mynginx1 bash
cd /usr/share/nginx/html
cat index.html
发现这里面也是动态发生变化的·
Docker -v 创建管理卷
指定了ro,容器就不能修改了,但是宿主机可以修改,所以ro保护的是容器的权限
docker run -d --name mynginx2 -v test2:/usr/share/nginx/html/:ro -p:8046:80 nginx:1.224.0
没有卷test2的话,就自动创建
docker ps
docer volume ls
docker inspect test2
ll /data/var/lib/docker/volums/test2/_data
也是有内容的
现在进入到容器里面对首页进行修改
docker exec -it mynginx2 bash
docker exec -it mynginx1 bash
cd /usr/share/nginx/html
cat index.html
echo “hello” > index.html
我们发现无法修改
exit
现在进入卷的目录进行修改
cd /data/var/lib/docker/volums/test2/_data
vi index.html
这个是可以修改的,而且会同步容器的目录,也是会对应修改的,意思就是这个ro本质限制的是容器
Docker mount创建管理卷
验证它创建的卷能不能文件同步
卷的目录绑定到容器首页所在的目录
docker run -d --name mynginx3 -p 8047:80 --mount src=test3,dst=/usr/share/nginx/html/ nginx:1.24.0
docer volume inspect test3
ll /data/var/lib/docker/volums/test3/_data
这个里面也是有内容的
cd /data/var/lib/docker/volums/test3/_data
vi index.html
然后也是会同步到容器里面的
docker exec -it mynginx3 bash
cd /usr/share/nginx/html
cat index.html
然后这个也是会改变的
Docker 卷生命周期
容器被删除了,卷也不会被删除
docker run -d -v test4:/usr/share/nginx/html --name mynginx4 -p 8049:80 nginx:1.24.0
docker inspect mynginx4
我们看容器也可以看到对应的挂载点
ll /data/var/lib/docker/volums/test4/_data
docker stop mynginx4
docker rm mynginx4
docker ps -a | grep mynginx4
ll /data/var/lib/docker/volums/test4/_data
我们可以发现这个卷里面的内容还是存在的
docker volume rm test4
ll /data/var/lib/docker/volums/test4/_data
这样卷就被删除了
Docker 卷共享
启动多个容器,首页都绑定到同一个卷上,一个宿主机上卷修改,引起多个容器的刷新修改
docker run -d -v test4:/usr/share/nginx/html --name mynginx51 -p 8051:80 nginx:1.24.0
docker run -d -v test4:/usr/share/nginx/html --name mynginx52 -p 8052:80 nginx:1.24.0
docker run -d -v test4:/usr/share/nginx/html --name mynginx53 -p 8053:80 nginx:1.24.0
这样多个容器都绑定到同一个卷了
ll /data/var/lib/docker/volums/test4/_data
我们发现有文件的,但是还是只有这两个,因为不同容器的这个文件都是一样的,名字也是一样的
所以就是同一个文件,三个容器都是绑定到了同一个位置,一处修改,多处共用
vi index.html
这样修改的,三个容器里面的首页内容都会修改了
docker exec -it mynginx51 bash
cd /usr/share/nginx/html
cat index.html