1、可视化
轻量级UI Portainer
Portainer 是一个轻量级的管理 UI ,可让你轻松管理不同的 Docker 环境(Docker 主机或 Swarm 群集)。它由可在任何 Docker 引擎上运行的单个容器组成,旨在使部署更简单 。
-v 就是挂载目录! 将linux中的目录和容器内的目录的文件同步,修改新增文件都会同步!
docker run -d -p 8088:9000 \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
--name ui-portainer \
docker.io/portainer/portainer
[root@alibaba ~]# docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --name ui-portainer docker.io/portainer/portainer
访问http://服务器ip:8088,会让我们设置密码,点击“create user”

选择连接本地或远程docker

我们选择Local,连接,显示当前连接的docer实例信息,容器、数据卷、镜像,宿主机的cpu核数,内存

点进docker实例,可以可视化查看我们的docker内部信息

点进容器,可以start,stop,remove,add的相关操作

点进镜像,可以pull,remove

2、Docker镜像
什么是镜像
镜像就是一种轻量级的,独立的软件包!
包含:服务+环境+linux,只需要运行这个镜像,生产容器提供服务!
以前:每个linux服务器都需要配置项目环境! 1000台可以写脚本配置,耗时费力
现在:在每个Linux安装一个docker即可!1分钟安装docker,run镜像暴露端口即可,无需脚本配置。
镜像加载的原理
联合文件系统
联合文件系统 核心:就是分层!
如果系统每发生一次变化或者修改,一但被提交,那么就生成新的一层,就是新的镜像
就好像版本的升级,
1.0 base基础(linux系统内核)
1.1 base+ java
1.2 base+ java + redis
1.3 base+ java + redis + maven
Docker的镜像分层原理

镜像也是分层的,构建的时候从底部开始一层层构建, 系统只要增加一层那么就会形成一个新的镜像!
tomcat 下载来的镜像,是有版本号的! 运行 => 容器 ,当前运行的容器会改变tomcat的镜像内容!本质就是加了一层Container
如果镜像每发生一次变化或者修改,一但被提交,那么就生成新的镜像,且在上一个镜像上增加一层!
科普:rootfs 与 bootfs
-
bootfs: bootloader + kernel。
bootloader 进行引导加载 kernel内核!这一层所有的Linux/Unix操作系统都是一样的!整个内核这个时候就在内存中了。内存使用权就从 bootfs 转交给了内核,这个时候系统就会自动卸载 bootfs!
-
rootfs (root file system)root文件系统
在 bootfs 之上,包含基本目录 /dev /bin /etc 。。。。等等标准的目录和文件!市面上看到的不同的操作系统发行版,其实核心就是 rootfs 有些区别,所以rootfs 就是各种不同操作系统的发行版,但是底层 bootfs 是一样的(进行引导加载 kernel内核)。

对于一个精简的 OS, rootfs 可以很小(文件管理系统)!我们只需要包含一些基本的命令就可以了,工具、程序库等等。底层可以共用一个 Kernel,这个时候我们不同的发行版主要就提供 rootfs 即可。
Linux不同发行版的 bootfs 几乎是一致的,区别就是 rootfs !
docker镜像的底层(第一层)都是一个linux系统(boots + rootfs)!
分层概念
我们下载镜像可以发现是分层下载的,层是可以复用的,already exists 表示宿主机docker已有该镜像层,不用重新拉取

思考:为什么要分层!
好处:资源共享,比如多个镜像都是从相同 base 镜像构建而来。那么我们的宿主机上只需要保留一份base即可。这一份base镜像可以为所有的容器镜像服务。每个镜像都可以有多个镜像层来进行组装构建,每一层也是可以被共享的。
# 查看镜像的全部信息
[root@kuangshen ~]# docker image inspect redis:latest

# 查看镜像的修改历史
[root@alibaba ~]# docker history redis
IMAGE CREATED CREATED BY SIZE COMMENT
36304d3b4540 11 days ago /bin/sh -c #(nop) CMD ["redis-server"] 0B
<missing> 11 days ago /bin/sh -c #(nop) EXPOSE 6379 0B
<missing> 11 days ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B
<missing> 11 days ago /bin/sh -c #(nop) COPY file:df205a0ef6e6df89… 374B
<missing> 11 days ago /bin/sh -c #(nop) WORKDIR /data 0B
<missing> 11 days ago /bin/sh -c #(nop) VOLUME [/data] 0B
<missing> 11 days ago /bin/sh -c mkdir /data && chown redis:redis … 0B
<missing> 11 days ago /bin/sh -c set -eux; savedAptMark="$(apt-m… 30.4MB
<missing> 11 days ago /bin/sh -c #(nop) ENV REDIS_DOWNLOAD_SHA=33… 0B
<missing> 11 days ago /bin/sh -c #(nop) ENV REDIS_DOWNLOAD_URL=ht… 0B
<missing> 11 days ago /bin/sh -c #(nop) ENV REDIS_VERSION=6.0.4 0B
<missing> 3 weeks ago /bin/sh -c set -eux; savedAptMark="$(apt-ma… 4.15MB
<missing> 3 weeks ago /bin/sh -c #(nop) ENV GOSU_VERSION=1.12 0B
<missing> 3 weeks ago /bin/sh -c groupadd -r -g 999 redis && usera… 329kB
<missing> 3 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:7780c81c33e6cc5b6… 69.2MB
官方文档查看更多使用命令:https://docs.docker.com/engine/reference/

理解:
基础镜像

在基于这个镜像再添加一些内容,commit组合新镜像

新增覆盖,第三层中的reids覆盖了第二层中的redis的镜像

对外暴露就是一个镜像

小结
Docker镜像进行启动的时候变成容器!(docker run 镜像)
镜像+容器层!我们的操作都是基于容器层来操作的,最上面的那一层就是Container 容器层
镜像Commit

一句话:从容器再构建成一个新的镜像!
# 运行镜像创建容器tomcat
[root@alibaba /]# docker run -it -d -p 8080:8080 tomcat:9.0
# 访问tomcat报404
[root@alibaba /]# curl localhost:8080
<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title>
....
...
# 进入容器
[root@alibaba /]# docker exec -it 332e68036723 /bin/bash
# 默认的官方tomcat镜像 webapps 是没有项目的!
root@332e68036723:/usr/local/tomcat/webapps# ls
# 复制webapp.dist的所有文件到webapps下
root@332e68036723:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@332e68036723:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
这时访问tomcat

# 帮助命令
[root@alibaba ~]# docker commit --help
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Create a new image from a container's changes
Options:
-a, --author string Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
-c, --change list Apply Dockerfile instruction to the created image
-m, --message string Commit message
-p, --pause Pause container during commit (default true)
# 定制一个自己的tomcat,放上项目,生成新的镜像!
# 将我们已经存在项目webapps的tomcat提交为一个新的镜像供我们使用!
# 返回新的镜像
[root@alibaba ~]# docker commit -a="jude<747464168@qq.com>" -m="webapps" 332e68036723 tocmat02:0.1
sha256:1812f2b66c81c9f3f3461a10570e4ae716b87015e929474ecc235ac33f631bad
# 比对官方tomcat与tomcat02,大小发生了变化
[root@alibaba ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tocmat02 0.1 1812f2b66c81 About a minute ago 652MB
tomcat 9.0 1b6b1fe7261e 3 weeks ago 647MB
# 关掉官方tomcat,运行tomcat02
[root@alibaba /]# docker stop 332e68036723
[root@alibaba /]# docker run -it -p 8080:8080 tocmat02:0.1
直接访问localhost:8080,返回首页,因为tomcat02镜像的webapps已包含了我们添加的项目

比较两个镜像的层,发现tomcat02多了一层

小结
制作的镜像的第一个方式:commit 提交生成镜像!还有两种方式:Tar files(少用)、Dockerfile
# 1、下载镜像运行=> 容器(新的镜像层)
# 2、在这里进行了一些操作之后, 通过commit 提交
# 3、这个新镜像就是自己的了!本地的,之后可以推送到dockerhub上!
3、Docker数据卷(重点)
应用和环境打包形成镜像=> 运行=> 容器,那我们保留数据,到底该保存在哪里!比如mysql镜像 =>容器, data 在容器内。
这时删除容器 = 删库跑路!这肯定不行!
所以为了保存数据同步持久化,Docker给我们提供了数据卷。把卷(目录)挂载到本地!这样删除容器,数据还在本地!
-
作用:
卷可以在一个或者多个容器内进行通信,共同存储东西。不属于联合文件系统!==提供数据持久化和数据共享操作==
# 格式:-v 宿主机目录:容器内目录 , 和 -p 道理一样,实现同步! -v \xxx:\xxx
方式一:通过命令来添加挂载
# 测试,挂载一个ceshi目录到容器
docker run -it -v /home/ceshi:/home centos /bin/bash
# 1、主机目录多了一个ceshi目录,自动生成的
# 2、可以通过 docker inspect 查看容器,发现挂载成功!
[root@alibaba home]# docker inspect 8d8d494175aa
"Mounts": [
{
"Type": "bind",
"Source": "/home/cechi",
"Destination": "/home",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
测试,在容器新建一个文件,也会同步到宿主机/home/cechi目录下

关掉容器再测试,本地到容器

# 修改test.java,添加hello world
[root@alibaba cechi]# vim test.java
hello world
# 启动容器
[root@alibaba home]# docker start 8d8d494175aa
进入容器,发现容器内的test.java文件已被同步修改

练习作业:将tomcat的webapps,进行挂载,然后随便发布一个项目测试玩玩!
# 把项目部署到宿主机/www/tomcat9/webapps就可以了
[root@alibaba home]# docker run -d -p 8080:8080 -v /www/tomcat9/webapps:/usr/local/tomcat/webapps --name tomcat9 tomcat:9.0
Docker安装MySQL
Docker hub搜索mysql ,怎么安装讲的很清楚
我们不是所有目录都会挂载,一般就是数据和应用的配置!
# 先看官网
# 1、docker安装mysql必要步骤: -e 设置环境变量 MYSQL_ROOT_PASSWORD=my-secret-p @ mysql的初始密码!
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 2、mysql核心1 配置文件挂载到宿主机,
docker run --name some-mysql -v /my/custom:/etc/mysql/mysql.conf.d -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 进入容器发现 /etc/mysql/my.cnf 才是mysql的核心配置文件,它里面有两行
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
# 意思包含两个目录下的配置文件,mysql.conf.d 目录下有一个默认的配置文件mysqld.cnf, 自己编写的配置文件第一行必须是[mysqld]
root@e8ada57c00cd:/etc/mysql/mysql.conf.d# cat mysqld.cnf
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
#log-error = /var/log/mysql/error.log
# By default we only accept connections from localhost
#bind-address = 127.0.0.1
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# 3、mysql核心2 数据存储挂载到宿主机
docker run --name some-mysql -v /my/own/datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
测试
# 1、先pull下来
[root@alibaba home]# docker pull mysql:5.7
# 2、挂载目录运行mysql
[root@alibaba home]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
查看运行容器

查看宿主机的/home/mysql/data目录,数据已同步过来,使用本地的数据连接工具,新建一个数据库test

移除容器
[root@alibaba home]# docker rm f9d70719e383
发现数据依然存在,那就保证了数据不会随容器删除而删除
docker run --name mysql01 -v /home/mysql/config:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
# 删除这个容器,发现数据还在
# 新建一个容器,连接挂载这个数据卷,发现mysql数据依旧存在!
# mysql 可以通过这个方式实现多个mysql容器,共享数据!
方式二:使用DockerFile来挂载卷
dockerfile 是用来构建Docker镜像的脚本文件,包含很多命令。
# 创建一个dokcerfile文件
[root@alibaba docker-test-volume]# vim dockerfile
FROM centos
VOLUME ["/datavolume01","/datavolume02"] # 匿名挂载
CMD echo "---end---"
CMD /bin/bash
# 可以通过dockerfile在镜像构建的时候就挂载目录!
[root@alibaba docker-test-volume]# docker build -f dockerfile -t coding/centos
docker build 镜像成功

运行容器,-it以交换模式进入容器,发现挂载的数据卷成功

docker inspect 命令查看容器的全部信息,查看datavolume01,datavolume02挂载在宿主机的目录
[root@alibaba docker-test-volume]# docker inspect ba4f46da4

发现自动挂载的卷,默认存在docker的路径下,随机生成一个id,十分难维护

挂载目录的3种方式
# 1、匿名挂载
-v 容器内的路径
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 缺点:在/var/lib/docker随机生成一个id目录!
# 2、具名挂载
-v 卷名:/容器内路径! -P 随机暴露宿主机的端口与容器内端口进行映射
docker run -d -P --name nginx01 -v nginxconfig:/etc/nginx:ro nginx
# 方便维护,知道自己的卷挂载的是什么!通常会使用具名挂载,它是在/var/lib/docker生成目录
# 3、指定目录挂载
-v /my/custom:/etc/mysql/conf.d
# 怎么目录挂载?具名挂载?
# 只要是 / 开头就是目录挂载,如果不是 /开头的就是一个具名挂载!
# 4、在有些情况下指定读写,:ro (只读) :rw(读写)
# 只要加了这个,在容器内不可修改此文件!只能通过外部挂载的地方来修改!
docker run -d -P --name nginx01 -v nginxconfig:/etc/nginx:ro nginx
# 查看挂载的数据卷
docker volumn --help

4、数据卷容器
把一个容器当做一个数据卷!实现容器之间的数据共享,集群配置的时候方便!
如果将一个容器作为目录卷挂载,共享一个容器中的数据!
测试,docker01与docker02共享数据
1、运行容器docker01
前面使用dockerfile创建了镜像coding/centos,运行起来,挂载的目录/datavolume01 和/datavolume02还在

# 在datavolume01创建一个文件docker01.txt
[root@cf8fd4d95671 datavolume01]# touch docker01.txt
2、运行容器docker02,指定挂载另外一个容器dokcer01的数据卷
--vloumes-form
[root@kuangshen volumes]# docker run -it --name docker02 --volumes-from docker01 cokding/centos

发现容器docker02里有数据卷datavolume01和datavolume02,cd到datavolume01,已经共享了文件docker01.txt。
同时容器docker02创建一个文件docker02.txt,回过头来看容器docker01的数据卷datavolume01就会把docker02.txt共享过来

所以容器docker01和docker02实现了数据的共享
3、在运行容器docker03,挂载docker01的数据卷

dokcer01.txt和docker02.txt已共享过来,创建dokcer03.txt
4、删除容器docker01
docker rm -f docker01

发现原容器删除之后,数据依旧会在新的容器存在!而且是持续传递的!
结论:
容器之间,可以实现配置共享,这个时候,数据卷的生命周期一直持续到没有容器使用它为止。
存储在本地的文件会一直保留!