飞天班第44节:Docker精通-2

2020/06/06

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 

发现原容器删除之后,数据依旧会在新的容器存在!而且是持续传递的!

结论:

容器之间,可以实现配置共享,这个时候,数据卷的生命周期一直持续到没有容器使用它为止。

存储在本地的文件会一直保留!

Post Directory