首先了解一下doker和k8s的故事:

容器技术Doker:_docker

那么容器对比虚拟机有哪些优势:

容器技术Doker:_docker_02

什么是云原生:

云原生是一种构建和运行云端应用程序的方法论。

云原生还提倡使用容器技术(如Docker)来打包和分发应用程序,使得应用程序的运行环境更加独立和可移植。同时,云原生还倡导采用微服务架构,将应用程序分解成一系列小型、独立的服务组件,每个组件负责一个特定的功能。这样可以实现模块化开发,方便应对复杂的业务需求和快速迭代。

综上所述,云原生是一种以云计算为基础,利用虚拟化容器化微服务架构的方式,更高效、更灵活地构建和运行应用程序(上层应用)。它可以让你专注于应用开发和业务创新,而不需要关注底层基础设施的细节。


什么是容器:

容器技术是一种轻量级的虚拟化技术,它允许将应用程序和其依赖项打包到一个独立的、可移植的运行环境中,称为容器。这些容器可以在任何支持容器化技术的主机上运行,而不受底层操作系统和硬件的影响。

容器技术是一种轻量级的虚拟化技术,它允许将应用程序和其依赖项打包到一个独立的、可移植的运行环境中,称为容器。这些容器可以在任何支持容器化技术的主机上运行,而不受底层操作系统和硬件的影响。

容器技术的优势:

简化部署:容器提供了一个一致的运行环境,可以轻松地在不同的主机或云平台上部署应用程序。

快速启动:容器可以在几秒钟内启动,相比之下,传统的虚拟机需要更长的启动时间。

可移植性:容器可以在不同的环境中移植和运行,无需重写代码或重新配置应用程序。

资源隔离:容器提供了资源隔离,使得不同的容器可以在同一台主机上运行,而互不干扰。

弹性伸缩:容器技术可以根据需求自动扩展或收缩容器实例,以适应负载的变化。

一些流行的容器化技术包括Docker和Kubernetes=k8s,podman,buildah。Docker提供了一种简单的方法来创建、打包和分享容器镜像,而Kubernetes是一个容器编排平台,用于自动化和管理大规模的容器部署。这些技术的出现,使得容器化应用程序的开发、部署和管理变得更加简单和高效。

容器和虚拟化的区别:

容器技术Doker:_docker_03

容器技术Doker:_docker_04

容器技术Doker:_docker_05

首先我们来安装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

容器技术Doker:_docker_06

docker架构:

容器技术Doker:_docker_07

镜像和容器是什么关系:

运行什么进程是由镜像决定的

容器技术Doker:_docker_08

docker镜像管理:

去ucloud拉取镜像,找到ucloud的镜像私有镜像仓库的地址后,开始登录自己的私有镜像仓库。

[root@ljhyum.repos.d]# docker login uhub.service.ucloud.cn/iecloud.ljh

如果是公开的镜像就不需要登录了直接拉取,如果是私有的就需要登录输入用户名和密码就行了。

容器技术Doker:_docker_09

查看是否有镜像:

[root@ljhyum.repos.d]# docker images

然后直接拉取过来就行了。命令如下,复制粘贴即可。

容器技术Doker:_docker_10

阿里云仓库镜像的拉取和推送

如何在阿里云的私有仓库中pull和push镜像,方法如下:

https://cr.console.aliyun.com/cn-hangzhou/instance/namespaces

容器技术Doker:_docker_11

容器技术Doker:_docker_12

先登录到阿里云镜像库里面,要把镜像推送到阿里云的话记得修改一下镜像的名字格式,然后进行推送。

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


镜像的分层:

容器技术Doker:_docker_13

[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中的内容。

为容器添加端口映射:

容器技术Doker:_docker_14

容器对外暴露的端口是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(桥接模式)与物理网卡绑定,通过物理网卡出去。

容器技术Doker:_docker_15

安装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:(如何构建自己的内部企业级私有镜像仓库)


容器技术Doker:_docker_16

流程

1. 官方下载harbor off离线包(很多脚本文件install.sh)

2. 下载我们自己打包的离线镜像包(包含了harbor搭建所需的镜像)

https://blog.51cto.com/cloudcs/11778828


Dockerfile 自定义镜像

容器技术Doker:_docker_17

在阿里开源镜像站上可以按到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

浏览器可以正常访问

容器技术Doker:_docker_18

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

容器技术Doker:_docker_19

容器技术Doker:_docker_20

进去后,是一个轻量级桌面,在application里面有个terminal打开终端也可以敲命令


容器技术Doker:_docker_21