Bootstrap

docker 详解

一、 Docker概述

1、基本介绍

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux机器上,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),我们用社区版就可以了。官网:https://docs.docker.com/

2、应用场景

  • Web 应用的自动化打包和发布。
  • 自动化测试和持续集成、发布。
  • 在服务型环境中部署和调整数据库或其他的后台应用。
  • 从头编译或者扩展现有的 OpenShift 或 Cloud Foundry 平台来搭建自己的 PaaS 环境。

3、Docker 的优势

Docker 是一个用于开发,交付和运行应用程序的开放平台。Docker 使您能够将应用程序与基础架构分开,从而可以快速交付软件。借助 Docker,您可以与管理应用程序相同的方式来管理基础架构。通过利用 Docker 的方法来快速交付,测试和部署代码,您可以大大减少编写代码和在生产环境中运行代码之间的延迟。

  • 快速,一致地交付您的应用程序。Docker 允许开发人员使用您提供的应用程序或服务的本地容器在标准化环境中工作,从而简化了开发的生命周期。

    容器非常适合持续集成和持续交付(CI / CD)工作流程,请考虑以下示例方案:

    您的开发人员在本地编写代码,并使用 Docker 容器与同事共享他们的工作。
    他们使用 Docker 将其应用程序推送到测试环境中,并执行自动或手动测试。
    当开发人员发现错误时,他们可以在开发环境中对其进行修复,然后将其重新部署到测试环境中,以进行测试和验证。测试完成后,将修补程序推送给生产环境,就像将更新的镜像推送到生产环境一样简单。

  • 响应式部署和扩展
    Docker 是基于容器的平台,允许高度可移植的工作负载。Docker 容器可以在开发人员的本机上,数据中心的物理或虚拟机上,云服务上或混合环境中运行。

    Docker 的可移植性和轻量级的特性,还可以使您轻松地完成动态管理的工作负担,并根据业务需求指示,实时扩展或拆除应用程序和服务。

  • 在同一硬件上运行更多工作负载
    Docker 轻巧快速。它为基于虚拟机管理程序的虚拟机提供了可行、经济、高效的替代方案,因此您可以利用更多的计算能力来实现业务目标。Docker 非常适合于高密度环境以及中小型部署,而您可以用更少的资源做更多的事情。

2. 虚拟化技术和容器化技术

虚拟化技术特点:1.资源占用多 2.冗余步骤多 3.启动很慢

容器化技术:容器化技术不是模拟的一个完整的操作系统

比较Docker和虚拟机的不同:

1.传统虚拟机,虚拟出硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件。

2.Docker容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有虚拟硬件。

3.每个容器都是相互隔离的,每个容器都有属于自己的文件系统,互不影响。

容器化带来的好处:

  • 应用更快速的交付和部署
  • 更便捷的升级和扩缩容
  • 更简单的系统运维
  • 更高效的计算资源利用

3. Docker的基本组成

Docker的基本组成图如下:

说明:

  • 镜像(image):

    docker 镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像—》run—》tomcat01 容器(提供服务器)通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中)

  • 容器(container):

    docker 利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的

    启动,停止,删除,基本命令

    目前就可以把这个容器理解为就是一个简易的 linux 系统

  • 仓库(repository):

    仓库就是存放镜像的地方

    仓库为公有的窗口和私有的仓库

    Docker Hub

4. Docker的安装

查看系统的内核:

uname -r

系统内核版本为3.10.0-514.26.2.el7.x86_64

查看系统配置

cat /etc/os-release
[root@izbp16oqont6wmaa5jso2yz ~]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

Docker的安装步骤:

(1)卸载旧的版本

yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

(2)下载需要的安装包

yum install -y yum-utils

(3)设置镜像的仓库

yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo  #国外的地址
    
    # 设置阿里云的Docker镜像仓库
yum-config-manager \
    --add-repo \
    https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo  #国外的地址

(4)更新yum软件包索引

yum makecache fast

(5)安装docker相关的配置

docker-ce 是社区版,docker-ee 企业版

 yum install docker-ce docker-ce-cli containerd.io

出现了completed即安装成功。

(6)启动Docker

systemctl start docker
# 查看当前版本号,是否启动成功
docker version
# 设置开机自启动
systemctl enable docker

结果:

[root@izbp16oqont6wmaa5jso2yz /]# docker version
Client: Docker Engine - Community
 Version:           20.10.11
 API version:       1.41
 Go version:        go1.16.9
 Git commit:        dea9396
 Built:             Thu Nov 18 00:38:53 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.11
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.9
  Git commit:       847da18
  Built:            Thu Nov 18 00:37:17 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.12
  GitCommit:        7b11cfaabd73bb80907dd23182b9347b4245eb5d
 runc:
  Version:          1.0.2
  GitCommit:        v1.0.2-0-g52b36a2
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

下载hello-world镜像进行测试

[root@izbp16oqont6wmaa5jso2yz /]# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete 
Digest: sha256:cc15c5b292d8525effc0f89cb299f1804f3a725c8d05e158653a563f15e4f685
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

查看下载的hello world镜像

[root@izbp16oqont6wmaa5jso2yz /]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    feb5d9fea6a5   2 months ago   13.3kB

5. Docker的卸载

# 1. 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
# 2. 删除资源  . /var/lib/docker是docker的默认工作路径
rm -rf /var/lib/docker

6. 配置阿里云镜像加速

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://axvfsf7e.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

7. Docker容器运行流程

启动一个容器,Docker的运行流程如下图:

8. 底层原理

Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上,通过Socker从客户端访问!Docker Server接收到Docker-Client的指令,就会执行这个指令!

Docker为什么比VM Ware快?

1、Docker比虚拟机更少的抽象层

2、docker利用宿主机的内核,VM需要的是Guest OS

Docker新建一个容器的时候,不需要像虚拟机一样重新加载一个操作系统内核,直接利用宿主机的操作系统,而虚拟机是需要加载Guest OS。Docker和VM的对比如下:

9. Docker常用命令

9.1 基础命令

docker version          #查看docker的版本信息
docker info             #查看docker的系统信息,包括镜像和容器的数量
docker 命令 --help       #帮助命令(可查看可选的参数)
docker COMMAND --help

9.2 镜像命令

  • docker images 查看本地主机的所有镜像
[root@izbp16oqont6wmaa5jso2yz /]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    feb5d9fea6a5   2 months ago   13.3kB

#解释:
1.REPOSITORY  镜像的仓库源

2.TAG  镜像的标签

3.IMAGE ID 镜像的id

4.CREATED 镜像的创建时间

5.SIZE 镜像的大小

# 可选参数

-a/--all 列出所有镜像

-q/--quiet 只显示镜像的id
  • docker search 搜索镜像
[root@izbp16oqont6wmaa5jso2yz /]# docker search mysql
NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                             MySQL is a widely used, open-source relation…   11748     [OK]       
mariadb                           MariaDB Server is a high performing open sou…   4478      [OK]       
mysql/mysql-server                Optimized MySQL Server Docker images. Create…   877                  [OK]
percona                           Percona Server is a fork of the MySQL relati…   564       [OK]       
phpmyadmin                        phpMyAdmin - A web interface for MySQL and M…   384       [OK]       
centos/mysql-57-centos7           MySQL 5.7 SQL database server                   92                   
mysql/mysql-cluster               Experimental MySQL Cluster Docker images. Cr…   89                   
centurylink/mysql                 Image containing mysql. Optimized to be link…   59                   [OK]
databack/mysql-backup             Back up mysql databases to... anywhere!         53                   
prom/mysqld-exporter                                                              43                   [OK]
deitch/mysql-backup               REPLACED! Please use http://hub.docker.com/r…   41                   [OK]
tutum/mysql                       Base docker image to run a MySQL database se…   35                   
linuxserver/mysql                 A Mysql container, brought to you by LinuxSe…   34                   
schickling/mysql-backup-s3        Backup MySQL to S3 (supports periodic backup…   31                   [OK]
mysql/mysql-router                MySQL Router provides transparent routing be…   23                   
centos/mysql-56-centos7           MySQL 5.6 SQL database server                   21                   
arey/mysql-client                 Run a MySQL client from a docker container      19                   [OK]
fradelg/mysql-cron-backup         MySQL/MariaDB database backup using cron tas…   16                   [OK]
openshift/mysql-55-centos7        DEPRECATED: A Centos7 based MySQL v5.5 image…   6                    
devilbox/mysql                    Retagged MySQL, MariaDB and PerconaDB offici…   3                    
ansibleplaybookbundle/mysql-apb   An APB which deploys RHSCL MySQL                3                    [OK]
jelastic/mysql                    An image of the MySQL database server mainta…   2                    
centos/mysql-80-centos7           MySQL 8.0 SQL database server                   2                    
widdpim/mysql-client              Dockerized MySQL Client (5.7) including Curl…   1                    [OK]
monasca/mysql-init                A minimal decoupled init container for mysql    0

#可选参数

Search the Docker Hub for images

Options:
  -f, --filter filter   Filter output based on conditions provided
      --format string   Pretty-print search using a Go template
      --limit int       Max number of search results (default 25)
      --no-trunc        Don't truncate output
      

#搜索收藏数大于3000的镜像
[root@izbp16oqont6wmaa5jso2yz /]# docker search mysql --filter=STARS=3000
NAME      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql     MySQL is a widely used, open-source relation…   11748     [OK]       
mariadb   MariaDB Server is a high performing open sou…   4478      [OK]  
  • docker pull 镜像名[:tag] 下载镜像
[root@izbp16oqont6wmaa5jso2yz /]# docker pull mysql
Using default tag: latest     #如果不写tag默认就是latest 	
latest: Pulling from library/mysql
a10c77af2613: Pull complete    #分层下载,docker image的核心-联合文件系统
b76a7eb51ffd: Pull complete 
258223f927e4: Pull complete 
2d2c75386df9: Pull complete 
63e92e4046c9: Pull complete 
f5845c731544: Pull complete 
bd0401123a9b: Pull complete 
3ef07ec35f1a: Pull complete 
c93a31315089: Pull complete 
3349ed800d44: Pull complete 
6d01857ca4c1: Pull complete 
4cc13890eda8: Pull complete 
Digest: sha256:aeecae58035f3868bf4f00e5fc623630d8b438db9d05f4d8c6538deb14d4c31b
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest    #下载来源的真实地址  #docker pull mysql等价于docker pull docker.io/library/mysql:latest

指定版本下载

[root@izbp16oqont6wmaa5jso2yz /]#  docker pull mysql:5.7
5.7: Pulling from library/mysql
a10c77af2613: Already exists 
b76a7eb51ffd: Already exists 
258223f927e4: Already exists 
2d2c75386df9: Already exists 
63e92e4046c9: Already exists 
f5845c731544: Already exists 
bd0401123a9b: Already exists 
2724b2da64fd: Pull complete 
d10a7e9e325c: Pull complete 
1c5fd9c3683d: Pull complete 
2e35f83a12e9: Pull complete 
Digest: sha256:7a3a7b7a29e6fbff433c339fc52245435fa2c308586481f2f92ab1df239d6a29
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
  • docker rmi 删除镜像
#1.删除指定的镜像id
[root@izbp16oqont6wmaa5jso2yz ~]# docker rmi -f  镜像id
#2.删除多个镜像id
[root@izbp16oqont6wmaa5jso2yz ~]# docker rmi -f  镜像id 镜像id 镜像id
#3.删除全部的镜像id
[root@izbp16oqont6wmaa5jso2yz ~]# docker rmi -f  $(docker images -aq)

9.3 容器命令

如拉取一个centos容器

docker pull centos

运行容器

docker run [可选参数] image

#参数说明
--name="名字"           指定容器名字
-d                     后台方式运行
-it                    使用交互方式运行,进入容器查看内容
-p                     指定容器的端口
(
-p ip:主机端口:容器端口  配置主机端口映射到容器端口
-p 主机端口:容器端口
-p 容器端口
)
-P                     随机指定端口(大写的P)

进入容器

[root@izbp16oqont6wmaa5jso2yz ~]# docker run -it centos /bin/bash
[root@858613ca7c96 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

退出容器

#exit 停止并退出容器(后台方式运行则仅退出)
#Ctrl+P+Q  不停止容器退出
[root@858613ca7c96 /]# exit
exit
[root@izbp16oqont6wmaa5jso2yz /]# 

列出运行过的容器

#docker ps 
     # 列出当前正在运行的容器
-a   # 列出所有容器的运行记录
-n=? # 显示最近创建的n个容器
-q   # 只显示容器的编号

[root@izbp16oqont6wmaa5jso2yz /]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@izbp16oqont6wmaa5jso2yz /]# docker ps -a
CONTAINER ID   IMAGE         COMMAND       CREATED          STATUS                      PORTS     NAMES
858613ca7c96   centos        "/bin/bash"   2 minutes ago    Exited (0) 54 seconds ago             loving_taussig
bee46b5c198b   hello-world   "/hello"      22 minutes ago   Exited (0) 22 minutes ago             nice_wright

删除容器

docker rm 容器id                 #删除指定的容器,不能删除正在运行的容器,强制删除使用 rm -f
docker rm -f $(docker ps -aq)   #删除所有的容器
docker ps -a -q|xargs docker rm #删除所有的容器

启动和停止容器

docker start 容器id          #启动容器
docker restart 容器id        #重启容器
docker stop 容器id           #停止当前运行的容器
docker kill 容器id           #强制停止当前容器

9.4 其他常用命令

  • 日志的查看:
[root@izbp16oqont6wmaa5jso2yz /]# docker logs --help

Usage:  docker logs [OPTIONS] CONTAINER

Fetch the logs of a container

Options:
      --details        Show extra details provided to logs
  -f, --follow         Follow log output
      --since string   Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
  -n, --tail string    Number of lines to show from the end of the logs (default "all")
  -t, --timestamps     Show timestamps
      --until string   Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)


常用:
docker logs -tf 容器id
docker logs --tail number 容器id #num为要显示的日志条数


#docker容器后台运行,必须要有一个前台的进程,否则会自动停止
#编写shell脚本循环执行,使得centos容器保持运行状态

[root@izbp16oqont6wmaa5jso2yz /]# docker run -d centos /bin/sh -c "while true;do echo hi;sleep 5;done"
fad4e4cfcdf8011ffb87c4af223a4def8bb56c4a915d0f2aae22fe7c36f4ea8f
[root@izbp16oqont6wmaa5jso2yz /]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
fad4e4cfcdf8   centos    "/bin/sh -c 'while t…"   18 seconds ago   Up 16 seconds             interesting_yalow

[root@izbp16oqont6wmaa5jso2yz /]# docker logs -tf --tail 10 fad4e4cfcdf8
2021-11-30T02:41:50.333740257Z hi
2021-11-30T02:41:55.335647423Z hi
2021-11-30T02:42:00.337543066Z hi
2021-11-30T02:42:05.339273910Z hi
2021-11-30T02:42:10.341044647Z hi
2021-11-30T02:42:15.342753069Z hi
2021-11-30T02:42:20.344723632Z hi
2021-11-30T02:42:25.346358519Z hi
2021-11-30T02:42:30.348062446Z hi
2021-11-30T02:42:35.349795650Z hi
2021-11-30T02:42:40.351508777Z hi
2021-11-30T02:42:45.353192496Z hi
2021-11-30T02:42:50.354857997Z hi
2021-11-30T02:42:55.356589223Z hi
2021-11-30T02:43:00.358487414Z hi
  • 查看容器中进程信息
[root@izbp16oqont6wmaa5jso2yz ~]# docker top c703b5b1911f
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                11156               11135               0                   11:31               ?                   00:00:00            /bin/sh -c while true;do echo hi;sleep 5;done
root                11886               11156               0                   11:43               ?                   00:00:00            /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 5
  • 查看容器的元数据
[root@izbp16oqont6wmaa5jso2yz ~]# docker inspect 容器id
  • 进入当前正在运行的容器

    因为通常我们的容器都是使用后台方式来运行的,有时需要进入容器修改配置

    方式一:

[root@izbp16oqont6wmaa5jso2yz ~]# docker exec -it c703b5b1911f /bin/bash
[root@858613ca7c96 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@c703b5b1911f /]# ps -ef      
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 03:31 ?        00:00:00 /bin/sh -c while true;do echo hi;sleep 5;done
root       279     0  0 03:54 pts/0    00:00:00 /bin/bash
root       315     1  0 03:56 ?        00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 5
root       316   279  0 03:56 pts/0    00:00:00 ps -ef

​ 方式二:

[root@izbp16oqont6wmaa5jso2yz ~]# docker attach c703b5b1911f

docker exec 进入容器后开启一个新的终端,可以在里面操作

docker attach 进入容器正在执行的终端,不会启动新的进程

拷贝容器的文件到主机中

docker cp 容器id:容器内路径 目的主机路径

[root@izbp16oqont6wmaa5jso2yz ~]# docker exec -it c703b5b1911f /bin/bash
[root@858613ca7c96 /]# cd home
[root@858613ca7c96 home]# ls
#touch 新建文件
[root@858613ca7c96 home]# touch test.java
[root@858613ca7c96 home]# ls
test.java
[root@c703b5b1911f home]# exit
exit
[root@izbp16oqont6wmaa5jso2yz ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
c703b5b1911f   centos    "/bin/sh -c 'while t…"   35 minutes ago   Up 35 minutes             pedantic_banach
[root@izbp16oqont6wmaa5jso2yz ~]# docker cp c703b5b1911f:/home/test.java /home
[root@izbp16oqont6wmaa5jso2yz ~]# ls /home
hai  pan  test.java

命令小结的图解如下:

10. Docker镜像详解

10.1 什么是镜像

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

10.2 Docker镜像加载原理

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

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

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

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

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

10.3 分层理解

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

[root@izbp16oqont6wmaa5jso2yz ~]# docker pull redis
Using default tag: latest
latest: Pulling from library/redis
eff15d958d66: Pull complete 
1aca8391092b: Pull complete 
06e460b3ba1b: Pull complete 
def49df025c0: Pull complete 
646c72a19e83: Pull complete 
db2c789841df: Pull complete 
Digest: sha256:619af14d3a95c30759a1978da1b2ce375504f1af70ff9eea2a8e35febc45d747
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest

为啥 Docker 镜像采用这种分层的结构呢?

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

查看镜像分层的方式可以通过 docker image inspect 命令

[root@izbp16oqont6wmaa5jso2yz ~]# docker image inspect redis
[
    {
        "Id": "sha256:40c68ed3a4d246b2dd6e59d1b05513accbd2070efb746ec16848adc1b8e07fd4",
        "RepoTags": [
            "redis:latest"
        ],
        "RepoDigests": [
            "redis@sha256:619af14d3a95c30759a1978da1b2ce375504f1af70ff9eea2a8e35febc45d747"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2021-11-17T23:55:32.992203883Z",
        "Container": "204dce7042f7d9b9ddfe3166f1fb31ab9e6796e9f85a61add0d162fa1b2af1d5",
        "ContainerConfig": {
            "Hostname": "204dce7042f7",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "6379/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "GOSU_VERSION=1.12",
                "REDIS_VERSION=6.2.6",
                "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.2.6.tar.gz",
                "REDIS_DOWNLOAD_SHA=5b2b8b7a50111ef395bf1c1d5be11e6e167ac018125055daa8b5c2317ae131ab"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"redis-server\"]"
            ],
            "Image": "sha256:f68fe14ac3ec56717680e0a1e8562ba7ec42aabcc9626615012304e2f18c5a84",
            "Volumes": {
                "/data": {}
            },
            "WorkingDir": "/data",
            "Entrypoint": [
                "docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": {}
        },
        "DockerVersion": "20.10.7",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "6379/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "GOSU_VERSION=1.12",
                "REDIS_VERSION=6.2.6",
                "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.2.6.tar.gz",
                "REDIS_DOWNLOAD_SHA=5b2b8b7a50111ef395bf1c1d5be11e6e167ac018125055daa8b5c2317ae131ab"
            ],
            "Cmd": [
                "redis-server"
            ],
            "Image": "sha256:f68fe14ac3ec56717680e0a1e8562ba7ec42aabcc9626615012304e2f18c5a84",
            "Volumes": {
                "/data": {}
            },
            "WorkingDir": "/data",
            "Entrypoint": [
                "docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": null
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 112704339,
        "VirtualSize": 112704339,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/79ddc136a5dafad37f136be013e6d46ca4c297b55078a581b667c48c2d0e2567/diff:/var/lib/docker/overlay2/f8adcd0b43cf5385c4a2857a2cfce1a003c04a652ef72150c74cca840fece768/diff:/var/lib/docker/overlay2/a2f88281181f6a7770fd70ad1865f1b453bd95bfd921d9a7586ada939e0b1d5c/diff:/var/lib/docker/overlay2/cdee6729b7975bde1f239e8d99de0ca980120b313e7d20f0c9ce8868ba9689f1/diff:/var/lib/docker/overlay2/a928c67db61c1eaf8439c38f7aa7c5b928010d2645a13eee2f8eb51b0fc54d46/diff",
                "MergedDir": "/var/lib/docker/overlay2/f7368939a93243eb249a4c06f26a208a500e1f03b795e88fca0d4349fb574bc0/merged",
                "UpperDir": "/var/lib/docker/overlay2/f7368939a93243eb249a4c06f26a208a500e1f03b795e88fca0d4349fb574bc0/diff",
                "WorkDir": "/var/lib/docker/overlay2/f7368939a93243eb249a4c06f26a208a500e1f03b795e88fca0d4349fb574bc0/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:e1bbcf243d0e7387fbfe5116a485426f90d3ddeb0b1738dca4e3502b6743b325",
                "sha256:58e6a16139eebebf7f6f0cb15f9cb3c2a4553a062d2cbfd1a782925452ead433",
                "sha256:503a5c57d9786921c992b7b2216ae58f69dcf433eedb28719ddea3606b42ce26",
                "sha256:277199a0027e044f64ef3719a6d7c3842e99319d6e0261c3a5190249e55646cf",
                "sha256:d0d567a1257963b9655dfceaddc76203c8544fbf6c8672b372561a3c8a3143d4",
                "sha256:a7115aa098139866d7073846e4321bafb8d5ca0d0f907a3c9625f877311bee7c"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

这里指示了分层信息:

"RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:e1bbcf243d0e7387fbfe5116a485426f90d3ddeb0b1738dca4e3502b6743b325",
                "sha256:58e6a16139eebebf7f6f0cb15f9cb3c2a4553a062d2cbfd1a782925452ead433",
                "sha256:503a5c57d9786921c992b7b2216ae58f69dcf433eedb28719ddea3606b42ce26",
                "sha256:277199a0027e044f64ef3719a6d7c3842e99319d6e0261c3a5190249e55646cf",
                "sha256:d0d567a1257963b9655dfceaddc76203c8544fbf6c8672b372561a3c8a3143d4",
                "sha256:a7115aa098139866d7073846e4321bafb8d5ca0d0f907a3c9625f877311bee7c"
            ]
        },

所有的 Docker 镜像都起始于一个基础镜像,当进项修改或增加新内容时,就会在镜像层之上,创建新的镜像层,举一个简单的例子,例如基于 Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python 包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层

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

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

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件,这样就使得文件的更新版本作为一个新的镜像层添加到镜像中,Docker 通过存储引擎(新版本采用快照进制)的方式来实现镜像层堆栈,并保证镜像层对外展示为统一的文件系统

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

Docker 在 Windows 上仅支持 windowsfileter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分成和 Cow[1],下图展示了与系统显示相同的三层镜像,所有镜像堆叠并合并,对外提供统一的视图

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

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

10.4 提交镜像

使用docker commit 命令提交容器成为一个新的版本

docker commit -m=“提交的描述信息”  -a="作者" 容器id 目标镜像名:[TAG] 

由于默认的Tomcat镜像的webapps文件夹中没有任何内容,需要从webapps.dist中拷贝文件到webapps文件夹。下面自行制作镜像:就是从webapps.dist中拷贝文件到webapps文件夹下,并提交该镜像作为一个新的镜像。使得该镜像默认的webapps文件夹下就有文件。具体命令如下:

#1.复制文件夹
[root@izbp16oqont6wmaa5jso2yz ~]# docker run -it tomcat /bin/bash
root@2a3bf3eaa2e4:/usr/local/tomcat# cd webapps
root@2a3bf3eaa2e4:/usr/local/tomcat/webapps# ls
root@2a3bf3eaa2e4:/usr/local/tomcat/webapps# cd ../
root@2a3bf3eaa2e4:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@2a3bf3eaa2e4:/usr/local/tomcat# cd webapps
root@2a3bf3eaa2e4:/usr/local/tomcat/webapps# ls
ROOT  docs  examples  host-manager  manager
[root@izbp16oqont6wmaa5jso2yz ~]# docker ps
CONTAINER ID   IMAGE                 COMMAND        CREATED         STATUS         PORTS                    NAMES
2a3bf3eaa2e4   tomcat                "/bin/bash"    4 minutes ago   Up 4 minutes   8080/tcp                 competent_torvalds
7789d4505a00   portainer/portainer   "/portainer"   24 hours ago    Up 24 hours    0.0.0.0:8088->9000/tcp   quirky_sinoussi
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker exec -it 2a3bf3eaa2e4 /bin/bash
root@2a3bf3eaa2e4:/usr/local/tomcat# cd webapps
root@2a3bf3eaa2e4:/usr/local/tomcat/webapps# ls
ROOT  docs  examples  host-manager  manager
root@2a3bf3eaa2e4:/usr/local/tomcat/webapps# cd ../
root@2a3bf3eaa2e4:/usr/local/tomcat# read escape sequence
[root@izbp16oqont6wmaa5jso2yz ~]# docker ps
CONTAINER ID   IMAGE                 COMMAND        CREATED         STATUS         PORTS                    NAMES
2a3bf3eaa2e4   tomcat                "/bin/bash"    8 minutes ago   Up 8 minutes   8080/tcp                 competent_torvalds
7789d4505a00   portainer/portainer   "/portainer"   24 hours ago    Up 24 hours    0.0.0.0:8088->9000/tcp   quirky_sinoussi
#2.提交镜像作为一个新的镜像

[root@izbp16oqont6wmaa5jso2yz ~]# docker commit -m="add webapps" -a="Ethan" 2a3bf3eaa2e4 mytomcat:1.0
sha256:f189aac861de51087af5bc88a5f1de02d9574e7ee2d163c647dd7503a2d3982b
[root@izbp16oqont6wmaa5jso2yz ~]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
mytomcat              1.0       f189aac861de   7 seconds ago   653MB
mysql                 5.7       f07dfa83b528   6 days ago      448MB
tomcat                latest    feba8d001e3f   10 days ago     649MB
nginx                 latest    ae2feff98a0c   12 days ago     133MB
centos                latest    300e315adb2f   2 weeks ago     209MB
portainer/portainer   latest    62771b0b9b09   5 months ago    79.1MB
elasticsearch         7.6.2     f29a1ee41030   9 months ago    791MB

#3.运行容器

[root@izbp16oqont6wmaa5jso2yz ~]# docker run -it mytomcat:1.0 /bin/bash
root@1645774d4605:/usr/local/tomcat# cd webapps
root@1645774d4605:/usr/local/tomcat/webapps# ls
ROOT  docs  examples  host-manager  manager
izbp16oqont6wmaa5jso2yz ~]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
mytomcat              1.0       f189aac861de   7 seconds ago   653MB
mysql                 5.7       f07dfa83b528   6 days ago      448MB
tomcat                latest    feba8d001e3f   10 days ago     649MB
nginx                 latest    ae2feff98a0c   12 days ago     133MB
centos                latest    300e315adb2f   2 weeks ago     209MB
portainer/portainer   latest    62771b0b9b09   5 months ago    79.1MB
elasticsearch         7.6.2     f29a1ee41030   9 months ago    791MB

好了,到这里我们 Docker 的入门就完成了!

7.6.2 f29a1ee41030 9 months ago 791MB

#3.运行容器

[root@izbp16oqont6wmaa5jso2yz ~]# docker run -it mytomcat:1.0 /bin/bash
root@1645774d4605:/usr/local/tomcat# cd webapps
root@1645774d4605:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
izbp16oqont6wmaa5jso2yz ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mytomcat 1.0 f189aac861de 7 seconds ago 653MB
mysql 5.7 f07dfa83b528 6 days ago 448MB
tomcat latest feba8d001e3f 10 days ago 649MB
nginx latest ae2feff98a0c 12 days ago 133MB
centos latest 300e315adb2f 2 weeks ago 209MB
portainer/portainer latest 62771b0b9b09 5 months ago 79.1MB
elasticsearch 7.6.2 f29a1ee41030 9 months ago 791MB


好了,到这里我们 Docker 的入门就完成了!

> 引用:https://www.bilibili.com/video/BV1og4y1q7M4
;