【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建

文章目录

  • 前言:项目部署的挑战
  • 一、初识 Docker
    • 1.1 什么是 Docker
    • 1.2 Docker 与 虚拟机的区别
    • 1.3 镜像和容器以及镜像托管平台
    • 1.4 Docker的架构解析
    • 1.5 Docker 在 CentOS 中的安装
  • 二、Docker 的基本操作
    • 2.1 操作 Docker 镜像命令
      • 2.1.1 镜像操作相关命令
      • 2.1.2 示例一:从 DockerHub 拉取一个 nginx 镜像
      • 2.1.3 示例二:使用 save 将 nginx 镜像导出磁盘,然后再通过 load 加载回来
    • 2.2 Docker 容器命令详解
      • 2.2.1 操作容器相关命令
      • 2.2.2 示例一:运行 nginx 镜像
      • 2.2.3 示例二:进行 Nginx 容器内部,修改HTML文件内容
    • 2.3 操作 Docker 数据卷命令详解
      • 2.3.1 容器与数据耦合的问题
      • 2.3.2 什么是数据卷
      • 2.3.3 数据卷相关操作命令
      • 2.3.4 示例一:创建一个数据卷,并查看数据卷在宿主机的目录位置
      • 2.3.5 示例二:创建nginx容器的同时创建数据卷,通过数据卷修改 HTML 内容
  • 三、Dockerfile 自定义镜像的创建
    • 3.1 镜像文件的结构详解
    • 3.2 Dockerfile 文件详解
    • 3.3 示例一:基于 Ubuntu 镜像构建一个新镜像,运行一个 Java 项目
    • 3.4 示例二:基于 java:8-alpine 镜像,修改示例一的 Dockerfile 文件


前言:项目部署的挑战

在部署大型项目时,常常面临多组件、复杂的依赖关系和不同环境之间的差异,这些因素可能导致以下问题:

  1. 复杂的依赖关系: 由于项目组件众多,各个组件之间的依赖关系变得复杂,容易出现版本不匹配或兼容性问题。

  2. 兼容性问题: 项目在不同的环境中可能会遇到兼容性挑战,导致在一个环境中正常运行的组件在另一个环境中出现问题。

  3. 环境差异: 开发、测试和生产环境之间存在差异,可能涉及操作系统、库版本、配置等方面的不一致性,增加了部署的复杂性。

这些挑战使得项目部署变得复杂且容易出错。为了解决这些问题,引入Docker技术是一个有效的方案。Docker的容器化特性能够提供一致的运行环境,简化依赖管理,并减轻不同环境之间的差异性,从而提高部署的可靠性和效率。在接下来的内容中,我们将深入了解Docker的基本概念以及如何利用Docker解决这些项目部署的挑战。

一、初识 Docker

1.1 什么是 Docker

Docker 是一种开源的容器化平台,旨在简化应用程序的开发、交付和部署过程。通过使用容器技术,Docker 能够将应用程序、所有依赖项以及程序运行所需要的环境打包成一个独立的容器。这个容器包含了运行应用所需的一切,包括操作系统、库和代码等等。这种打包的方式使得应用程序在任何环境中都能够以一致的方式运行,从而实现了跨平台、可移植和快速部署的优势。

Docker 是一项旨在实现快速交付应用和高效运行应用的技术。它提供了以下主要特性:

  1. 容器化打包: Docker允许将程序、其依赖以及运行环境一同打包成一个独立的镜像。这个镜像包含了应用程序所需的一切,从操作系统到所有依赖库,形成了一个可移植的、一致的运行环境。

  2. 跨平台移植性: 由于 Docker 镜像是独立的、轻量级的打包,因此可以轻松迁移到任意支持 Docker 的 Linux 操作系统,无需担心环境差异性问题。

  3. 沙箱隔离: 运行时,Docker 利用沙箱机制为每个容器创建独立的运行环境,使得各个应用程序在容器内互不干扰。这种隔离性确保了安全性和可靠性。

  4. 便捷的管理命令: Docker 提供了简单而强大的命令行工具,用户可以使用一行命令完成启动、停止、移除容器等操作。这种便捷性提高了应用程序的开发、测试和部署效率。

总体而言,Docker 为开发人员提供了一种先进的、可移植的容器化解决方案,通过将应用程序及其运行时环境打包成镜像,实现了快速部署和跨平台运行的便利性。同时,沙箱隔离机制确保了多个应用程序之间的独立性,使得Docker成为现代应用开发和部署的理想选择。

1.2 Docker 与 虚拟机的区别

Docker和虚拟机是两种常见的容器化技术,它们在实现虚拟化和隔离的方式以及性能表现上存在一些区别。在理解Docker和虚拟机之前,首先我们可以简单了解它们的层次结构:

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第1张图片

通过上图可以发现虚拟机是使用 Hypervisor 在操作系统上模拟出计算机硬件,然后再在这个虚拟硬件上安装的操作系统;而 Docker 容器则是直接运行在操作系统上的。因此 Docker 的性能会远远优于虚拟机。

下面我们来比较一下 Docker 和虚拟机的特性:

特性 Docker 虚拟机
性能 接近原生 性能较差
硬盘占用 一般为MB 一般为GB
启动 秒级 分钟级

Docker的优势:

  1. 性能: Docker容器直接运行在宿主操作系统的内核上,因此性能接近原生,而虚拟机需要在Hypervisor的管理下运行,性能相对较差。

  2. 硬盘占用: Docker镜像是轻量级的,通常只有MB级别,而虚拟机的镜像则往往是GB级别,因此Docker在硬盘占用上更为高效。

  3. 启动速度: Docker容器启动非常迅速,可以达到秒级的启动时间,而虚拟机的启动则需要较长的时间,通常是分钟级。

总体而言,Docker适用于快速部署、轻量级应用,而虚拟机则更适合需要完全隔离的复杂应用。选择使用哪种技术取决于具体的应用场景和需求。

1.3 镜像和容器以及镜像托管平台

在Docker的世界里,镜像和容器是两个核心概念,理解它们是使用 Docker 的关键。

镜像是什么?

镜像是一个轻量级、独立的可执行软件包,包含运行应用程序所需的一切:代码、运行时、系统工具、系统库,以及设置。简单来说,镜像就是一个应用程序的打包。

构成要素:

  1. 应用程序代码: 你的应用程序的所有文件和代码。
  2. 运行时: 定义应用程序如何运行的配置文件。
  3. 系统工具: 用于操作系统和应用程序的工具。
  4. 系统库: 应用程序所需的任何库文件。

特点:

  • 不可修改性:一旦构建,镜像的内容不可更改。
  • 轻量性:镜像通常很小,因为它只包含运行应用程序所需的最小内容。

例子:

  • 一个运行Node.js应用的镜像可能包含Node.js运行时、应用代码、以及一些操作系统工具。

容器是什么?

容器是镜像的运行实例。可以将容器视为一个轻量级、独立的可执行包,包含应用程序、运行时和系统工具,并根据镜像的定义执行。

特点:

  • 隔离性:容器之间相互隔离,一个容器的变化不会影响其他容器。
  • 可移植性:容器可以在任何支持Docker的环境中运行。

例子:

  • 使用一个Node.js镜像运行两个相同的应用程序,每个应用程序在一个独立的容器中运行,相互隔离。

镜像托管平台:

DockerHub:

  • DockerHub 是一个 Docker 镜像的托管平台,类似于云存储,同时我们也可以在上面存储和分享自己的镜像。

其他镜像托管平台:

  • 除了DockerHub,国内也有一些类似的服务,如网易云镜像服务、阿里云镜像库等,它们提供了更快速、稳定的镜像下载服务,同时支持用户私有镜像的存储。另外我们也可以创建自己私有的镜像托管平台。

示意图:
【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第2张图片

总之,理解镜像和容器的关系,以及它们在 Docker 中的作用,是使用 Docker 进行应用开发和部署的基础。 Docker 的成功部分归功于这种轻量级、可移植的容器化技术,使得应用程序的构建、分发和运行变得更加简单和高效。

1.4 Docker的架构解析

Docker的架构设计简单而灵活,分为客户端和服务端两部分,它们协同工作以实现容器的创建、运行和管理。

客户端(Client)

客户端是用户与Docker交互的界面。用户可以通过命令行、图形界面或者使用 Docker 提供的API与服务端通信,发送指令来管理 Docker。

服务端(Server)

服务端是 Docker 的守护进程,负责处理来自客户端的指令,管理 Docker 的各项工作。服务端的主要组件包括:

  1. Docker Daemon: 守护进程,运行在主机上,负责管理容器的创建、运行和停止等操作。它还负责与其他Docker守护进程通信,以及与客户端通信。

  2. Docker REST API: 客户端和守护进程之间的通信通过REST API进行。客户端可以通过REST API向守护进程发送命令,实现与Docker的交互。

  3. Docker Registry: 用于存储Docker镜像的服务。Docker官方提供了Docker Hub作为默认的公共Registry,用户也可以使用私有Registry或其他公共Registry存储和分享镜像。

架构图示

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第3张图片

在这个架构中,客户端和服务端可以运行在同一台主机上,也可以通过网络连接在不同的主机上。当客户端发送Docker命令时,它们通过REST API与服务端进行通信,服务端根据指令执行相应的操作。

交互流程

  1. 客户端发送命令: 用户通过命令行或其他工具发送Docker命令,如创建镜像、运行容器等。

  2. 命令发送至服务端: 客户端将命令发送至服务端,通过REST API进行通信。

  3. 服务端执行命令: Docker Daemon接收到命令后,执行相应的操作,如创建或管理容器、拉取或推送镜像等。

  4. 结果返回给客户端: 服务端执行完命令后,将结果返回给客户端,用户可以看到执行结果。

Docker的这种CS(Client-Server)架构使得用户可以通过简单的命令与Docker进行交互,同时服务端负责具体的管理和操作,使得整个系统更加模块化和易扩展。

1.5 Docker 在 CentOS 中的安装

Docker是一款强大的容器化平台,为了在CentOS上使用Docker,我们将按照以下步骤进行安装。

  1. 卸载旧版本(可选)

如果之前安装过 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. 安装依赖工具

安装必要的工具和依赖:

sudo yum install -y yum-utils device-mapper-persistent-data lvm2
  1. 添加 Docker 存储库

添加 Docker 的官方存储库。这里我们使用阿里云的镜像加速地址:

sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  1. 安装 Docker 引擎

安装最新版本的 Docker 引擎:

sudo yum install docker-ce docker-ce-cli containerd.io
  1. 启动 Docker 引擎

启动 Docker 引擎并设置开机启动:

sudo systemctl start docker
sudo systemctl enable docker
  1. 验证安装

运行以下命令验证 Docker 是否正确安装:

docker --version
docker info
  1. 配置镜像加速

为了提升 Docker 镜像的下载速度,配置镜像加速器。以阿里云为例,前往阿里云容器镜像服务注册账号并获取加速地址。然后在/etc/docker/daemon.json中添加以下内容:

{
  "registry-mirrors": ["https://your-registry-mirror"]
}

替换https://your-registry-mirror为你的加速地址。

完成上述步骤后,我们的 CentOS 系统就成功安装并配置好了 Docker。现在,就可以通过运行 docker run hello-world 测试Docker是否正常工作。

二、Docker 的基本操作

Docker 的操作主要分为三个方面:镜像操作、容器操作和数据卷管理。下面详细介绍这三方面的相关命令。

2.1 操作 Docker 镜像命令

在Docker的世界中,镜像是应用程序的打包和分发单位。理解并熟练使用与镜像相关的命令是使用Docker的关键。本文将详细介绍一些常见的镜像操作命令。

2.1.1 镜像操作相关命令

镜像名称解析

在Docker中,镜像名称通常由两部分组成:[repository]:[tag]。如果不指定tag,默认使用latest,表示最新版本的镜像。例如,mysql的镜像名称:
【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第4张图片

镜像操作命令概览

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第5张图片

从上图可以发现,镜像命令主要包括以下几种:

  1. docker pull 从远程仓库拉取镜像。

    docker pull image_name
    
  2. docker push 将本地镜像推送到远程仓库。

    docker push image_name
    
  3. docker build 根据Dockerfile构建镜像。

    docker build -t image_name .
    
  4. docker save 将镜像保存为一个tar压缩包。

    docker save -o image_name.tar image_name
    
  5. docker load 从一个tar压缩包中加载镜像。

    docker load -i image_name.tar
    

2.1.2 示例一:从 DockerHub 拉取一个 nginx 镜像

DockerHub是Docker官方的镜像仓库,提供了大量的官方和社区维护的镜像。以下是一个从 DockerHub 拉取nginx 镜像的示例:

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第6张图片

docker pull nginx

上述命令将从 DockerHub 下载最新版本的 nginx 镜像到本地。然后使用 docker images命令则可以查看当前已经存在的镜像:

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第7张图片

如果需要特定版本的镜像,可以使用:

docker pull nginx:version

version替换为需要的具体版本即可。

2.1.3 示例二:使用 save 将 nginx 镜像导出磁盘,然后再通过 load 加载回来

首先,关于 saveload 的语法,我们可以使用 --help 选项来进行查看:

save 命令:

docker save --help

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第8张图片

可以发现,save 命令的作用是将镜像保存为一个tar格式的压缩包,使用 -o 选项代表STDOUT 标准输出,将其写入到文件中。

例如,保存上面的nginx镜像到磁盘:

docker save -o nginx.tar nginx:latest

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第9张图片

load 命令:

docker load --help

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第10张图片
可以发现,load 命令的作用是将一个tar格式的压缩包加载为一个 Docker 镜像,使用 -i 选项代表STDIN 标准输入,将其写入到指定文件中,-q 选项则不会输出日志到终端。

例如,加载刚才的 nginx.tar 压缩包:

首先删除nginx:latest镜像:
【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第11张图片

然后加载nginx.tar 压缩包:
【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第12张图片

2.2 Docker 容器命令详解

容器是Docker的运行实例,是镜像的具体执行环境。了解并熟练使用容器相关的命令是使用Docker的核心部分。接下来,我们将详细介绍一些常见的容器操作命令。

2.2.1 操作容器相关命令

容器操作命令如下图所示:

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第13张图片

让我们逐一了解这些命令:

  1. docker run 运行容器。

    docker run options image_name
    
  2. docker pause 暂停容器。

    docker pause container_id
    

    此命令可以暂停运行中的容器,使其进程挂起。

  3. docker unpause 恢复容器。

    docker unpause container_id
    

    docker pause相对应,该命令用于恢复被暂停的容器。

  4. docker stop 停止容器。

    docker stop container_id
    

    通过此命令,你可以停止运行中的容器,但容器实例仍然存在。

  5. docker start 启动已停止的容器。

    docker start container_id
    

    使用该命令,你可以启动之前停止的容器。

  6. docker rm 移除容器。

    docker rm container_id
    

    通过此命令,你可以删除已经停止的容器实例。请注意,删除容器不会删除镜像。

  7. docker exec 在运行中的容器中执行命令。

    docker exec options container_id command
    

    该命令用于在正在运行的容器中执行特定命令,例如:

    docker exec -it container_id /bin/bash
    

    上述命令将在容器中打开一个交互式的bash shell。

  8. docker logs 查看容器日志。

    docker logs container_id
    

    此命令用于查看容器的输出日志。

  9. docker ps 列出运行中的容器。

    docker ps options
    

    通过此命令,可以列出正在运行的容器。使用-a选项可以列出所有容器,包括已停止的。

这些命令覆盖了 Docker 容器操作的核心方面,通过它们,可以方便地管理和使用 Docker 容器。在实践中,根据具体需求巧妙组合这些命令,可以更加高效地运行和管理容器。

补充:暂停pause和停止stop的区别说明:

docker pausedocker stop 是两个不同的命令,它们的作用分别是暂停容器和停止容器。下面分别说明它们之间的区别:

docker pause

  • 作用: 暂停容器的所有进程,冻结容器的状态。
  • 使用场景: 当希望保留容器的当前状态,但是暂时停止容器中的所有进程时,可以使用此命令。容器处于暂停状态时,其文件系统和内存中的数据仍然存在,但是容器内的所有进程都会被挂起,不再执行。
  • 例子:
    docker pause container_id
    

docker stop

  • 作用: 停止容器的运行,终止容器的所有进程。
  • 使用场景: 当希望完全终止容器的运行时,包括停止容器内的所有进程,释放占用的资源,可以使用此命令。容器处于停止状态时,可以选择删除容器或者重新启动。
  • 例子:
    docker stop container_id
    

区别总结:

  • docker pause 暂停容器,冻结容器状态,容器中的数据保留。
  • docker stop 停止容器,终止容器内的所有进程,容器中的数据保留。

在选择使用这两个命令时,需要根据具体的需求来决定。如果需要在保留容器状态的同时暂时停止容器中的所有进程,可以使用 docker pause;如果希望完全停止容器的运行,释放资源,可以使用 docker stop

2.2.2 示例一:运行 nginx 镜像

通过下面命令,可以在新的容器中运行一个 nginx镜像。例如:

docker run -d -p 8080:80 --name my-nginx nginx:latest

说明:

  • -d选项:让容器在后台运行;
  • -p选项:将宿主机的 8080 端口与容器的 80 端口进行映射,即访问宿主机的 8080 端口即可访问到容器的 80 端口;
  • --name选项:指定容器的名称,需要保证唯一;

    当运行成功之后,则会在终端中输出这个容器的唯一 ID。

可以使用 docker ps 命令查看当前运行中的容器:

另外,为了验证 nginx 容器成功启动并运行了,可以在浏览器中使用 宿主机IP:8080进行访问:

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第14张图片
此时出现了 nginx 的欢迎页面,则说明成功启动并运行容器了。

2.2.3 示例二:进行 Nginx 容器内部,修改HTML文件内容

  1. 首先,我们可以使用 docker exec 命令进入容器的内容:
docker exec -it my-nginx bash

说明:

  • -it 给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互;
  • my-nginx:要进入的容器的名称;
  • bash:开启 linux终端交互的命令。

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第15张图片
此时的主机名变成了容器的部分 ID。

  1. 然后进入nginxHTML文件所在目录 /usr/share/nginx/html
    【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第16张图片

  2. 修改index.html 文件的内容:

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第17张图片

如果我们想要使用 vim 进行修改的话,发现 Docker 容器并没有提供 vim 编辑器,另外我们也可以发现其实 Docker 容器也只提供了少量的命令,原因在于保持容器的轻量化。

此时,我们可以使用 sed 命令进行修改:

# sed
sed -i 's#Welcome to nginx#Docker 非常简单!#g' index.html
sed -i 's###g' index.html # 修改编码方式为 UTF-8

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第18张图片

  1. 再次在浏览器中进行访问:

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第19张图片

2.3 操作 Docker 数据卷命令详解

2.3.1 容器与数据耦合的问题

在容器化应用中,容器与其数据之间的耦合可能带来一些问题:

  1. 不便于修改: 当需要修改容器内部的数据时,必须进入容器内部进行修改,这样不够方便。
  2. 数据不可复用: 对容器内数据的修改对外部是不可见的,新创建的容器无法复用这些修改。
  3. 升级维护困难: 如果数据在容器内,升级容器就意味着删除旧容器,所有数据都会被删除。

为了解决这些问题,可以使用 Docker 的数据卷。

2.3.2 什么是数据卷

数据卷(Volume)是一个可以在容器之间共享和重用的目录,它存在于宿主机而不是容器内。通过数据卷,将宿主机文件系统中的某个目录与容器中的目录进行映射,实现数据的共享和持久化。

如下图所示:
【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第20张图片

可以发现,其实就是通过数据卷帮助宿主机文件系统中的文件与 Docker 容器中的文件建立了映射关系。

2.3.3 数据卷相关操作命令

Docker 提供了一系列的命令来管理数据卷,基本语法如下:

docker volume [COMMAND]

其中,COMMAND 可以是以下几个操作之一:

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第21张图片

  • create: 创建一个数据卷。
  • inspect: 显示一个或多个数据卷的信息。
  • ls: 列出所有的数据卷。
  • prune: 删除未使用的数据卷。
  • rm: 删除一个或多个指定的数据卷。

下面将详细介绍其中的一些常用命令。

  1. 创建数据卷

要创建一个数据卷,可以使用 docker volume create 命令:

docker volume create my_volume

上述命令将创建一个名为 my_volume 的数据卷。

  1. 查看数据卷信息

使用 docker volume inspect 命令可以查看一个或多个数据卷的详细信息:

docker volume inspect my_volume
  1. 列出所有数据卷

使用 docker volume ls 命令可以列出所有的数据卷:

docker volume ls
  1. 删除数据卷

要删除一个或多个指定的数据卷,可以使用 docker volume rm 命令:

docker volume rm my_volume
  1. 清理未使用的数据卷

使用 docker volume prune 命令可以删除未被使用的数据卷:

docker volume prune

上述命令将提示是否删除未使用的数据卷,确认后将执行删除操作。

通过这些数据卷的管理命令,可以更加灵活地处理容器中的数据,实现数据的持久化和共享。在实际应用中,数据卷是非常有用的特性,尤其是对于需要持久化存储的应用场景。

2.3.4 示例一:创建一个数据卷,并查看数据卷在宿主机的目录位置

  1. 创建数据卷
docker volume create html


2. 查看当前所有的数据卷

docker volume ls

  1. 查看数据卷 html 的详细信息
docker volume inspect html

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第22张图片

可以发现,html 的宿主机中的挂载点为:/var/lib/docker/volumes/html/_data

2.3.5 示例二:创建nginx容器的同时创建数据卷,通过数据卷修改 HTML 内容

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

docker run \
  --name my-nginx \
  -v html:/usr/share/nginx/html \
  -p 8080:80 \
  -d \
  nginx:latest

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第23张图片

  1. 进入html数据卷所在位置
    【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第24张图片

  2. 并修改 index.html 内容
    【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第25张图片

  3. 通过浏览器访问 nginx
    【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第26张图片
    此时便成功通过数据卷的方式对 Docker 容器内容的文件进行了修改了。

三、Dockerfile 自定义镜像的创建

3.1 镜像文件的结构详解

Docker 镜像是一个包含应用程序及其运行所需组件的轻量级、可执行的软件包。它的文件结构是分层的,每一层都包含了对文件系统的一些更改。让我们深入了解镜像文件的结构。

  1. 镜像的层次结构

镜像的层次结构由多个层组成,如下图所示:

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第27张图片

这些层次分为以下几类:

  1. Base Image 层: 包含基本的系统函数库、环境变量和文件系统。这一层构成了镜像的基础。

  2. Entrypoint 层: 包含应用程序的启动命令。它定义了镜像中应用程序的入口点。

  3. 其它层: 在 Base Image 的基础上添加应用程序的依赖、安装程序等,完成整个应用的安装和配置。每一层都是基于前一层的修改。

  1. 镜像的分层优势

Docker 镜像采用分层的设计有一些优势:

  • 高效的存储利用: 如果多个镜像共享相同的基础层,这一层只需要存储一次,减少了存储空间的占用。

  • 快速的分发: 镜像的分层结构也使得只需要传输发生更改的层,而不是整个镜像,因此可以更快速地分发和部署。

通过这样的分层结构,Docker 实现了镜像的高效管理、存储和传输,使得容器的构建和分发变得更加轻量和快速。

3.2 Dockerfile 文件详解

  1. 什么是 Dockerfile

Dockerfile 是 Docker 中用于构建镜像的脚本文件,它包含了一系列指令,每个指令都会在当前层次上进行修改,形成一个新的层次,最终组合成一个完整的容器镜像。

  1. Dockerfile 指令

以下是一些常用的 Dockerfile 指令及其说明:

指令 说明 示例
FROM 指定基础镜像,后续的指令将基于这个镜像构建。 FROM centos:7
ENV 设置环境变量,这些变量可在后续指令中使用。 ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk
COPY 将文件从构建上下文复制到镜像中的指定路径。 COPY ./app.jar /usr/app/
RUN 执行 Linux 的 shell 命令,一般用于安装软件包等操作。 RUN yum install -y gcc
EXPOSE 指定容器运行时监听的端口,是给镜像使用者看的。 EXPOSE 8080
ENTRYPOINT 指定容器中应用的启动命令,容器运行时会调用这个命令。 ENTRYPOINT ["java", "-jar", "app.jar"]

更多 Dockerfile 指令和语法细节可以参考官方文档:Dockerfile reference

  1. Dockerfile 文件

在构建 Docker 镜像时,Docker 会按照 Dockerfile 中的指令逐层构建镜像。每个指令都会在当前层次上进行修改,形成一个新的层次。

例如一个简单的 Dockerfile 如下:

# 使用基础镜像
FROM ubuntu:latest

# 执行一些命令
RUN apt-get update && apt-get install -y \
    nginx \
    && rm -rf /var/lib/apt/lists/*

# 设置工作目录
WORKDIR /app

# 复制文件
COPY . .

# 设置入口命令
CMD ["nginx", "-g", "daemon off;"]

在这个例子中,每一个指令都会在前一个指令的基础上进行修改,构建出一个包含了基础镜像、安装了 Nginx、设置了工作目录和入口命令的完整镜像。

  1. 使用 Dockerfile 构建镜像

在构建 Docker 镜像时,通过以下命令使用 Dockerfile:

docker build -t my-image:tag path/to/Dockerfile-context
  • -t:指定镜像的名称和标签。
  • path/to/Dockerfile-context:Dockerfile 所在的上下文路径。

例如,在一个包含 Dockerfile 的目录中运行以下命令:

docker build -t my-app:1.0 .

上述命令将在当前目录中查找 Dockerfile 文件并构建一个名为 my-app、标签为 1.0 的镜像。

3.3 示例一:基于 Ubuntu 镜像构建一个新镜像,运行一个 Java 项目

  1. 准备工作
  • 步骤1:新建一个空文件夹 docker-demo

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第28张图片

  • 步骤2:拷贝 Java 项目文件

拷贝提前准备好的 Java jar 包 docker-demo.jar 文件到 docker-demo 这个目录

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第29张图片

  • 步骤3:拷贝 JDK 文件

拷贝提前准备的 jdk8.tar.gz 文件到 docker-demo 这个目录

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第30张图片

  1. 编写 Dockerfile

docker-demo 这个目录下,编写一个 Dockerfile 文件,其内容如下:

# 指定基础镜像
FROM ubuntu:16.04

# 配置环境变量,JDK的安装目录
ENV JAVA_DIR=/usr/local

# 拷贝 JDK 和 Java 项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar

# 安装 JDK
RUN cd $JAVA_DIR \
 && tar -xf ./jdk8.tar.gz \
 && mv ./jdk1.8.0_144 ./java8

# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin

# 暴露端口
EXPOSE 8090

# 入口,Java 项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar
  1. 构建和运行 Docker 镜像

docker-demo 目录下,执行以下命令构建 Docker 镜像:

docker build -t java-app:1.0 .

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第31张图片

运行这个镜像:

docker run -d -p 8090:8090 --name java-app java-app:1.0

Run Container

最后在浏览器中访问: http://宿主机IP:8090/hello/count

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第32张图片

通过这个示例,我们成功地基于 Ubuntu 镜像构建了一个包含 Java 项目的镜像,并运行了一个容器。这展示了 Dockerfile 的使用以及如何在容器中运行 Java 应用程序。

3.4 示例二:基于 java:8-alpine 镜像,修改示例一的 Dockerfile 文件

在示例一中,我们使用了 Ubuntu 作为基础镜像。这一示例中,我们将使用 java:8-alpine 作为基础镜像,这是一个更轻量级的镜像,适用于精简容器体积的场景。

什么是 java:8-alpine

java:8-alpine 是一个基于 Alpine Linux 发行版的 Docker 镜像,专门用于运行 Java 应用程序。让我们拆解这个标签的含义:

  • java:这表示这个镜像是为 Java 应用程序准备的。
  • 8:这表示 Java 版本,具体是 Java 8。
  • alpine:这表示基础操作系统是 Alpine Linux。Alpine Linux 是一个轻量级的 Linux 发行版,以小巧、简单而闻名。

Alpine Linux 与传统的 Linux 发行版相比,更注重精简和安全。它的包管理系统采用 apk,而不是像 Ubuntu 和 CentOS 那样使用 aptyum。由于精简的设计,Alpine Linux 提供了更小的镜像体积,这对于容器化应用来说非常重要。

因此,java:8-alpine 镜像是一个非常适合运行 Java 应用程序的轻量级选择。

  1. 修改 Dockerfile

docker-demo 目录下,修改 Dockerfile 文件如下:

# 指定基础镜像
FROM java:8-alpine

# 拷贝 Java 项目的包
COPY ./docker-demo.jar /tmp/app.jar

# 暴露端口
EXPOSE 8090

# 入口,Java 项目的启动命令
CMD ["java", "-jar", "/tmp/app.jar"]
  1. 重新构建和运行 Docker 镜像

docker-demo 目录下,执行以下命令重新构建 Docker 镜像:

docker build -t java-app:2.0 .

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第33张图片

运行这个镜像:

docker run -d -p 8090:8090 --name java-app-alpine java-app:2.0

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第34张图片

最后在浏览器中访问: http://宿主机IP:8090/hello/count

【Docker】初识 Docker,Docker 基本命令的使用,Dockerfile 自定义镜像的创建_第35张图片

通过这个示例,我们成功地使用了 java:8-alpine 作为基础镜像,实现了相同的 Java 项目运行。这样的修改不仅提高了容器的轻量级,同时也减小了镜像体积。

你可能感兴趣的:(微服务,docker,容器,微服务)