Docker继续学习二--原理到Dockerfile

一、Docker镜像原理

docker 的镜像实际上由一层一层的文件系统组成,这种层级的文件系统 UnionFS
bootfs(boot fifile system) 主要包含 bootloader kernel, bootloader 主要是引导加载 kernel, Linux 刚启
动时会加载 bootfs 文件系统,在 Docker 镜像的最底层是 bootfs 。这一层与我们典型的 Linux/Unix 系统是
一样的,包含 boot 加载器和内核。当 boot 加载完成之后整个内核就都在内存中了,此时内存的使用权已
bootfs 转交给内核,此时系统也会卸载 bootfs
rootfs (root fifile system) ,在 bootfs 之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标
准目录和文件。 rootfs 就是各种不同的操作系统发行版,比如 Ubuntu Centos 等等。

 分层理解

我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载!

为什么 Docker 镜像要采用这种分层的结构呢?
最大的好处,我觉得莫过于是资源共享了!比如有多个镜像都从相同的 Base 镜像构建而来,那么宿主机 只需在磁盘上保留一份base 镜像,同时内存中也只需要加载一份 base 镜像,这样就可以为所有的容器服 务了,而且镜像的每一层都可以被共享。 查看镜像分层的方式可以通过
docker image inspect 命令! 所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之 上,创建新的镜像层。
举一个简单的例子,假如基于 Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python 包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。 该镜像当前已经包含 3 个镜像层,如下图所示(这只是一个用于演示的很简单的例子)

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了 一个简单的例子,每个镜像层包含 3 个文件,而镜像包含了来自两个镜像层的 6 个文件

 

上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有 6 个文件,这是因为最上层中的文件 7 是文件 5 的一个更新版本。

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新 镜像层添加到镜像当中。
Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统 一的文件系统。
Linux 上可用的存储引擎有 AUFS Overlay2 Device Mapper Btrfs 以及 ZFS 。顾名思义,每种存储 引擎都基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker Windows 上仅支持 windowsfifilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分 层和 CoW[1]
下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图

 Docker镜像特点

Docker 镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层!
------------------------------------------------------------------------------------------------------------------------------

二、镜像Commit

docker commit 从容器创建一个新的镜像
#docker commit -m="描述镜像的信息"  -a ="作者"  容器id  要创建的目标镜像名:[标签名]
# 测试-->先从镜像仓库下载一个官方的Tomcat

 发现Tomcat下的Webapps里面是没有Root的目录的, 所以访问IP:8080 是404页面..

此时我们可以使用exec -it 容器id /bin/bash 进入tomcat容器内部,将webapps.dist里面的文件复制到webapps文件中,使得该文件里有Root, 并且将DOSC删掉.

docker ps # 查看容器
id docker exec -it 容器id /bin/bash /usr/local/tomcat # cd webapps/ 
/usr/local/tomcat/webapps # ls -l # 查看是否存在 docs文件夹 
/usr/local/tomcat/webapps # curl localhost:8080/docs/ # 可以看到 docs 返回的内容
/usr/local/tomcat/webapps # rm -rf docs # 删除它 
/usr/local/tomcat/webapps # curl localhost:8080/docs/ # 再次访问返回404

#提交自制的强化版的Tomcat  , 此时我们的webapps里面已经有Root并且没有DOCS了.

docker commit -a="alenwong" -m="this its no docs tomcat"  tomcatnew:1.1

[root@localhost alenwong]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
tomcat                latest    46cfbf1293b1   43 hours ago     668MB
nginx                 latest    4cdc5dd7eaad   2 weeks ago      133MB
mysql                 5.7       09361feeb475   4 weeks ago      447MB
portainer/portainer   latest    580c0e4e98b0   4 months ago     79.1MB
hello-world           latest    d1165f221234   4 months ago     13.3kB
centos                latest    300e315adb2f   7 months ago     209MB
[root@localhost alenwong]# docker commit -a="alenwong" -m="thisits no docs tomcat" 46cfbf1293b1 tomcatnew:1.1

提交完成后,直接启动新的镜像容器,访问就有页面了。

 三、数据容器卷

问题:你安装一个 MySQL ,结果你把容器删了,就相当于删库跑路了,这 TM 也太扯了吧!
所以我们希望容器之间有可能可以共享数据, Docker 容器产生的数据,如果不通过 docker commit 生成 新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了!这样是行 不通的! 为了能保存数据在Docker 中我们就可以使用卷!让数据挂载到我们本地!这样数据就不会因为容器删除 而丢失了。
卷就是目录或者文件,存在一个或者多个容器中,由 docker 挂载到容器,但不属于联合文件系统,因此 能够绕过 Union File System , 提供一些用于持续存储或共享数据的特性:
卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此 Docker 不会在容器删除时删除其挂 载的数据卷。
特点:
1、数据卷可在容器之间共享或重用数据
2、卷中的更改可以直接生效
3、数据卷中的更改不会包含在镜像的更新中
4、数据卷的生命周期一直持续到没有容器使用它为止

方式一,挂载

docker run -it -v 服务器绝对路径目录:容器内目录 镜像名

这里现在Linux主机创建一个文件夹进行测试

[root@localhost alenwong]# cd /home/
[root@localhost home]# ls 
alenwong
[root@localhost home]# mkdir guazaitest
[root@localhost home]# ll
总用量 4
drwx------. 16 alenwong alenwong 4096 7月  25 11:40 alenwong
drwxr-xr-x.  2 root     root        6 7月  25 13:05 guazaitest   #创建一个挂载测试文件夹

#docker run -it -v 宿主机绝对路径:需要挂载的容器路径   镜像名  操作后台
[root@localhost home]# docker run -it -v /home/guazaitest:/home centos /bin/bash #挂载指令
[root@88145a9d4692 /]# cd /home/
[root@88145a9d4692 home]# touch test2.txt
[root@88145a9d4692 home]# ls
test2.txt

在创建了test2.txt后 到第二个session窗口 看看Linux是否有这个文件?

 挂载成功。可以通过docker insepct 容器id 查看 是否挂载成功: 如下图

测试容器停止退出后,主机修改数据也是会同步!
1. 停止容器
2. 在宿主机上修改文件,增加些内容
3. 启动刚才停止的容器
4. 然后查看对应的文件,发现数据依旧同步! ok
停止了

 修改文件

 

启动再查看后...

 匿名与具名挂载

# 匿名挂载 
-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx

# 匿名挂载的缺点,就是不好维护,通常使用命令 docker volume维护
docker volume ls

# 具名挂载 -v 卷名:/容器内路径 
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx nginx 

# 查看挂载的路径 
[root@kuangshen ~]# docker volume inspect nginxconfig 
[ 
    { 
        "CreatedAt": "2020-05-13T17:23:00+08:00", 
        "Driver": "local", 
        "Labels": null, 
        "Mountpoint": "/var/lib/docker/volumes/nginxconfig/_data", 
        "Name": "nginxconfig", 
        "Options": null, 
        "Scope": "local" 
                            } ]

# 怎么判断挂载的是卷名而不是本机目录名? 
不是/开始就是卷名,是/开始就是目录名

# 改变文件的读写权限 
# ro: readonly 
# rw: readwrite 
# 指定容器对我们挂载出来的内容的读写权限 
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:ro nginx 
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:rw nginx

ro = 只读权限
rw = 读写权限

但是用MYSQL的话,只要删除容器,那么数据就会丢失,显然不可行,这里我们进入

方式二、DockerFile方式进行学习

DockerFile 是用来构建 Docker 镜像的构建文件,是由一些列命令和参数构成的脚本
#命令:
docker build -f dockerfile的绝对路径 -t 镜像名称:版本号 .  (注意那个点不要漏了)
[root@localhost docker-test-volume]# pwd
/home/docker-test-volume
[root@localhost docker-test-volume]# vim dockerfile1 
[root@localhost docker-test-volume]# cat dockerfile1 
FROM centos #来自centos基底
VOLUME ["volumn01","VOLUMN02"] #挂载路径
CMD echo "---------------end----------"
CMD /bin/bash


#docker build -f 是dockerfile的绝对路径  -t 是目标镜像名字 : 版本号 即TAG
[root@localhost docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile1  -t alenwong/centos:1.0 .

#执行过程
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos
 ---> 300e315adb2f
Step 2/4 : VOLUME ["volumn01","VOLUMN02"]
 ---> Running in ddcd857cec8b
Removing intermediate container ddcd857cec8b
 ---> 07a38f5a1f62
Step 3/4 : CMD echo "---------------end----------"
 ---> Running in 9589d8def621
Removing intermediate container 9589d8def621
 ---> c856b8b4975f
Step 4/4 : CMD /bin/bash
 ---> Running in d6fc4d6b0cff
Removing intermediate container d6fc4d6b0cff
 ---> 8f2c3218f044
Successfully built 8f2c3218f044
Successfully tagged alenwong/centos:1.0
[root@localhost docker-test-volume]# 

创建成功

 如何找到这个容器对应的服务器路径呢?? 我们先找到目前运行中的容器..看看id,然后

docker inspect 这个容器id 就可以找到卷挂载的路径了.

 在Linux卷目录中同步成功

 数据卷容器

--volumes-form

 

 先启动一个父容器

 再创建docker02和03 让他们继承docker01  --volumes-form

[root@localhost docker-test-volume]# docker ps
CONTAINER ID   IMAGE                 COMMAND        CREATED      STATUS       PORTS                                       NAMES
da182c3fdf28   portainer/portainer   "/portainer"   4 days ago   Up 3 hours   0.0.0.0:8088->9000/tcp, :::8088->9000/tcp   distracted_torvalds
[root@localhost docker-test-volume]# clear
[root@localhost docker-test-volume]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
alenwong/centos       1.0       b32442cbdd6c   36 minutes ago   209MB
tomcatnew             1.1       3507faca9348   2 hours ago      670MB
tomcat                latest    46cfbf1293b1   45 hours ago     668MB
nginx                 latest    4cdc5dd7eaad   2 weeks ago      133MB
mysql                 5.7       09361feeb475   4 weeks ago      447MB
portainer/portainer   latest    580c0e4e98b0   4 months ago     79.1MB
hello-world           latest    d1165f221234   4 months ago     13.3kB
centos                latest    300e315adb2f   7 months ago     209MB
[root@localhost docker-test-volume]# docker run -it --name docker01 b32442cbdd6c

#创建docker02
[root@localhost docker-test-volume]# docker run -it --name docker02 --volumes-from docker01 alenwong/centos:1.0
[root@0274106f2c4d /]# [root@localhos

#创建docker03
[root@localhost docker-test-volume]# docker run -it --name docker03 --volumes-from docker01 alenwong/centos:1.0
[root@44ed54af47d2 /]# cd home/ 
#进入容器后,看看挂载的数据卷
[root@44ed54af47d2 /]# ls -l
total 0
lrwxrwxrwx.   1 root root   7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x.   5 root root 360 Jul 25 06:47 dev
drwxr-xr-x.   1 root root  66 Jul 25 06:47 etc
drwxr-xr-x.   2 root root   6 Nov  3  2020 home
lrwxrwxrwx.   1 root root   7 Nov  3  2020 lib -> usr/lib
lrwxrwxrwx.   1 root root   9 Nov  3  2020 lib64 -> usr/lib64
drwx------.   2 root root   6 Dec  4  2020 lost+found
drwxr-xr-x.   2 root root   6 Nov  3  2020 media
drwxr-xr-x.   2 root root   6 Nov  3  2020 mnt
drwxr-xr-x.   2 root root   6 Nov  3  2020 opt
dr-xr-xr-x. 230 root root   0 Jul 25 06:47 proc
dr-xr-x---.   2 root root 162 Dec  4  2020 root
drwxr-xr-x.  11 root root 163 Dec  4  2020 run
lrwxrwxrwx.   1 root root   8 Nov  3  2020 sbin -> usr/sbin
drwxr-xr-x.   2 root root   6 Nov  3  2020 srv
dr-xr-xr-x.  13 root root   0 Jul 25 03:32 sys
drwxrwxrwt.   7 root root 145 Dec  4  2020 tmp
drwxr-xr-x.  12 root root 144 Dec  4  2020 usr
drwxr-xr-x.  20 root root 262 Dec  4  2020 var
drwxr-xr-x.   2 root root   6 Jul 25 06:43 volumn01  #数据卷
drwxr-xr-x.   2 root root   6 Jul 25 06:43 volumn02  #数据卷
#在docker03 里的volumn01创建文件...
[root@44ed54af47d2 /]# cd volumn01
[root@44ed54af47d2 volumn01]# ls
[root@44ed54af47d2 volumn01]# touch docker03

在子容器docker03的数据卷目录内 创建了一个文件..看看父容器是否有

 注意:容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。

存储在本机的文件则会一直保留! (即系 只要有一个容器有这个文件, 这个文件会一直保留, 哪怕你突然删除其中一个容器。  但是删除其中一个文件,即会同步删除了。)

DockerFile正式学习

DockerFel基础知识:

1 、每条保留字指令都必须为大写字母且后面要跟随至少一个参数
2 、指令按照从上到下,顺序执行
3 # 表示注释
4 、每条指令都会创建一个新的镜像层,并对镜像进行提交

流程:

1、docker从基础镜像运行一个容器

2、执行一条指令并且对容器做出修改

3、执行类似docker commit 的操作提交一个新的镜像层

4、Docker再基于刚刚提交的镜像运行一个新容器

5、执行dockerfile中的下一条指令知道所有指令都执行完成!

说明:

从应用软件的角度来看,DockerFile,docker镜像与docker容器分别代表软件的三个不同阶段。

  • DcokerFile是软件的原材料(代码)
  • Dcoker镜像则是软件的交付品(.apk)
  • Dcoker容器则是软件的运行转改(客户下载安装执行)

DockerFile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可。

DockerFile指令

FROM                     #基础镜像,当前新镜像是基于哪个镜像的

MAINTAINER         #镜像维护者的姓名+邮箱地址

RUN                       #容器构建时需要运行的命令

EXPOSE               #当前容器对外保留出的端口

WORKDIR            #指定在创建容器后,终端默认登陆进来的工作目录, 一个落脚点

ENV                     #构建过程中设置环境变量的

ADD                    #将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL或解压tar压缩包

COPY                 #类似ADD , 拷贝文件和目录到镜像中

VOLUME           # 容器数据卷,用于数据保存和持久化的工作

CMD                 #指定一个容器启动时要运行的命令,dockerFile中可以有多个CMD命令,但是只有最后一个生效。

ENTRYPOINT     #指定一个容器启动时要运行的命令,和CMD一样

CMD和ENTRYPOINT的区别

CMD Dockerfifile 中可以有多个 CMD 指令,但只有最后一个生效 CMD 会被 docker run 之后的参数 替换!
ENTRYPOINT docker run 之后的参数会被当做参数传递给 ENTRYPOINT ,之后形成新的命令组合(即是可以追加)

ONBUILD            #当构建一个被继承的DockerFile时运行命令,父镜像在子镜像继承后,父镜像ONBUILD被触发

构建DockerFile指令

docker build -f DockerFile路径  -t 镜像名字:tag版本号 .

注意:!!  当DockerFile文件名为 DockerFile后, 不需要-f docker build会自动去识别DockerFile文件!!!!

 试试用DockerFile创建一个增强的Centos

原本下载的Cetnos没有任何命令拆件。。。

创建一个DockerFile文件进行增强

 文件内容

 

 利用DockerFile构建一个新的镜像

 构建完成后, 看看自己造的centos。。已经有增强了。

查看镜像地的变更历史

 docker history 镜像id

 练习: 自定义制作TOMCAT

先用rz上传 JDK和TOMCAT9 的压缩包

 2. 编写DockerFile文件

vim Dockerfile :

 创建刚刚写的DockerFile镜像

 搞掂..即刻运行一下

 启动自定义tomcat!!!!!!!!!

docker images
REPOSITORY             TAG       IMAGE ID       CREATED             SIZE
diytomcatgogogo        latest    c904850b0018   5 minutes ago       614MB
alencentos/havetools   1.0       09d2bcc3a56d   About an hour ago   302MB
alenwong/centos        1.0       b32442cbdd6c   4 hours ago         209MB
tomcatnew              1.1       3507faca9348   6 hours ago         670MB
tomcat                 latest    46cfbf1293b1   2 days ago          668MB
nginx                  latest    4cdc5dd7eaad   2 weeks ago         133MB
mysql                  5.7       09361feeb475   4 weeks ago         447MB
portainer/portainer    latest    580c0e4e98b0   4 months ago        79.1MB
hello-world            latest    d1165f221234   4 months ago        13.3kB
centos                 latest    300e315adb2f   7 months ago        209MB

#启动容器
#第一个-v  挂载webapps到宿主机
#第二个-v  挂载日志.

[root@localhost dev]# docker run -d -p 9090:8080 --name mydiytomcat -v /home/dev/build/tomcat/test:/usr/local/apache-tomcat-9.0.50/webapps/test -v /home/dev/build/tomcat/tomcat9logs/:/usr/local/apache-tomcat-9.0.50/logs --privileged=true diytomcatgogogo
15698eb3eaa237056549cb38fd647fb76acdb01a4ecefb5222aa42e0b8900edd

测试可访问后,可以加入以下东西令页面有东西可以访问.

#web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>test</display-name>

 </web-app>
#jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
<title>hello,alenwong</title> 
</head> 
<body> -----------welcome------------ 
<%=" my docker tomcat,kuangshen666 "%> <br> <br> <% System.out.println("-------my docker tomcat-------");%> </body> </html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值