docker小笔记(镜像实战、DockerFile)

可视化

  • portainer (先用这个)

docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
  • Rancher(CI/CD再用)

 

什么是portainer ?

Docker图形化界面管理工具!提供一个后台面板供我们操作!

docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

访问测试:外网8088

通过它来访问

image-20211123184350130

进入之后的面板:

image-20211123185148299

可视化面板平时不使用,这里爷就vanvan(doge

 

Docker镜像

镜像是什么

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

所有的应用,直接打包docker镜像,就可以直接跑起来!

如何得到镜像:

  • 从远程仓库下载

  • 朋友拷贝

  • 自己制作一个镜像DockerFile

 

Docker镜像加载原理

UnionFS(联合文件系统)

我们下载的时候看到的一层一层就是这个!

Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

 

Docker镜像加载原理:

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。

bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

平时安装虚拟机系统都是好几个G,为什么Docker这里才100+M?

image-20211123191712830

对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootf就可以了。由此可见对于不同的Linux发行版,bootf基本是一致的,rootf会有差别,因此不同的发行版可以共用bootf。

虚拟机是分钟级别,容器是秒级!

 

分层理解

分层的镜像

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

image-20211123192243760

思考:Docker镜像为何要采用这种分层结构呢?

最大的好处?莫过于是资源共享罢!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

[
  //......
       "RootFS": {
           "Type": "layers",
           "Layers": [              "sha256:e1bbcf243d0e7387fbfe5116a485426f90d3ddeb0b1738dca4e3502b6743b325",
               "sha256:58e6a16139eebebf7f6f0cb15f9cb3c2a4553a062d2cbfd1a782925452ead433",
               "sha256:503a5c57d9786921c992b7b2216ae58f69dcf433eedb28719ddea3606b42ce26",
               "sha256:277199a0027e044f64ef3719a6d7c3842e99319d6e0261c3a5190249e55646cf",
               "sha256:d0d567a1257963b9655dfceaddc76203c8544fbf6c8672b372561a3c8a3143d4",
               "sha256:a7115aa098139866d7073846e4321bafb8d5ca0d0f907a3c9625f877311bee7c"
          ]
      },
       "Metadata": {
           "LastTagTime": "0001-01-01T00:00:00Z"
      }
  }
]

理解:

所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。

举一个简单的例子,假如基于 Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python 包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。

该镜像当前已经包含 3 个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。

基于Ubuntu Linux 16.04创建镜像

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

添加额外的镜像层后的镜像

上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。

下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有 6 个文件,这是因为最上层中的文件 7 是文件 5 的一个更新版本。

三层镜像

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。

Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。

Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顾名思义,每种存储引擎都基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。

Docker 在 Windows 上仅支持 windowsfilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和 CoW[1]。

下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。

从系统角度看三层镜像

特点

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!

这一层就是我们通常说的容器层,容器之下的都叫镜像层!

image-20211123195739169

 

如何提交一个自己的镜像

commit镜像

docker commit 提交容器成为一个新的副本

#命令和Git原理相似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]

实战测试

#1、启动一个默认的tomcat

#2、发现这个默认的tomcat 是没有webapps应用, 镜像的原因,官方的镜像默认 webapps下面是没有文件的!

#3、爷自己拷贝进去了基本的文件

#4、将我们操作过的容器通过commit提交为一个镜像!我们以后就使用我们修改过的镜像计科,这就是我们自己的一个修改的镜像

image-20211123201313797

 

学习方式说明:理解概念,但是一定要实践,最后实践和理论相结合一次搞定这个知识

如果想要保存当前容器的状态,就可以通过commit提交,获得一个镜像,
就好比VM快照!

到了这里才算是入门docker~ 要多加认真吸收练习~

 

容器数据卷

什么是容器数据卷

docker的理念回顾

将应用和环境打包成一个镜像!

数据?如果数据都在容器中,那么我们容器删除,数据就会丢失! 需求:数据可以持久化

就像...MySQL,容器删了,删库跑路ovo 需求:MySQL数据可以存储在本地

容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!

这就是卷技术!目录的挂载,将我们容器内的目录,挂载到Linux上面!image-20211123204147049

总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的!

 

使用数据卷

方式一:直接使用命令来挂载 -v

docker run -it -v 主机目录:容器内目录 

#测试
hadoop@hzk-VirtualBox:/home$ docker run -it -v /home/test:/home centos /bin/bash

#启动起来的时候我们可以通过 docker inspect 容器id 确认(是否已挂载

image-20211123210507021

测试文件的同步

image-20211123211327753

再来测试!

  1. 停止容器

  2. 宿主机上修改文件

  3. 启动容器

  4. 容器内的数据依旧是同步的

image-20211125103410044

好处:我们以后修改只需要在本地修改即可,内容会自动同步!

 

实战:安装MySQL

思考:MySQL的数据持久化问题

#获取镜像
root@hzk-VirtualBox:~# docker pull mysql

#运行容器,需要做数据挂载
#安装启动mysql,需要配置密码,需要注意
#官方测试:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

#启动
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
--name 容器名字
root@hzk-VirtualBox:~# 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

假设将容器删除

挂载到本地的数据卷依旧没有丢失,实现了容器数据持久化功能

 

具名和匿名挂载

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

# 查看所有的 volume 的情况
root@hzk-VirtualBox:~# docker volume ls
local 44e45019a3102a89916ad587d0bb8e43118fd92cc7a4d8a14d26658a3f6127ff

# 这里发现,这种就是匿名挂载,我们在 -v 只写了容器内的路径,没有写容器外的路径!

# 具名挂载
root@hzk-VirtualBox:/home# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
c62fadbb714a4d078f039088d612213c06a720cdf649b8ca54d797a87c440fe8
root@hzk-VirtualBox:/home# docker volume ls
DRIVER VOLUME NAME
local juming-nginx

# 通过 -v 卷名:容器内路径
# 查看一下这个卷

image-20211125234822075

所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxxx/_data下面

我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用的具名挂载

# 如何确定是匿名挂载还是具名挂载,还是指定路径挂载
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径::容器内路径 #指定路径挂载

拓展:

# 通过 -v 容器内路径:ro  rw 改变读写权限
ro readonly # 只读
rw readwrite # 可读可写

# 一旦这个设置了容器权限,容器对我们挂载出来的内容就有限定了!
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx

# ro 只要看到ro就说明这个路径只能通过宿主机来操作,宿主机内部无法操作!

 

初识DockerFile

DockerFile 就是用来构建docker镜像的构建文件!命令脚本!先体验一下!

通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每个命令都是一层!

# 创建一个dockerfile文件,名字可以随机,建议Dockerfile
# 文件中的内容 指令(大写) 参数
FROM cetos

VOLUME ["volume01","volume02"] # 构建镜像的时候直接进行挂载

CMD echo "-----end----"

CMD /bin/bash

# 这里的每个命令,就是镜像的一层!

image-20211126210836284

# 启动一下自己写的容器

image-20211126212411956

这个卷和外部一定有一个同步的目录!

image-20211126212955470

查看一下卷挂载的路径:

image-20211126213142432

测试一下刚才的文件是否同步!

image-20211126214205162

这种方式未来使用的十分多,因为我们通常会构建自己的镜像!

假设构建镜像时候没有挂载卷,要手动镜像挂载 -v 卷名:容器为路径!

 

数据卷容器

两个mysql同步数据!

image-20211126215141707

# 启动3个容器,通过刚才自己写的镜像启动

image-20211126220745395

# --volumes-from 
只要通过它就可以实现容器间的数据共享了
# 测试:可以删除docker01,查看一下docker02和docker03是否还可以访问这个文件
# 测试依旧可以访问

 

多个mysql实现数据共享

root@hzk-VirtualBox:~# docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql

root@hzk-VirtualBox:~# docker run -d -p 3311:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql

# 这个时候,可以实现两个容器数据同步!

 

结论:

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

但是一旦持久化到了本地,这个时候,本地的数据是不会删除的!

 

 

DockerFile

DockerFile介绍

dockerfile是用来构建docker镜像的文件!命令参数脚本!

构建步骤:

  1. 编写一个 dockerfile 文件

  2. docker build 构建成为一个镜像

  3. docker run 运行镜像

  4. docker push 发布镜像(DockerHub、阿里云镜像仓库!)

查看一下官方是怎么做的

image-20211126224732433

 

image-20211126225125584

很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!

官方既然可以制作镜像,那我们也可以!

 

DockerFile构建过程

基础知识:

1、 每个保留关键字(指令)都必须是大写字母

2、 执行从上到下顺序执行

3、 # 表示注释

4、 每一个指令都会创建提交一个新的镜像层,并提交!

image-20211126230059659

dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!

Docker镜像逐渐成为企业交付的标准,必须要掌握!

步骤:开发,部署,运维。。。缺一不可!

DockerFile:构建文件,定义了一切的步骤,源代码

Dockerimages: 通过DockerFile 构建生成的镜像,最终发布和运行的产品!

Docker容器: 容器就是镜像运行起来提供服务器

 

DockerFile的指令

以前的话我们就是使用别人的,现在我们知道了这些指令后,我们来练习自己写一个镜像!

FROM         # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤,tomcat镜像,这个tomcat压缩包!添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 暴露端口配置
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的指令,触发指令
COPY # 类似ADD,将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量!

 

image-20211126230952190

 

实战测试

Docker Hub 中 99%镜像都是从这个基础镜像过来的 FROM scratch,然后配置需要的软件和配置来进行的构建

image-20211126232618214

创建一个自己的centos

# 1、 编写DockerFile的文件
root@hzk-VirtualBox:/home/dockerfile# cat mydockerfile-centos
FROM centos
MAINTAINER hzk<1829044988@qq.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash

# 2、 通过这个文件构建镜像
# 命令 docker build -f dockerfile文件路径 -t 镜像名:[tag]
Successfully built 64db56109408
Successfully tagged mycentos:0.1

# 3、 测试运行

对比之前原生的centos:

image-20211127002031548

增加内容之后的镜像:

image-20211127002321319

我们可以列出本地进行的变更历史

image-20211127002540112

我们平时拿到一个镜像,可以研究一下它是怎么做的

 

CMD

CMD          #指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令

测试cmd

root@hzk-VirtualBox:/home/dockerfile# vim dockerfile-cmd-test

FROM centos
CMD ["ls","-a"]

# 构建镜像
root@hzk-VirtualBox:/home/dockerfile# docker build -f dockerfile-cmd-test -t cmdtest .

# run运行 , 发现我们的ls -a 命令生效
root@hzk-VirtualBox:/home/dockerfile# docker run 2ce74924223b
.
..
.dockerenv
bin
dev
etc
home
lib
lib64

# 想追加一个命令 -l (ls -al)
root@hzk-VirtualBox:/home/dockerfile# docker run 2ce74924223b -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.

# cmd的情况下 -l替换了CMD ["ls","-a"] 命令,而-l不是命令所以报错

测试ENTRYPOINT

root@hzk-VirtualBox:/home/dockerfile# vim docker-cmd-entrypoint

ENTRYPOINT ["ls","-a"]

root@hzk-VirtualBox:/home/dockerfile# docker build -f docker-cmd-entrypoint -t entrypoint-test .
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM centos
---> 5d0da3dc9764
Step 2/2 : ENTRYPOINT ["ls","-a"]
---> Running in 13ff3c0fd594
Removing intermediate container 13ff3c0fd594
---> b0be100c46d7
Successfully built b0be100c46d7
Successfully tagged entrypoint-test:latest
root@hzk-VirtualBox:/home/dockerfile# docker run b0be100c46d7
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

# 我们的追加命令,是直接拼接在我们的 ENTRYPOINT 命令的后面!
root@hzk-VirtualBox:/home/dockerfile# docker run b0be100c46d7 -l
total 56
drwxr-xr-x 1 root root 4096 Nov 26 16:45 .
drwxr-xr-x 1 root root 4096 Nov 26 16:45 ..
-rwxr-xr-x 1 root root 0 Nov 26 16:45 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 340 Nov 26 16:45 dev
drwxr-xr-x 1 root root 4096 Nov 26 16:45 etc
drwxr-xr-x 2 root root 4096 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 4096 Sep 15 14:17 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 207 root root 0 Nov 26 16:45 proc
dr-xr-x--- 2 root root 4096 Sep 15 14:17 root
drwxr-xr-x 11 root root 4096 Sep 15 14:17 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Nov 26 13:20 sys
drwxrwxrwt 7 root root 4096 Sep 15 14:17 tmp
drwxr-xr-x 12 root root 4096 Sep 15 14:17 usr
drwxr-xr-x 20 root root 4096 Sep 15 14:17 var

DockerFile中很多命令都十分的相似,我们需要了解它们的区别,我们最好的学习就是对比它们然后测试效果!

 

实战:Tomcat镜像

1、 准备镜像文件 tomcat压缩包,jdk的压缩包!

2、 编写DockerFile文件

 

 

 

 

 

 

 

 

 

Docker网络

 

企业实战

 

Docker Compose

 

Docker Swarm

 

CI/CD Jenkins流水线!

 

 

 

posted @ 2021-12-01 18:46  雪糕sama  阅读(222)  评论(0编辑  收藏  举报