首先了解一下doker和k8s的故事:
那么容器对比虚拟机有哪些优势:
什么是云原生:
云原生是一种构建和运行云端应用程序的方法论。
云原生还提倡使用容器技术(如Docker)来打包和分发应用程序,使得应用程序的运行环境更加独立和可移植。同时,云原生还倡导采用微服务架构,将应用程序分解成一系列小型、独立的服务组件,每个组件负责一个特定的功能。这样可以实现模块化开发,方便应对复杂的业务需求和快速迭代。
综上所述,云原生是一种以云计算为基础,利用虚拟化、容器化和微服务架构的方式,更高效、更灵活地构建和运行应用程序(上层应用)。它可以让你专注于应用开发和业务创新,而不需要关注底层基础设施的细节。
什么是容器:
容器技术是一种轻量级的虚拟化技术,它允许将应用程序和其依赖项打包到一个独立的、可移植的运行环境中,称为容器。这些容器可以在任何支持容器化技术的主机上运行,而不受底层操作系统和硬件的影响。
容器技术是一种轻量级的虚拟化技术,它允许将应用程序和其依赖项打包到一个独立的、可移植的运行环境中,称为容器。这些容器可以在任何支持容器化技术的主机上运行,而不受底层操作系统和硬件的影响。
容器技术的优势:
简化部署:容器提供了一个一致的运行环境,可以轻松地在不同的主机或云平台上部署应用程序。
快速启动:容器可以在几秒钟内启动,相比之下,传统的虚拟机需要更长的启动时间。
可移植性:容器可以在不同的环境中移植和运行,无需重写代码或重新配置应用程序。
资源隔离:容器提供了资源隔离,使得不同的容器可以在同一台主机上运行,而互不干扰。
弹性伸缩:容器技术可以根据需求自动扩展或收缩容器实例,以适应负载的变化。
一些流行的容器化技术包括Docker和Kubernetes=k8s,podman,buildah。Docker提供了一种简单的方法来创建、打包和分享容器镜像,而Kubernetes是一个容器编排平台,用于自动化和管理大规模的容器部署。这些技术的出现,使得容器化应用程序的开发、部署和管理变得更加简单和高效。
容器和虚拟化的区别:
首先我们来安装docker:
CentOS stream 8
2U8G100G NAT模式 保证能上外网
Docker分为两个版本:ee 企业版 需要付费 ce 开源社区版 免费使用
安装基础软件包:
[root@ljh~]# mount /dev/sr0 /mnt/
mount:/mnt:WARNING:device write-protected, mounted read-only.
[root@ljh~]# cd /etc/yum.repos.d/
[root@ljhyum.repos.d]# mkdir bak
[root@ljhyum.repos.d]# mv CentOS-Stream-* bak/
[root@ljhyum.repos.d]# vim abc.repo
[root@ljhyum.repos.d]# cat abc.repo
[baseos]
name = baseos
baseurl = file:///mnt/BaseOS
gpgcheck = 0
[app]
name = app
baseurl = file:///mnt/AppStream
gpgcheck = 0
[root@docker yum.repos.d]# yum -y install vim net-tools bash-completion yum-utils
//yum-utils安装后可以帮助我们下载在线的repo
下载docker-ce repo文件
阿里巴巴开源镜像站:https://developer.aliyun.com/mirror/
获取在线仓库:
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@ljhyum.repos.d]# ls
abc.repo bak docker-ce.repo
查看下docker-ce.repo仓库中有哪些docker版本可供选择安装
[root@ljh yum.repos.d]# yum list docker-ce --showduplicate |sort -r
安装一下docker
[root@ljh yum.repos.d]# yum -y install docker-ce //默认安装最新版本
如果需要指定安装docker的版本的话,采用如下命令
[root@ljh yum.repos.d]# yum -y install docker-ce-20.10.24 docker-ce-cli-20.10.24
查看安装的docker的版本
[root@ljh yum.repos.d]# docker -v
Docker version 24.0.5, build ced0996
启动docker服务
[root@ljh yum.repos.d]# systemctl status docker
[root@ljh yum.repos.d]# systemctl start docker
[root@ljh yum.repos.d]# systemctl status docker
[root@ljh yum.repos.d]# systemctl enable docker
docker架构:
镜像和容器是什么关系:
运行什么进程是由镜像决定的
docker镜像管理:
去ucloud拉取镜像,找到ucloud的镜像私有镜像仓库的地址后,开始登录自己的私有镜像仓库。
[root@ljhyum.repos.d]# docker login uhub.service.ucloud.cn/iecloud.ljh
如果是公开的镜像就不需要登录了直接拉取,如果是私有的就需要登录输入用户名和密码就行了。
查看是否有镜像:
[root@ljhyum.repos.d]# docker images
然后直接拉取过来就行了。命令如下,复制粘贴即可。
阿里云仓库镜像的拉取和推送
如何在阿里云的私有仓库中pull和push镜像,方法如下:
https://cr.console.aliyun.com/cn-hangzhou/instance/namespaces
先登录到阿里云镜像库里面,要把镜像推送到阿里云的话记得修改一下镜像的名字格式,然后进行推送。
docker login --username=aliyun2841463476 registry.cn-hangzhou.aliyuncs.com
docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/iecloud1/alpine:[镜像版本号]
docker push registry.cn-hangzhou.aliyuncs.com/iecloud1/alpine:[镜像版本号]
镜像重命名:
[root@ljh~]# docker tag registry.cn-hangzhou.aliyuncs.com/cloudcszx/centos:latest registry.cn-hangzhou.aliyuncs.com/cloudcszx/centos:v1.0
[root@ljh~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.cn-hangzhou.aliyuncs.com/cloudcszx/centos latest 5d0da3dc9764 2 years ago 231MB
registry.cn-hangzhou.aliyuncs.com/cloudcszx/centos v1.0 5d0da3dc9764 2 years ago 231MB
docker rmi+镜像名
注意:镜像重命名时不能镜像名不能用大写字母
镜像的导入和导出:
某个镜像有用,我需要把它拿到另外一个节点上,在另外节点上没有外网或没有内部的镜像仓库的情况下,需要把镜像导出来,拷贝过去之后,再导入。
save和load
[root@docker ~]# docker save nginx:latest mysql:latest wordpress:latest -o wmn.tar
[root@docker ~]# ls
anaconda-ks.cfg wmn.tar
[root@docker ~]# ls
anaconda-ks.cfg wmn.tar
[root@docker ~]#
[root@docker ~]# docker load -i wmn.tar
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
wordpress latest bfcb59709143 3 years ago 550MB
mysql latest 8457e9155715 3 years ago 546MB
nginx latest 298ec0e28760 3 years ago 133MB
=========================================================
将目前的镜像都打包导出到一个压缩包里面去
[root@ljh~]# docker save centos:v1.0 centos:v2.0 centos:v3.0 registry.cn-hangzhou.aliyuncs.com/cloudcszx/centos > /tmp/centosimages.tar
[root@ljh~]# cd /tmp/
ls就可以看见刚刚导出的压缩包。
删除所有的镜像:docker rmi + 镜像名称
再导入压缩包,会自动解压
[root@ljhtmp]# docker load -i centosimages.tar
74ddd0ec08fa:Loading layer [==================================================>] 238.6MB/238.6MB
Loaded image:centos:v1.0
Loaded image:centos:v2.0
Loaded image:centos:v3.0
Loaded image:registry.cn-hangzhou.aliyuncs.com/cloudcszx/centos:latest
脚本批量删除镜像:
[root@ljhtmp]# docker rmi -f $(docker images -q)一键删除所有的镜像
那我们就可以把它写入到脚本里面:
[root@ljhtmp]# cd
[root@ljh~]# vim delimages.sh
[root@ljh~]# cat delimages.sh
#!/bin/bash
docker rmi -f $(docker images -q)
[root@ljh~]# sh delimages.sh 执行这个脚本就行了 记得修改权限 chomd u+x delimages.sh
镜像的分层:
[root@ljh~]# docker history alpine:latest
IMAGE CREATED CREATED BY SIZE COMMENT
324bc02ae123 2 weeks ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 2 weeks ago /bin/sh -c #(nop) ADD file:99093095d62d04215… 7.8MB
docker容器管理:
查询容器:docker ps -a
创建容器:docker run alpine
删除容器:docker rm + ID的第一个字母或数字
添加伪终端-t:[root@ljh ~]# docker run -t alpine
添加交互-i:[root@ljh ~]# docker run -ti alpine
为容器添加持续运行:[root@ljh~]# docker run -ti --restart always alpine
为容器添加后端运行-d:[root@ljh~]# docker run -tid alpine
为容器和容器主机定义名称 --name -h:
docker run -tid --name os1(容器名) -h os1(容器内部主机名) --restart always centos
进入容器登录:
[root@ljh~]# docker exec -ti ID的第一个字母bash
[root@ljh~]# docker exec -ti ID的第一个字母 /bin/sh
为容器自定义名称:(创建容器)
[root@ljh~]# docker run -tid --name os1 --restart always alpine
再登录的话就使用 docker exec -ti os1 /bin/sh
批量删除容器:
[root@ljh~]# docker rm -f $(docker ps -qa)
有时候我们创建一个容器,仅仅是临时使用的,用完即止,用完(退出)直接删除。
创建临时容器:
用完即止,注意,--rm和-d他俩不能见面。
[root@docker ~]# docker run -ti --name os1 --rm centos:latest
当退出容器的时候,容器会自动被删除。不要带-d,不然不生效,-d后台运行与--rm冲突
指定容器的生命周期:
[root@ljh~]# docker run -tid --name os1 alpine sleep 30这里默认是秒
持续每隔1s动态观察
[root@ljh~]# watch -n 1 docker ps -a
容器的关闭:
[root@ljh~]# docker start/stop/restart + ID的第一个数字或字母
查询容器日志定位故障:
先拉取一个MySQL镜像,root@ljh~]# docker pull uhub.service.ucloud.cn/hciecloud/mysql:latest
改个名字,[root@ljh~]# docker tag uhub.service.ucloud.cn/hciecloud/mysql:latest mysql:latest
然后创建MySQL容器,[root@ljh~]# docker run -tid --name db1 --restart always mysql
查询容器日志logs,状态不正常,查看该容器的日志
[root@ljh~]# docker logs db1
2024-08-10 05:08:48+00:00 [Note] [Entrypoint]:Entrypoint script for MySQL Server 9.0.1-1.el9 started.
2024-08-10 05:08:49+00:00 [Note] [Entrypoint]:Switching to dedicated user 'mysql'
2024-08-10 05:08:49+00:00 [Note] [Entrypoint]:Entrypoint script for MySQL Server 9.0.1-1.el9 started.
2024-08-10 05:08:49+00:00 [ERROR] [Entrypoint]:Database is uninitialized and password option is not specified
You need to specify one of the following as an environment variable:
- MYSQL_ROOT_PASSWORD
- MYSQL_ALLOW_EMPTY_PASSWORD
- MYSQL_RANDOM_ROOT_PASSWORD
然后把容器删了,然后指定环境变量,因为MySQL没有设置密码。
[root@ljh~]# docker run -tid --name os1 --restart always -e MYSQL_ROOT_PASSWORD=redhat mysql
登录容器的数据库:
容器里面的数据库的登录方式有2种
方法一:先登录容器 在登录数据库
[root@ljh ~]# docker exec -ti os1 /bin/bash
bash-5.1# mysql -uroot -predhat
mysql> exit
Bye
bash-5.1# exit
exit
[root@ljh~]#
方法二:直接从主机登录容器里面的数据库
[root@ljh~]# mysql -uroot -predhat
bash:mysql:command not found...
Packages providing this file are:
'mariadb'
'mysql'
[root@ljh~]# yum -y install mariadb
查看容器名
[root@ljh~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b7da8ab84581 mysql "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 3306/tcp, 33060/tcp os1
查询容器的详细信息:
[root@ljh~]# docker inspect os1 |grep -i ipaddr
然后我们就可以看见IP地址了后续通过IP地址加端口的方式可以访问
MySQL数据库中html中的内容。
为容器添加端口映射:
容器对外暴露的端口是80,
[root@ljh~]# docker run -tid --name web1 --restart always -p 8080:80 nginx
使用exec登录:
[root@ljh~]# docker exec -ti web1 /bin/bash
root@98da0ef7e5de:/# cd /usr/share/nginx/html/
root@98da0ef7e5de:/usr/share/nginx/html# ls
50x.html index.html
root@98da0ef7e5de:/usr/share/nginx/html# echo 1111 > index.html
root@98da0ef7e5de:/usr/share/nginx/html# cat index.html
1111
root@98da0ef7e5de:/usr/share/nginx/html# exit
exit
[root@ljh~]# ifconfig
ens160:flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.100.11 netmask 255.255.255.0 broadcast 192.168.100.255
inet6 fe80::20c:29ff:feee:63c6 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:ee:63:c6 txqueuelen 1000 (Ethernet)
RX packets 653658 bytes 737945345 (703.7 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 216085 bytes 194488351 (185.4 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
容器与宿主机之间的拷贝:
[root@ljh~]# touch a.txt
[root@ljh~]# vim a.txt
[root@ljh~]# cat a.txt
123456
[root@ljh~]# docker cp a.txt web1:/root
Successfully copied 2.05kB to web1:/root
登录进去看看:
[root@ljh~]# docker exec -ti web1 /bin/bash
root@98da0ef7e5de:/# cd
root@98da0ef7e5de:~# ls
a.txt
从容器里面拷出来到宿主机上面:
[root@ljh~]# docker cp web1:/root/bbb .
Successfully copied 1.54kB to /root/.
总结:docker常用命令:
docker search 查找
docker pull 拉取镜像
docker run/create run创建镜像并运行 create创建
docker attach 进入容器
docker exec -ti *** /bin/bash 进入容器
docker logs ***查看容器日志
docker history 查看镜像的历史版本分层结构
docker inspect 查看容器底层信息(Mac/ip)
docker stop/start/restart 停止,开启,重启容器
docker rm 删除容器
docker rmi 删除镜像
docker ps 显示运行的容器
docker ps -a 显示所以容器
docker push 推送镜像
docker rm -f $(docker ps -qa ) 批量删除容器
docker rmi -f $(docker images -qa ) 批量删除镜像
容器的网络管理:
为什么容器可以上外网:
宿主机通过docker0这个交换机与容器互通;
容器还是通过docker0(桥接模式)与物理网卡绑定,通过物理网卡出去。
安装docker,宿主机上linux多出一块虚拟网桥(虚拟网卡/虚拟交换机 docker 0)
[root@ljh~]# docker network list
NETWORK ID NAME DRIVER SCOPE
0ae7b7e1bdb6 bridgebridge local
67d01e77fd70 host host local仅主机
aacfa404442a none null local
默认有3种网络,主要关注bridge(桥接)网络。当创建要给容器的时候,该容器默认是可以连通外网的。
bridge 相当于vmware NAT ,可以上外网
host 直接复用了主机网络(共享),可以上外网 只能有一个
none 没有虚拟网卡
SCOPE字段,默认local,本地。这个网络不能跨节点互通。
在线源安装:
[root@docker ~]# yum install -y https://mirrors.aliyun.com/centos/7/os/x86_64/Packages/bridge-utils-1.5-9.el7.x86_64.rpm
[root@ljh~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02423a427367 no
virbr0 8000.525400150b3a yes
每多创建一个容器,docker0上就多一个接口,在宿主机上也可以看到这个接口
自定义网络类型:
自定义网络,不想用bridge和host,创建自定义网络类型,或者还是桥接模式,但是我想用C类地址,192.168.66.0/24
自定义一个192.168.66.0/24的网段的桥接网络
[root@ljh~]# docker network create -d bridge --subnet 192.168.66.0/24 mynet
a58609952cbbc01cc85f3bcd1e0a2daec74fcc4d616b04613ee1c54b46352c6f
默认情况下,跨节点容器是不能互通的,早期版本是可以通过部署etcd,然后安装网络插件来实现互通,但是新版本已经不再支持。跨节点互通,只能通过docker swarm或者k8s。后面再讲跨节点通信,这里我们讲的是同一个节点上的容器间的通信
接下来,看容器之间如何互通:
博客系统wordpress
部署两个容器:
创建一个mysql:
我们上一节课讲的用mysql的镜像启动一个数据库容器,至少需要跟一个环境变量。
而我们用wordpress镜像启动一个web网站容器的话,至少需要4个变量。
WORDPRESS_DB_HOST:指定一下wordpress要连接的mysql容器的地址
WORDPRESS_DB_USER:指定一下wordpress要连接mysql用哪个用户连接mysql
WORDPRESS_DB_PASSWORD:输入一下wordpress连接mysql用户的密码
WORDPRESS_DB_NAME:mysql容器里面的mysql框架里面有很多数据库,请写上你要链接的数据库名字,后面wordpress博客系统子初始化时候,会根据我们的这里填的内容创建对应的数据库,并在数据库里面建表
-p 指定端口 端口映射 宿主机端口:容器的端口
请问mysql容器需要对外暴露端口吗?不需要。因为未来我们是用户,只需要通过wordpress的web UI来访问博客网站,所以只需要暴露wordpress容器的端口给用户即可
-v 卷映射 宿主机的目录:容器存放数据的默认目录
mysql容器存放数据的默认目录是/var/lib/mysql
wordpress容器存放数据的默认目录是/var/www/html
nginx容器存放数据的默认目录是/usr/sheare/nginx/html
创建一个MySQL数据库容器:
[root@ljh/]# docker run -tid --name db1 --restart always -v /zxx:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=redhat -e MYSQL_DATABASE=wordpresszxx mysql
创建一个wordpress容器blog:
[root@ljh/]# docker run -tid --name blog -v /xxx:/var/www/html -p 8080:80 -e WORDPRESS_DB_HOST=172.17.0.3 -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=redhat -e WORDPRESS_DB_NAME=wordpresszxx wordpress
浏览器访问wordpress服务,利用宿主机的ip:8080(如果创建容器的时候写的是-p 80:80,那么主机IP后面的80端口跟不跟都行,因为http协议默认就是80端口)
开始做wordpress的初始化配置,博客名称,登录用户名和密码,登录博客,发表一篇文章,此时文章数据就会存入到数据库,说明这两容器互联了
创建新容器,来占db容器的ip:
[root@ljh/]# docker run -tid --name os3 alpine
再开启db1
[root@ljh/]# docker start db1
发现db1的IP从原来的172.17.0.3变成了172.17.0.5了
[root@ljh/]# docker inspect db1 |grep -i ipaddr
"SecondaryIPAddresses":null,
"IPAddress":"172.17.0.5",
"IPAddress":"172.17.0.5",
浏览器还是无法正常访问,因为创建wordpress的时候让他去连接数据库IP是指定172.17.0.3了,所以需要引入link概念
删除所有容器,重新创建db1和blog容器。
--link
因为博客使用的是link的别名,所以不管ip地址怎么变化,会通过link别名动态的更新/etc/hosts映射关系。解决容器IP地址被占用的问题,容器互联。
[root@ljh/]# docker run -tid --name db1 --restart always -v /zxx:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=redhat -e MYSQL_DATABASE=wordpresszxx mysql
[root@ljh/]# docker run -tid --name blog -v /xxx:/var/www/html -p 8080:80 --link db1:zxxdb-e WORDPRESS_DB_HOST=zxxdb-e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=redhat -e WORDPRESS_DB_NAME=wordpresszxx wordpress
把刚刚创建的db1关掉,然后我们创建一个新容器,占掉db1容器的IP
[root@ljh/]# docker run -tid --name os1 alpine
5b87159512f388bfde701895b8ebb9e321a364d3585932abec1f2a6869097668
[root@ljh/]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5b87159512f3 alpine "/bin/sh" 4 seconds ago Up 2 seconds os1
240593813fce wordpress "docker-entrypoint.s…" 5 minutes ago Up 5 minutes 0.0.0.0:8080->80/tcp, :::8080->80/tcp blog
3b74741ac7a2 mysql "docker-entrypoint.s…" 7 minutes ago Exited (0) About a minute ago db1
[root@ljh/]# docker start db1
db1
[root@ljh/]# docker inspect db1 |grep -i ipaddr
"SecondaryIPAddresses":null,
"IPAddress":"172.17.0.4",
"IPAddress":"172.17.0.4",
容器db1的IP虽然变了,但是浏览器还是可以正常访问wordpress网站
说明用了link再容器互联的时候,即使容器IP发生变化,也还是可以互联的
也可以进到blog的容器里面看一下连接的db1容器的IP
[root@ljh/]# docker exec -ti blog /bin/bash
root@240593813fce:/var/www/html# 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.4 zxxdb 3b74741ac7a2 db1
172.17.0.3 240593813fce
root@240593813fce:/var/www/html# exit
exit
容器存储管理:
默认卷(临时卷):
先查看下/var/lib/docker目录下的子目录
[root@ljhdocker]# cd /var/lib/docker/
[root@ljhdocker]# ls
buildkit containersengine-id imagenetwork overlay2 plugins runtimes swarm tmp volumes
子目录image里面存放的是pull下来的镜像,镜像以数据文件的形式存放在image里面
子目录containers里面存放的是用镜像启动的容器
进入到专门存放容器的目录containers,里面是空的
[root@ljhdocker]# cd containers/
[root@ljhcontainers]# ls
以centos为例创建一个容器
[root@ljhcontainers]# docker run -tid --name os1 --restart always centos
在专门存放容器的目录containers里面多了一个容器id为名的目录
[root@ljhcontainers]# ls
d5fe3505b4bf7494ea3f552fb8ec9a652cfdd213fda69ad7a673029bb786ec57
进到这个目录下
[root@ljhcontainers]# cd d5fe3505b4bf7494ea3f552fb8ec9a652cfdd213fda69ad7a673029bb786ec57/
发现很多容器文件
回到根目录
[root@ljhd5fe3505b4bf7494ea3f552fb8ec9a652cfdd213fda69ad7a673029bb786ec57]# cd /
在/目录下查询文件名ljh.txt的文件,查不到
[root@ljh/]# find / -name ljh.txt
登录容器os1,在容器里面创建taozi.txt的文件
[root@ljh/]# docker exec -ti os1 /bin/bash
[root@d5fe3505b4bf /]# touch ljh.txt
[root@d5fe3505b4bf /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys ljh.txttmp usr var
再回到宿主机查询文件ljh.txt,从而来验证容器中的数据存放在宿主机上的什么位置
[root@ljh/]# find / -name ljh.txt
/var/lib/docker/overlay2/c83a787f6b6cd7e1471ef7b52573373eace1e22018196e2ae330a0678178b419/diff/ljh.txt
/var/lib/docker/overlay2/c83a787f6b6cd7e1471ef7b52573373eace1e22018196e2ae330a0678178b419/merged/ljh.txt
diff目录保存的就是你新增或修改的数据,差分目录
merge 目录是合并目录,可以看到所有差分目录里面的数据,容器开启状态下,两个目录数据是一样的。
这两个默认映射的底层目录,也是临时的,会随着容器的删除而删除。
所以在容器里面写入的数据,宿主机上是生效的
在宿主机上写入的数据,容器里面也是生效的
如果删除容器,容器对应的存数据的目录也会被删除
指定永久卷:
如果容器数据很重要 即使容器被删除了 我们希望数据还在 怎么办?
-v 将宿主机的目录与容器目录绑定映射,你往容器哪个命令写数据,你希望跟宿主机的哪个目录形成映射关系,多复制一份,那么就采用-v
语法一:
-v /data
代表的是容器目录,没有指定宿主机目录,那么宿主机目录就是随机生成的长字符串目录下去存放,即使容器被删除,数据还在
语法二:
-v /host_data:/data
指定宿主机的目录/host_data与容器里面的/data形成绑定映射关系,即使容器被删除 数据还在
先用语法一创建一个容器,查看容器的数据会被存放在主机的哪里
[root@ljh~]# docker run -tid --name os1 --restart always -v /data centos
登录容器,查看容器基本情况
[root@ljh~]# docker exec -ti os1 /bin/bash
[root@de89215ce824 /]# cd data/
[root@de89215ce824 data]# ls
回到宿主机在根目录下查看ljh666的文件,没找到
[root@ljh~]# cd /
[root@ljh/]# find / -name ljh666
find:‘/run/user/0/gvfs’:Transport endpoint is not connected
登录容器,在容器的根目录下创建一个空文件ljh666
[root@ljh/]# docker exec -ti os1 /bin/bash
[root@de89215ce824 data]# touch ljh666
再回到宿主机,可以查看到zx666在宿主机的哪个目录了
[root@ljh/]# find / -name ljh666
find:‘/run/user/0/gvfs’:Transport endpoint is not connected
/var/lib/docker/volumes/d182016dc38fb76166e208e81c0be7051d70dc96e3fc40129f3afb4177071c96/_data/ljh666
[root@ljh/]# docker inspect os1
"Mounts":[
{
"Type":"volume",
"Name":"d182016dc38fb76166e208e81c0be7051d70dc96e3fc40129f3afb4177071c96",
"Source": "/var/lib/docker/volumes/d182016dc38fb76166e208e81c0be7051d70dc96e3fc40129f3afb4177071c96/_data",
"Destination":"/data",
"Driver":"local",
"Mode":"",
"RW":true,
"Propagation":""
}
],
即使删除容器了,数据依然存在,可以查到
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
de89215ce824 centos "/bin/bash" 6 minutes ago Up 6 minutes os1
[root@ljh/]# docker rm -f d
[root@ljh/]# find / -name ljh666
find:‘/run/user/0/gvfs’:Transport endpoint is not connected
/var/lib/docker/volumes/d182016dc38fb76166e208e81c0be7051d70dc96e3fc40129f3afb4177071c96/_data/ljh666
-v /hostdata:/data
用语法二创建一个容器,查看容器的数据会被存放在主机的哪里
[root@ljh/]# docker run -tid --name os1 --restart always -v /zjdata:/rqdatacentos
8d6c862758cd9f750462dda57df06a2ea674d42b2c54f90e3a4ef0d6070ac871
进入容器里面,查看下基本情况
[root@ljh/]# docker exec -ti os1 /bin/bash
[root@8d6c862758cd /]# cd rqdata/
在宿主机上查看文件ljh888在哪,没找到
[root@ljh/]# find / -name ljh888
find:‘/run/user/0/gvfs’:Transport endpoint is not connected
去容器的/rqdata里面创建一个空文件ljh888
[root@ljh/]# docker exec -ti os1 /bin/bash
[root@8d6c862758cd rqdata]# ls
[root@8d6c862758cd rqdata]# touch ljh888
在宿主机上可以查到ljh888在哪了
[root@ljh/]# find / -name ljh888
find:‘/run/user/0/gvfs’:Transport endpoint is not connected
/zjdata/ljh888
[root@ljh/]# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var xxx ljhdata zxx
删除容器,数据也还在
[root@ljh/]# find / -name ljh888
find:‘/run/user/0/gvfs’:Transport endpoint is not connected
/zjdata/ljh888
-v 指定目录的权限
默认情况下,-v映射的宿主机的卷对于容器来说是可读可写的,但是如果你需要指定权限 也可以实现
查看下宿主机/目录下有哪些可用目录,待会用zjdata这个目录
[root@ljh/]# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var xxx zjdatazxx
[root@ljhzjdata]# docker run -tid --name os1 --restart always -v /zjdata:/rqdata:rocentos
[root@ljhzjdata]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b26b6ed451e5 centos "/bin/bash" 1 second ago Up 1 second os1
进入容器里面,发现只有读权限
[root@ljhzjdata]# docker exec -ti os1 /bin/bash
[root@b26b6ed451e5 /]# cd /rqdata/
[root@b26b6ed451e5 rqdata]# touch ljh666
touch:cannot touch 'ljh666':Read-only file system
[root@b26b6ed451e5 rqdata]# rm -f ljh888
rm:cannot remove 'ljh888':Read-only file system
如果我创建新容器,来映射刚才的还有数据的目录,那么新容器可以读到该目录里面的数据吗?可以。代表-v指定创建目录是可以复用的,也就是帮给其他的容器读到上个容器的数据的
-v 复用卷
例如:之前讲link链接的实验的时候,我们创建了wordpress和mysql的容器,虽然已经删除,但是他们的主机目录还在,现在拿wordpress做一个博客系统,提供服务,wordpress默认的网站根目录/var/www/html,我们可以把本地之前的数据库和博客目录里面的所有文件备份一份到本地系统,那么新创建的数据库和博客容器,通过-v参数映射,以实现对原来wordpress博客和数据库内容的复用。
创建容器,最好再跟--name blog的参数,创建名字为blog的容器
[root@ljh/]# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var xxxzjdata zxx
[root@ljh/]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@ljh/]# docker run -tid --name db1 --restart always -v /zxx:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=redhat -e MYSQL_DATABASE=wordpresszxx mysql
280dd5a167c4cf756ba835831aacea2a5420aa4c7dd4665e89f112131debb777
[root@ljh/]# docker run -tid --name blog -v /xxx:/var/www/html -p 8080:80 --link db1:zxxdb -e WORDPRESS_DB_HOST=zxxdb -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=redhat -e WORDPRESS_DB_NAME=wordpresszxx wordpress
1f904433bf50a1ae2b255abcf466731b876425dbd683d07e79c8a4501b24c9ca
[root@ljh/]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1f904433bf50 wordpress "docker-entrypoint.s…" 2 seconds ago Up 1 second 0.0.0.0:8080->80/tcp, :::8080->80/tcp blog
280dd5a167c4 mysql "docker-entrypoint.s…" 14 seconds ago Up 12 seconds 3306/tcp, 33060/tcp db1
直接浏览器访问wordpress可以看到昨天的文章
docker compose
就是一个简单的,针对于小环境使用的容器编排工具。
编写一个yaml(呀某/耶某)文件,语法规则
1. 缩进必须使用空格,不得使用tab
2. 缩进几个空格无所谓,但是同一级标题,必须左对齐
创建一个yaml文件,名称必须叫docker-compose.yaml(标准名称),内容如下
services:
blog:
image: wordpress:888
restart: always
links:
- db:dblink
ports:
- "80:80"
environment:
- WORDPRESS_DB_HOST=dblink
- WORDPRESS_DB_USER=root
- WORDPRESS_DB_PASSWORD=memeda
- WORDPRESS_DB_NAME=wordpressdb
db:
image: mysql:888
restart: always
environment:
- MYSQL_ROOT_PASSWORD=memeda
- MYSQL_DATABASE=wordpressdb
[root@docker ~]# docker compose up -d
[+] Running 3/3
✔ Network root_default Created 0.1s
✔ Container root-db-1 Started 0.7s
✔ Container root-blog-1 Started 1.7s
[root@docker ~]# docker compose stop
[+] Stopping 2/2
✔ Container root-blog-1 Stopped 1.1s
✔ Container root-db-1 Stopped 1.3s
[root@docker ~]# docker compose start
[+] Running 2/2
✔ Container root-db-1 Started 0.5s
✔ Container root-blog-1 Started 1.4s
如果不是标准名称呢?
[root@docker test]# docker compose -f blog.yaml up -d
[+] Running 2/2
✔ Container test-db-1 Started 0.6s
✔ Container test-blog-1 Started 1.4s
harbor:(如何构建自己的内部企业级私有镜像仓库)
流程
1. 官方下载harbor off离线包(很多脚本文件install.sh)
2. 下载我们自己打包的离线镜像包(包含了harbor搭建所需的镜像)
https://blog.51cto.com/cloudcs/11778828
Dockerfile 自定义镜像
在阿里开源镜像站上可以按到centos 8.4.2105版本ISO大小是9.2GB,而上面我们查看到我们pull下来的centos镜像只有231MB,所以docker里面pull下来的镜像是精简的,包不完整,很多软件包都没有,也没有安装对应的软件包。
阿里巴巴开源镜像站链接如下:
https://developer.aliyun.com/mirror/?spm=a2c6h.13651104.mirror-detail.d1002.7ccd2dcb0hwPbF
创建容器:
[root@ljh/]# docker run -tid --name os1 --restart always centos
容器里面查看源的信息:
[root@ecbd7675b02b /]# cd /etc/yum.repos.d/
[root@ecbd7675b02b yum.repos.d]# ls
CentOS-Linux-AppStream.repo CentOS-Linux-Debuginfo.repo CentOS-Linux-FastTrack.repo CentOS-Linux-Plus.repo
CentOS-Linux-BaseOS.repo CentOS-Linux-Devel.repo CentOS-Linux-HighAvailability.repo CentOS-Linux-PowerTools.repo
CentOS-Linux-ContinuousRelease.repo CentOS-Linux-Extras.repo CentOS-Linux-Media.repo CentOS-Linux-Sources.repo
更新源地址,所有的repo都做备份(.bak):
[root@ecbd7675b02b yum.repos.d]# sed -e "s|^mirrorlist=|#mirrorlist=|g" -e "s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://mirrors.aliyun.com/centos-vault/8.4.2105|g" -i.bak /etc/yum.repos.d/CentOS-*.repo
验证命令没问题后,就在宿主机上把刚才更新源的命令写入到dockerfile的文件中去:
[root@ljh~]# vim dockerfile
[root@ljh~]# cat dockerfile
FROM centos:latest
MAINTAINER zxmintainer
RUN minorver=8.4.2105\
&& sed -e "s|^mirrorlist=|#mirrorlist=|g" -e "s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://mirrors.aliyun.com/centos-vault/8.3.2011|g" -i.bak /etc/yum.repos.d/CentOS-*.repo
RUN yum -y install vim net-tools bash-completion zip unzip bzip2
CMD ["/bin/bash"]
开始读取当前目录下的dockerfile文件来构建镜像
[root@ljh~]# docker build -t centos:8.4.2105 .
用刚才构建的镜像启动一个容器os2
[root@ljh~]# docker run -tid --name os2 --restart always centos:8.4.2105
登录容器os2
[root@ljh~]# docker exec -ti os2 /bin/bash
[root@e86a5a4b7834 /]# cat /etc/redhat-release
CentOS Linux release 8.4.2105
就可以使用vim....
[root@e86a5a4b7834 /]# ifconfig
COPY和ADD
当我们在编写dockerfile文件的时候,在要执行的命令里面加入COPY和ADD命令
利用COPY和ADD把宿主机上到文件拷贝到容器里面是没有区别的
那么COPY和ADD的区别是什么?在于拷贝压缩包的时候
COPY压缩包到容器,还是压缩包
ADD压缩包不到容器会把压缩包解压
[root@ljh~]# tar -zcvf abc.tar.gz a.txt b.txt c.txt
不管是tar包还是压缩过的tar.gz,通过add参数,都会自动解压;通过copy参数,会原封不动进行复制。
自定义一个nginx镜像
如果你想要运行一个网站,那么需要有nginx服务,所以可以在centos系统基础上安装nginx服务,安装好nginx服务后把宿主机上家目录里面的index.html文件COPY到容器的nginx服务的根目录/usr/share/nginx/html目录下去
于是在笔记本上的浏览器可以访问宿主机ip加端口即可看到容器里面的静态网页
[root@ljh~]# touch index.html
[root@ljh~]# echo 111 > index.html
[root@ljh~]# echo 222 >> index.html
[root@ljh~]# echo 333 >> index.html
[root@ljh~]# cp dockerfile02 dockerfile03
找到这个守护进程后,复制到dockerfile03里面去,加上逗号分隔
[root@ljh~]# docker history nginx:latest --no-trunc |head -2
IMAGE CREATED CREATED BY SIZE COMMENT
sha256:a72860cb95fd59e9c696c66441c64f18e66915fa26b249911e83c3854477ed9a 7 weeks ago CMD ["nginx" "-g" "daemon off;"]0B buildkit.dockerfile.v0
[root@ljh~]# vim dockerfile03
[root@ljh~]# cat dockerfile03
FROM centos:8.4.2105
MAINTAINER zxmintainer
RUN yum -y install nginx
COPY index.html /usr/share/nginx/html
CMD ["nginx","-g","daemon off;"]
开始读取当前目录下的dockerfile03文件来构建镜像
[root@ljh~]# docker build -t nginx:v1 . -f dockerfile03
利用镜像创建容器:
[root@ljh~]# docker run -tid --name nginx1 --restart always -p 8080:80 nginx:v1
浏览器可以正常访问
User
指定哪个默认用户登录,USER修改容器里面登录用户
[root@ljh~]# vim dockerfile04
[root@ljh~]# cat dockerfile04
FROM centos:latest
MAINTAINER ljh
RUN sed -e "s|^mirrorlist=|#mirrorlist=|g" -e "s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://mirrors.aliyun.com/centos-vault/8.3.2011|g" -i.bak /etc/yum.repos.d/CentOS-*.repo
RUN yum install -y vim net-tools bash-completion zip unzip bzip2 httpd passwd
RUN useradd tom
RUN echo "redhat" |passwd tom --stdin
RUN echo "redhat" |passwd root --stdin
USER tom
CMD ["/bin/bash"]
[root@ljh~]# docker build -t nginx:v3 . -f dockerfile04
[root@ljh~]# docker run -tid --name os1 --restart always -h ooss1 nginx:v3
[root@ljh~]# docker exec -ti os1 /bin/bash
[tom@ooss1 /]$ id
uid=1000(tom) gid=1000(tom) groups=1000(tom)
[tom@ooss1 /]$ su - root
Password:
[root@ooss1 ~]# id
uid=0(root) gid=0(root) groups=0(root)
[root@ooss1 ~]# exit
logout
[tom@ooss1 /]$ exit
exit
[root@ljh~]# docker inspect os1 |grep -i ipaddr
"SecondaryIPAddresses":null,
"IPAddress":"172.17.0.2",
"IPAddress":"172.17.0.2",
[root@ljh~]# ssh root@172.17.0.2
ssh:connect to host 172.17.0.2 port 22:Connection refused
卷映射:
VOLUME的映射
[root@ljh~]# cp dockerfile04 dockerfile05
[root@ljh~]# cat dockerfile05
FROM centos:v2
MAINTAINER ljh
VOLUME /data
CMD ["/bin/bash"]
[root@ljh~]# docker build -t centos:v3 . -f dockerfile05
[root@ljh~]# docker run -tid --name os1 --restart always centos:v3
[root@ljh~]# docker exec -ti os1 /bin/bash
[root@e4da4c495150 /]# cd data/
[root@e4da4c495150 data]# ls
[root@e4da4c495150 data]# touch zzz
[root@ljh~]# find / -name zzz
find:‘/run/user/0/gvfs’:Transport endpoint is not connected
/var/lib/docker/volumes/b6611777d57b80f3bb98b245e78c6da11c5070baa996135d3b9357e6164a4a68/_data/zzz
配置ssh镜像:
能被ssh连接的主机,必须要得有这3对钥匙,也就是6个秘钥文件,才能用ssh连接上主机
[root@ljh~]# cd /etc/ssh/
[root@ljhssh]# ls
moduli ssh_config.d ssh_host_ecdsa_key ssh_host_ed25519_key ssh_host_rsa_key
ssh_config sshd_config ssh_host_ecdsa_key.pub ssh_host_ed25519_key.pub ssh_host_rsa_key.pub
修改dockerfile04文件内容如下:
[root@ljh~]# vim dockerfile04
[root@ljh~]# cat dockerfile04
FROM centos:latest
MAINTAINER ljh
RUN sed -e "s|^mirrorlist=|#mirrorlist=|g" -e "s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://mirrors.aliyun.com/centos-vault/8.3.2011|g" -i.bak /etc/yum.repos.d/CentOS-*.repo
RUN yum install -y vim net-tools bash-completion zip unzip bzip2 httpd passwd openssh-clients openssh-server
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
RUN ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
RUN useradd zhangsan
RUN echo "redhat" |passwd zhangsan --stdin
RUN echo "redhat" |passwd root --stdin
EXPOSE 22
RUN rm -rf /run/nologin
CMD ["/usr/sbin/sshd","-D"]
[root@ljh~]# docker build -t centos:ssh . -f dockerfile04
[root@ljh~]# docker run -tid --name os1 --restart always -h ooss1 centos:ssh
[root@ljh~]# docker inspect os1 |grep -i ipaddr
"SecondaryIPAddresses":null,
"IPAddress":"172.17.0.2",
"IPAddress":"172.17.0.2",
[root@ljh~]# ssh root@172.17.0.2
The authenticity of host '172.17.0.2 (172.17.0.2)' can't be established.
ECDSA key fingerprint is SHA256:78EBI8fHqZrKH6LuAnyYxB4Sfp34dEottoj0rqCp81s.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning:Permanently added '172.17.0.2' (ECDSA) to the list of known hosts.
root@172.17.0.2's password:
[root@ooss1 ~]# ifconfig
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 59 bytes 7777 (7.5 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 22 bytes 4293 (4.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
为容器配置简化桌面:
[root@ljh~]# docker run -tid --name os1 -h ooos1 --privileged=true centos:ssh /usr/sbin/init
/usr/sbin/init 启动容器可以使用systemctl启动服务。
--privileged=true 获取宿主机root权限(特殊权限)
[root@ljh~]# docker exec -ti os1 /bin/bash
[root@ooos1 yum.repos.d]# cd /etc/yum.repos.d/
[root@ooos1 yum.repos.d]#ls
[root@ooos1 yum.repos.d]# yum -y install xrdp
[root@ooos1 yum.repos.d]# cd /etc/yum.repos.d/
[root@ooos1 yum.repos.d]# ls
下载扩展源epel
[root@ooos1 yum.repos.d]# yum -y install epel-release.noarch
安装轻量级桌面软件包组,需要的软件包组在上面命令执行得来的epel的扩展源里面来的
[root@ooos1 yum.repos.d]# yum -y install xrdp &&yum -y groupinstall Xfce
[root@ooos1 yum.repos.d]# exit
exit
必要的参数给他贴一下
[root@ooos1 /]# echo xfce4-session > /root/.xsession
[root@ooos1 /]# cat /root/.xsession
xfce4-session
然后给他授权
[root@ooos1 /]# chmod +x /root/.xsession
启动服务
[root@ooos1 /]# systemctl restart xrdp && systemctl enable xrdp
Created symlink /etc/systemd/system/multi-user.target.wants/xrdp.service → /usr/lib/systemd/system/xrdp.service.
[root@ooos1 /]# systemctl status xrdp
●xrdp.service - xrdp daemon
Loaded:loaded (/usr/lib/systemd/system/xrdp.service; enabled; vendor preset:disabled)
Active: active (running)since Sun 2024-08-11 08:36:34 UTC; 14s ago
退出容器
[root@ooos1 /]# exit
用commit把容器os1提交成镜像centos:666
[root@ljh~]# docker commit os1 centos:desk
sha256:e3fe9152ebed72169c231f744ff19d8a89f35e0add4cce36368d52fe7e2946b6
[root@ljh~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos desk e3fe9152ebed 3 seconds ago 1.08GB
[root@ljh~]# docker run -tid --name os2 -h ooos2 -p 13389:3389 --privileged=true centos:desk /usr/sbin/init
远程桌面登录容器 登录的时候用root用户,密码redhat
进去后,是一个轻量级桌面,在application里面有个terminal打开终端也可以敲命令