Docker笔记01:常用命令、数据卷、部署应用、制作镜像

一、Docker 简介

1.1 应用部署的环境问题

在 Java 大型项目的开发中,微服务虽然具备各种各样的优势,但服务的拆分通用给部署带来了很大的麻烦。

可以说项目越大,运行环境也越复杂,部署时就会遇到:

  • 依赖关系复杂,容易出现兼容性问题
    • 比如:分布式系统中,依赖的组件非常多,不同组件之间部署时往往会产生一些冲突。
  • 开发、测试、生产环境的差异,不同机器硬件导致的差异
    • 比如:在数百上千台服务中重复部署,环境不一定一致,会遇到各种问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8mgOimLL-1640568727780)(image/image-20211110085402911.png)]

如上图:一个项目中,部署时需要依赖于 node.js、Redis、RabbitMQ、MySQL 等,这些服务部署时所需要的函数库、依赖项各不相同,甚至会有冲突,给部署带来了极大的困难。


1.2 Docker 如何解决问题

1.2.1 解决依赖兼容

Docker 为了解决依赖的兼容问题的,采用了两个手段:

  • 将应用的 Libs(函数库)、Deps(依赖)、配置与应用一起打包
  • 将每个应用放到一个隔离容器去运行,避免互相干扰

这样打包好的应用包中,既包含应用本身,也包含应用所需要的 Libs、Deps,无需再操作系统上安装这些,自然就不存在不同应用之间的兼容问题了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h8T4Caot-1640568727783)(image/image-20211110091320605.png)]

虽然解决了不同应用的兼容问题,但是开发、测试等环境会存在差异,操作系统版本也会有差异,怎么解决这些问题呢?


1.2.2 解决操作系统环境

要解决不同操作系统环境差异问题,必须先了解操作系统结构。以一个 Ubuntu 操作系统为例,结构如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TfkyS3Og-1640568727784)(image/image-20211110091719783.png)]

结构包括:

  • 计算机硬件:例如 CPU、内存、磁盘等
  • 系统内核:内核可以与计算机硬件交互,对外提供内核指令,用于操作计算机硬件。
  • 系统应用:操作系统本身提供的应用、函数库。这些函数库是对内核指令的封装,使用更加方便。

而应用于计算机交互的流程如下:

  • 应用调用操作系统应用(函数库),实现各种功能
  • 系统函数库是对内核指令集的封装,会调用内核指令
  • 内核指令操作计算机硬件

举例:Ubuntu 和 CentOS 都是基于 Linux 内核,无非是系统应用不同,提供的函数库有差异,那如果将一个Ubuntu 版本的 MySQL 安装到 CentOS 上,MySQL 在调用 Ubuntu 函数库时,会发现找不到或者不匹配,如图:
在这里插入图片描述

那 Docker 如何解决不同系统环境的问题?

  • Docker 将用户程序与所需要调用的系统(比如 Ubuntu)函数库一起打包
  • 当 Docker 运行到不同操作系统时,直接基于打包的函数库,借助于操作系统的 Linux 内核来运行,可以说屏蔽了操作系统

在这里插入图片描述


1.3 什么是 Docker

Docker 是一个开源的应用容器引擎,诞生于 2013 年初,基于 Go 语言实现,dotCloud 公司出品

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上。而容器是完全使用沙箱机制,相互隔离,容器性能开销极低。

Docker 从 17.03 版本之后分为 CE(Community Edition:社区版)免费,支持周期 7 个月和 EE(Enterprise Edition:企业版)强调安全,付费使用,支持周期 24 个月。

官网地址:https://www.docker.com/

​	[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nEZYOpkH-1640568727789)(image/1-3.png)]

Docker 通俗的讲,是服务器中高性能的虚拟机,可以将一台物理机虚拟 N 多台虚拟机的机器,互相之间隔离,互不影响。

特点:

  • 容器将应用打包成标准化单元,用于交付、部署;
  • 容器及包含了软件运行所需的所有环境,而且非常轻量级
  • 容器化的应用程序,可以在任何 Linux 环境中始终如一的运行
  • 容器化的应用程序,具备隔离性,这样多团队可以共享同一 Linux 系统资源


1.4 虚拟化技术

​ 虚拟化(Virtualization)是一种资源管理技术,是将计算机的各种实体资源,如服务器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍,使用户可以比原本的组态更好的方式来应用这些资源。

​ 这些资源的核心虚拟部分是不受现有资源的架设方式,低于或者物理组态所限制,一般所指的虚拟化资源包括计算能力和资料存储。

虚拟化技术主要作用:

  • 高性能的物理硬件产能过剩和老的硬件产能过低问题
  • 软件跨环境迁移问题(代码的水土不服)

1.5 容器与虚拟机比较

Docker 可以让一个应用在任何操作系统中非常方便的运行。而以前我们接触的虚拟机,也能在一个操作系统中,运行另外一个操作系统,保护系统中的任何应用。两者有什么差异呢?

虚拟机(virtual machine):是在操作系统中模拟硬件设备,然后运行另一个操作系统,比如在 Windows 系统里面运行 Ubuntu 系统,这样就可以运行任意的 Ubuntu 应用了。

Docker:仅仅是封装函数库,并没有模拟完整的操作系统

下面的图片比较了 Docker 和传统虚拟化方式的不同之处,总的来说:Docker 是操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而虚拟机则是在硬件层面实现虚拟化。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h7s2xnMm-1640568727792)(image/image-20210731145914960.png)]

特性Docker虚拟机
隔离级别进程级操作系统级
隔离策略直接运行在宿主机内核中运行于 Hypervisor 上
启动速度秒级分钟级
占用磁盘空间一般为MB一般为GB
性能接近原生硬件弱鸡
系统支持量单机可跑几十个容器单机几个虚拟OS
运行环境主要在 Linux主要在 Windows

相同:Docker 和虚拟机都是虚拟化技术,具备资源隔离和分配优势

不同:

  • Docker 虚拟化的是操作系统,而虚拟机虚拟化的是硬件
  • Docker 它是操作系统上的一个系统进程,而虚拟机它是在操作系统中的操作系统

1.6 Docker 概念与架构

1.6.1 Docker 基本概念

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BFenPAG2-1640568727795)(image/image-20211110103911330.png)]

宿主机:安装 Docker 守护进程的 Linux 服务器,称之为宿主机;

镜像(Image):Docker 将应用程序及其所需的依赖、函数库、环境、配置等文件打包在一起,称为镜像。

容器(Container):镜像运行之后的实体,镜像和容器的关系,就像是面向对象程序设计中的类和对象一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等,也可以有多个。

例如:你下载了一个 QQ,如果我们将 QQ 在磁盘上的运行文件及其运行的操作系统依赖打包,形成 QQ 镜像。然后你可以启动多次,双开、甚至三开 QQ,跟多个妹子聊天。

仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。类似 Maven 的中央仓库

Docker 官方镜像的托管平台叫 Docker Hub,我们可以将自己的镜像共享到 Docker Hub,也可以从 Docker Hub 上拉取镜像。同时国内也有类似于 Docker Hub 的公开服务,比如网易云镜像服务阿里云镜像库等。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zKfazCyK-1640568727796)(image/image-20210731153743354.png)]


1.6.2 Docker 基本架构

Docker是一个 C/S 结构的程序,由两部分组成:

  • 服务端(Server):Docker 的守护进程,负责处理 Docker 指令,管理镜像和容器等等

  • 客户端(Client):通过命令或 RestAPI 向 Docker 服务端发送指令。可以在本地或远程向服务端发送指令。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5XKFeZUa-1640568727797)(image/image-20210731154257653.png)]


二、Docker 安装与启动

安装之前进行虚拟机网卡配置:IP 地址 192.168.88.101、网关为 192.168.88.2

2.1 安装

Docker 官方建议在 Ubuntu 中安装,因为 Docker 是基于 Ubuntu 发布的,而且一般 Docker 出现的问题 Ubuntu 是最先更新或者打补丁的。在很多版本的 CentOS 中是不支持更新最新的一些补丁包的。

由于我们学习的环境都使用的是 CentOS,因此这里我们将 Docker 安装到 CentOS 上。

注意:这里建议安装在 CentOS 7.x 以上的版本!其他更多安装参考官网:https://docs.docker.com/get-docker/

0)如果之前安装过旧版本的Docker,可以使用下面命令卸载

sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-selinux \
                  docker-engine-selinux \
                  docker-engine \
                  docker-ce

1)yum 包更新到最新

sudo yum -y update

2)安装需要的软件包, yum-util 提供 yum-config-manager 功能,另外两个是 devicemapper 驱动依赖的

sudo yum install -y yum-utils

3)设置 yum 源为阿里云

sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo yum makecache fast

4)安装 docker

sudo yum -y install docker-ce

5)安装后查看 docker 版本

docker -v

6)通过运行 hello-world 来验证是否正确安装了 Docker

docker run hello-world

2.2 Docker 守护进程相关命令

Docker应用需要用到各种端口,逐一去修改防火墙设置。非常麻烦,因此建议大家直接关闭防火墙!

# 关闭
systemctl stop firewalld
# 禁止开机启动防火墙
systemctl disable firewalld
操作指令
启动 Dockersystemctl start docker
停止 Dockersystemctl stop docker
重启 Dockersystemctl restart docker
查看 Docker 状态systemctl status docker
设置开机启动systemctl enable docker
查看 Docker 概要信息docker info
查看 Docker 帮助文档docker --help

如下图 docker info 展示信息
在这里插入图片描述


2.3 镜像加速

默认情况,将从Docker Hub(https://hub.docker.com)下载镜像,因为太慢,一般都会配置镜像加速器;

建议配置阿里云镜像加速,可以自己从阿里云上申请!必须要注册,每个人分配一个免费的 Docker 镜像加速地址,速度杠杠的~,配置完成记得刷新配置

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

三、Docker 中常用命令

3.1 镜像相关命令

首先来看下镜像的名称组成:

  • 镜名称一般分两部分组成:[repository]:[tag]
  • 在没有指定tag时,默认是latest,代表最新版本的镜像

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-quSalpXS-1640568727801)(image/image-20211110165435829.png)]

这里的 MySQL 就是 repository,5.7就是tag,合一起就是镜像名称,代表5.7版本的MySQL镜像。

而常见的镜像操作命令如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4dGTexrc-1640568727802)(image/image-20210731155649535.png)]


3.1.1 搜索镜像

如果你需要从网络中查找需要的镜像,可以通过以下命令搜索,注意:必须确保当前系统能联网,当然最好的方式还是在 Docker Hub 上进行搜索查找

docker search 镜像名称

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aERGzTw3-1640568727803)(image/image-20191206102720912.png)]


3.1.2 拉取镜像

拉取镜像:从Docker仓库下载镜像到本地,镜像名称格式为名称:版本号,如果版本号不指定则是最新的版本。如果不知道镜像版本,可以去 Docker Hub 搜索对应镜像查看。

docker pull 镜像名称

例如,我要下载 nginx 最新的镜像:docker pull nginx


3.1.3 查看镜像

查看本地所有镜像

docker images

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C6v6dluC-1640568727804)(image/image-20191206102003178.png)]
这些镜像都是存储在 Docker 宿主机的 /var/lib/docker 目录下


3.1.4 删除镜像

如果该镜像正在使用(创建了容器),则先删除容器再删除镜像

docker rmi 镜像ID # 按镜像ID删除镜像
docker rmi `docker images -qa` # 删除所有镜像

3.2 容器相关命令

有镜像才能创建容器,这是根本前提
在这里插入图片描述
容器的三个状态:

  • 运行:进程正常运行
  • 暂停:进程暂停,CPU不再运行,并不释放内存
  • 停止:进程终止,回收进程占用的内存、CPU等资源

其中:

  • docker run:创建并运行一个容器,处于运行状态
  • docker pause:让一个运行的容器暂停
  • docker unpause:让一个容器从暂停状态恢复运行
  • docker stop:停止一个运行的容器
  • docker start:让一个停止的容器再次运行
  • docker rm:删除一个容器

3.2.1 查看容器

查看正在运行的容器:docker ps

查看所有容器:docker ps –a

查看最后一次运行的容器:docker ps –l

查看停止的容器:docker ps -f status=exited

查看容器日志:docker logs 容器ID


3.2.2 创建与启动容器

在这里插入图片描述
创建容器命令:

docker run

创建容器常用的参数说明:

# OPTIONS说明(常用):有些是一个减号,有些是两个减号

--name:为创建的容器命名。

-d:在run后面加上-d参数,会创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器)。

-i:以交互模式运行容器,通常与 -t 同时使用

-t:表示容器启动后会进入其命令行。为容器重新分配一个伪输入终端,通常与 -i 同时使用

-p: 表示端口映射,前者表示宿主机端口,后者是容器内的映射端口,可以使用多个-p做多个端口映射

--restart=always:可以让容器开机自启

1)交互式容器
docker run -it --name=容器名称 镜像名称:标签 /bin/bash
# 举例:/bin/bash的作用是因为docker后台必须运行一个进程,否则容器就会退出,在这里表示启动容器后启动bash。
docker run -it --name=mycentos centos:7 /bin/bash

这时我们通过ps命令查看,发现可以看到启动的容器,状态为启动状态
在这里插入图片描述
退出当前容器

exit

2)守护式容器

什么是守护式容器:能够长期运行、 没有交互式会话、 适合运行应用程序和服务

docker run -d --name=容器名称 镜像名称:标签
# 举例:
docker run -d --name=nginx1 nginx:latest

3)进入容器
docker exec -it 容器名称 (或者容器ID) /bin/bash
# 举例:
docker run -it nginx1 /bin/bash

注意:这里的登陆容器之后执行的脚本 /bin/bash 必须写


4)端口的注意点

默认情况下,容器是隔离环境,我们直接访问宿主机的 80 端口,肯定访问不到容器中的 nginx。

所以我们需要将容器的 80 端口与宿主机的 80 端口关联起来,当我们访问宿主机的 80 端口时,就会被映射到容器的 80,这样就能访问到 nginx 了:
在这里插入图片描述

3.2.3 停止与启动容器

操作指令
启动容器docker start 容器名称(或者容器ID)
停止容器docker stop 容器名称(或者容器ID)
重启容器docker restart 容器名称(或者容器id)
强制停止容器docker kill 容器名称(或者容器id)

3.2.4 文件拷贝

如果我们需要将文件拷贝到容器内可以使用cp命令

docker cp 宿主机需要拷贝的文件或目录 容器名称:容器目录
# 举例:
docker cp /etc/hosts nginx1:/tmp

也可以将文件从容器内拷贝出来

docker cp 容器名称:容器目录 宿主机存放的文件或目录
# 举例:
docker cp nginx1:/usr/share/nginx/html/index.html /tmp

3.2.5 查看容器 IP 地址

我们可以通过以下命令查看容器运行的各种数据

docker inspect 容器名称(容器ID) 
# 举例:
docker inspect nginx1

在这里插入图片描述
也可以直接执行下面的命令直接输出IP地址

docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器名称(容器ID)
# 举例:
docker inspect --format='{{.NetworkSettings.IPAddress}}' nginx1

3.2.6 删除容器

删除指定的容器

docker rm 容器名称(容器ID) # 无法删除运行的容器
docker rm `docker ps -qa` # 删除所有容器
docker rm -f 容器名称(容器ID) # 慎用:可以删除正在运行的容器

3.3 迁移与备份

1)镜像备份

我们可以通过以下命令将镜像保存为 tar 文件

docker save -o {镜像的备份文件} {镜像名称}
# 举例:-o表示输出到的文件
docker save -o nginx.tar nginx:latest

在这里插入图片描述

2)镜像恢复与迁移

我们先删除掉 nginx:latest 镜像:docker rmi nginx:latest,然后再进行恢复

docker load -i {备份的镜像文件}
# 举例:-i表示指定导入的文件
docker load -i nginx.tar

3)容器保存为镜像

我们可以通过以下命令将容器保存为镜像

docker commit [OPTIONS] 容器名称 [镜像名称[:TAG]]
# 举例,不指定为latest
docker commit nginx1 test_nginx
docker images # 查看

四、Docker 数据卷

4.1 什么是数据卷

由于每个容器是互相隔离的,那么就会产生以下的问题:

Docker 容器删除之后,在容器中产生的数据还在吗?

Docker 容器和外部机器可以直接交换文件吗?

容器之间怎么进行数据交互?

要解决以上问题,就需要将数据与容器解耦,这就要用到数据卷了。

数据卷(volume):是一个虚拟目录,指向宿主机文件系统中的某个目录。当容器目录和数据卷目录绑定后,对方的修改自然会立即同步;一个数据卷可以被多个容器同时挂载,一个容器也可以挂载多个数据卷
在这里插入图片描述


4.2 数据卷基本命令

数据卷操作的基本语法如下:

docker volume [COMMAND]

其中 docker volume 命令是数据卷操作,根据命令后跟随的 command 来确定下一步的操作:

create # 创建一个volume
ls # 列出所有的volume
inspect # 显示一个或多个volume的信息
prune # 删除未使用的volume
rm # 删除一个或多个指定的volume

使用上面命令演示:创建一个数据卷,并查看数据卷在宿主机的目录位置,然后删除它

# 1、创建数据卷
docker volume create html
# 2、查看所有数据卷
docker volume ls
# 3、查看数据卷的详细信息
docker volume inspect html
# 可以看到,我们创建的html这个数据卷关联的宿主机目录为/var/lib/docker/volumes/html/_data目录。
[
    {
        "CreatedAt": "2021-11-11T16:52:34+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/html/_data",
        "Name": "html",
        "Options": {},
        "Scope": "local"
    }
]
# 4、删除html的数据卷
docker volume rm html
# 5、删除所有未使用的数据卷
docker volume prune

4.3 挂载数据卷

我们在创建容器时,可以通过 -v 参数来挂载一个数据卷到某个容器内目录

1)1个容器挂载1个数据卷

创建启动容器时,使用 –v 参数设置数据卷,冒号前面是宿主机目录,冒号后是容器目录

注意事项:如果宿主机目录不存在,会自动创建,可以挂载多个数据卷

docker run ... –v 宿主机目录(文件):容器内目录(文件) ... 

案例:创建一个 nginx 容器,挂载容器内的 html 目录到默认目录

# 1、创建容器并挂载数据卷到容器内的HTML目录
docker run -d --name=nginx2 -v html:/usr/share/nginx/html -p 80:80 nginx
# 2、查看html数据卷的位置
docker volume inspect html
# 3、进入html数据卷所在位置,并修改HTML内容
cd /var/lib/docker/volumes/html/_data
# 修改文件,保存,然后刷新网页就可以看到效果了
vi index.html

2)1个容器挂载多个数据卷

我们可以通过以下命令,挂载多个数据卷,其实就是多个 -v 参数

docker run -d --name=nginx3 -v /tmp/data1:/data1 -v /tmp/data2:/data2 nginx

3)多个容器挂载1个数据卷

方式一:多个容器挂载1个数据卷,实现数据共享,2个容器都挂载到/tmp/data_common

docker run -d --name=nginx4 -v /tmp/data_common:/data4 nginx
docker run -d --name=nginx5 -v /tmp/data_common:/data5 nginx

方式二:多个容器挂载1个容器(这个容器挂载1个数据卷)

# 创建启动 c3 数据卷容器,使用 –v 参数设置数据卷,激素创建一个容器,挂载一个目录,让其他容器继承自该容器
docker run -d --name=c3 -v /tmp/data_container:/c3 nginx
# 创建启动 c1 c2 容器,使用 –-volumes-from 参数设置数据卷
docker run -d --name=c1 --volumes-from c3 nginx
docker run -d --name=c2 --volumes-from c3 nginx

在这里插入图片描述


五、在 Docker 中部署应用

熟悉基本应用部署的使用

5.1 端口映射

在这里插入图片描述
开启 IP 转发,参考:https://www.cnblogs.com/sfnz/p/6555723.html

echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
# 重启network和docker服务
systemctl restart network && systemctl restart docker

# 查看是否修改成功 (备注:返回1,就是成功)
sysctl net.ipv4.ip_forward

5.2 MySQL 部署

  • 拉取MySQL镜像
docker pull mysql:8.0.27
  • 创建容器、设置端口映射、设置数据卷
docker run -d --name=mysql1 -p 3307:3306 \
-v /opt/mysql/logs:/logs \
-v /opt/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0.27
# 参数说明:
-p 3307:3306:将容器的 3306 端口映射到宿主机的 3307 端口。
-v /opt/mysql/logs:/logs:将主机目录(/opt/mysql/logs)挂载到容器中的 /logs 日志目录
-v /opt/mysql/data:/var/lib/mysql:将主机目录(/opt/mysql/data)挂载到容器的 /var/lib/mysql 数据目录
-e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码。
  • 进入容器,操作mysql
docker exec -it mysql1 mysql -uroot -p123456

# 修改远程访问
GRANT ALL ON *.* TO 'root'@'%';
  • 使用 Navicat、DataGrip 等工具连接容器中的 MySQL

5.3 Tomcat 部署

  • 拉取 Tomcat 镜像
docker pull tomcat
  • 创建容器,设置端口映射、目录映射
docker run -d --name=tomcat1 -p 8080:8080 -v /opt/tomcat/webapps:/usr/local/tomcat/webapps tomcat
# 参数说明:
-p 8080:8080:将容器的8080端口映射到主机的8080端口
-v /opt/tomcat/webapps:/usr/local/tomcat/webapps:将主机目录(/opt/tomcat/webapps)挂载到容器webapps
  • 向 Tomcat 中部署服务

  • 使用外部机器访问 Tomcat,测试部署服务


5.4 Redis 部署

  • 拉取 Redis 镜像
docker pull redis:latest
  • 创建容器,设置端口映射
docker run -d --name=redis1 -p 6379:6379 redis:latest
  • 进入容器,使用 redis-cli
docker exec -it redis1 redis-cli
  • 使用外部机器连接 Redis,测试

六、制作 Docker 镜像

常见的镜像在 Docker Hub 就能找到,但是我们自己写的项目就必须自己构建镜像了。而要自定义镜像,就必须先了解镜像的结构才行。

6.1 镜像结构

镜像就是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。以MySQL为例看看镜像的组成结构:
在这里插入图片描述

简单来说,镜像就是在系统函数库、运行环境基础上,添加应用程序文件、配置文件、依赖文件等组合,然后编写好启动脚本打包在一起形成的文件。我们要构建镜像,其实就是实现上述打包的过程。


6.2 镜像原理(重要)

Docker镜像都是只读的, 当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称作“容器层”, “容器层”之下的都叫“镜像层”。


6.2.1 UnionFS(联合文件系统)

UnionFS(联合文件系统): Union文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。

Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

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


6.2.2 镜像加载原理

Docker 镜像本质是什么?
Docker 中一个 CentOS 镜像为什么只有200MB,而一个 CentOS 操作系统的 ISO 文件要几个个G?
Docker 中一个 Tomcat 镜像为什么有500MB,而一个 Tomcat 安装包只有70多MB?
在下载镜像的过程中我可以看到 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等标准目录和文件。不同的 Linux 发行版,bootfs 基本一样,而 rootfs 不同,如 Ubuntu、CentOS 等。

在这里插入图片描述

1)Docker 镜像本质是什么?

  • 是一个分层文件系统,层层叠加

2)Docker 中一个 CentOS 镜像为什么只有 200MB,而一个 CentOS 操作系统的 ISO 文件要几个 G?

  • 因为 Docker 的 CentOS 镜像复用了操作系统的 bootfs,自己只需要提供 rootfs 就行了,而对于一个精简的OS,rootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了

3)Docker 中一个 Tomcat 镜像为什么有 500MB,而一个 Tomcat 安装包只有 10 多 MB?

  • 因为 Docker 中镜像是分层的,Tomcat 虽然只有 10 多 MB,但它也需要依赖于父镜像和基础镜像,所有整个对外暴露的 Tomcat 镜像大小是 500 多 MB

4、为什么 Docker 镜像采用分层结构?

  • 最大的一个好处就是共享资源,比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需保存一份 base 镜像,同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。可以说镜像中的每一层都可以被共享。

6.3 Dockerfile 简介

构建自定义的镜像时,并不需要一个个文件去拷贝,打包。

我们只需要告诉 Docker,我们的镜像的组成,需要哪些 BaseImage、需要拷贝什么文件、需要安装什么依赖、启动脚本是什么,将来 Docker 会帮助我们构建镜像。而描述上述信息的文件就是 Dockerfile 文件。

可以说 Dockerfile 就是一个文本文件,包含了构建镜像文件的指令,用指令来说明要执行什么操作来构建镜像。每一个指令都会形成一层 Layer,最终构建出一个新的镜像;

  • 对于开发人员:可以为开发团队提供一个完全一致的开发环境
  • 对于测试人员:可以直接拿开发时所构建的镜像或者通过 Dockerfile 文件构建一个新的镜像,直接开始工作
  • 对于运维人员:在部署时,可以实现应用的无缝移植

6.3.1 Dockerfile 构建过程解析

1)Dockerfile 内容基础知识

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

2)Docker 执行 Dockerfile 大致流程

  1. Docker 从基础镜像运行一个容器
  2. 从上到下执行指令,每执行一条指令就对容器作出修改
  3. 执行类似 Docker Commit 的操作提交一个新的镜像层
  4. Docker 再基于刚提交的镜像运行一个新容器
  5. 不断重复 2 ~ 4 的操作,直到所有指令都执行完成

3)从应用软件的角度来看,Dockerfile、Docker 镜像、Docker 容器分别代表软件的三个不同阶段

  • Dockerfile 是软件的原材料
    • Dockerfile 定义了进程需要的一切东西。包括执行文件、环境依赖、动态链接库、服务进程和内核进程等
  • Docker 镜像是软件的交付品
    • 在用 Dockerfile 定义一个文件后,docker build 时会产生一个 Docker 镜像
  • Docker 容器则可以认为是软件的运行状态
    • 当运行 Docker 镜像时,就会启动一个容器来提供服务

可以理解为 Dockerfile 面向开发,Docker 镜像成为交付标准,Docker 容器则涉及部署与运维,三者缺一不可,合力充当 Docker 体系的基石。


6.3.2 Dockerfile 语法

更多语法说明,参考官网文档:https://docs.docker.com/engine/reference/builder
在这里插入图片描述

指令示例作用
FROM image_name:tag定义了使用哪个基础镜像启动构建流程
LABEL key value声明我们需要各种元数据,比如版本、作者、描述等等(可以写多条)
ENV key value设置环境变量(可以写多条)
RUN command执行一段命令默认是/bin/sh,也是Dockerfile的核心部分(可以写多条)
COPY source_dir/file dest_dir/file将宿主机文件复制到容器内,如果有压缩文件并不能解压
ADD source_dir/file dest_dir/file与COPY类似,但如果是压缩文件会在复制后自动解压
WORKDIR path_dir设置工作目录,如果没有会自动创建
EXPOSE 8080/udp运行时监听的端口, 启动容器的时候使用 -p 绑定
ENTRYPOINT command镜像中应用的启动命令,在容器运行时调用,只有最后一个会生效

6.4 制作 Docker 镜像

发布 SpringBoot 项目到 Docker 容器中

实现过程:

1)编辑 Dockerfile 文件

# 定义基础镜像
FROM java:8-alpine
# 添加jar包文件到镜像中
COPY ./springboot.jar /opt/app.jar
# 暴露端口
EXPOSE 8080
# 定义当前镜像启动容器时,执行命令
ENTRYPOINT java -jar /opt/app.jar

2)在宿主机中,构建镜像

docker bulid –t {镜像名称:版本} {构建文件所在路径}
# 举例:注意后面的空格和点,不要省略,点表示当前目录
docker build -t boot:1.0 ./
# -t:镜像的名字及标签,通常 name:tag 或者 name 格式,不设置为latest

3)基于镜像,启动容器

docker run -d --name=boot1 -p 9001:8080 boot:1.0

4)测试:http://192.168.88.101:9001/sayHello

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值