当前位置: 首页 > news >正文

玩转Docker(一):基本概念

容器技术是继大数据和云计算之后又一炙手可热的技术,而且未来相当一段时间内都会非常流行。

本文将对其基本概念和基本使用做出介绍。包括容器生态系统、容器的原理、怎样运行第一个容器、容器技术的概念与实践、Docker镜像等等

目录

一. 鸟瞰容器生态系统

1. 容器生态系统包含哪些不同层次的技术?

2. 先了解下Docker

3. 容器、镜像、镜像仓库

4. Docker容器与虚拟机技术的区别和联系

二. 运行第一个容器

三. 容器技术

1. What - 什么是容器?

2. Why - 为什么需要容器?

3. How - 容器是如何工作的

Docker架构

Docker服务器:Docker Daemon

Docker客户端:Docker CLI

Docker镜像:Image

Docker容器:Container

Registry:存放Docker镜像的仓库

4. 小结

四. Docker镜像

1. 镜像的内部结构

hello-world -- 最小的镜像

base镜像

支持运行多种LinuxOS

2. 镜像的分层结构

3. 构建镜像

docker commit

Dockerfile

RUN vs CMD vs ENTRYPOINT


一. 鸟瞰容器生态系统

1. 容器生态系统包含哪些不同层次的技术?

容器生态系统是基于Docker等各种容器的生态系统,包含的技术层次

容器生态系统包含核心技术、平台技术和支持技术。

简而言之:

  • 核心技术:能够让 Container 在 host 上运行的那些技术。解决的是容器自身怎样运行。
  • 平台技术:关注一组容器如何组织运行,管理这组容器的生命周期。
  • 容器支持技术:支持基于容器的基础设施。例如,容器网络、服务发现、监控、数据管理、日志管理、安全性等等

2. 先了解下Docker

Docker是一种开源的容器化平台,旨在简化应用程序的开发、部署和运行过程。提供了一种轻量级、可移植和自包含的容器化环境,使开发人员能够在不同计算机上以一致的方式构建、打包和分发应用程序

3. 容器、镜像、镜像仓库

  • 容器(Container):容器是Docker中运行应用程序的运行时实例。它是一个轻量级、可执行的软件包,包含了运行某个应用程序所需的所有内容,包括代码、运行时、系统工具、系统库和设置等。容器基于镜像创建,是镜像的运行实例。容器可以处于以下几种状态:

    • 运行中:容器正在运行应用程序
    • 已停止:容器已经停止运行,但仍然存在于系统中,可以随时重新启动。
    • 已删除:容器被删除后,其所有数据和状态都会被清除。
  • 镜像(Image):镜像是容器的模板,是只读的。它包含了容器运行所需的文件系统和应用程序的初始状态。镜像是由一系列的分层文件系统组成的,每一层都包含了特定的修改或更新。

  • 镜像仓库(Image Registry):镜像仓库是用于存储和分发 Docker 镜像的地方。最常用的公共镜像仓库是 Docker Hub,上面有大量的官方和社区共享的镜像。此外,还可以搭建私有的镜像仓库,用于存放自己的镜像。

  • Dockerfile:Dockerfile 是一种文本文件,用于定义 Docker 镜像的构建过程。它包含了一系列的指令,用于指定基础镜像、安装软件、拷贝文件、配置环境等。通过 Dockerfile,可以自动化地构建镜像,确保镜像的一致性和可重复性。

4. Docker容器与虚拟机技术的区别和联系

Docker容器和虚拟机都是用于隔离和运行应用程序的技术,但它们在实现方式、性能、资源占用、启动速度等方面存在显著差异。以下是它们的主要区别:

  • Docker容器:容器是一种轻量级的隔离运行环境,基于宿主机的操作系统内核,共享内核但拥有独立的文件系统、网络接口和进程空间。容器启动快(通常几秒内完成),资源占用低,性能接近物理机,适合快速部署和运行应用程序,尤其适用于微服务架构和开发测试环境。
  • 虚拟机:虚拟机通过虚拟化技术创建一个完整的虚拟计算机环境,运行独立的操作系统和应用程序。它提供强隔离性,适合运行多个不同操作系统或需要高度安全隔离的场景。虚拟机启动慢(通常几分钟),资源占用高,性能损耗较大,但可移植性强,适合长期运行且对隔离性要求高的应用。

5. 运行第一个容器

首先,请安装Docker并配置Docker的apt源。

  • 配置Docker的APT源主要是为了确保能够从官方或可信的源中安装和更新Docker软件包,同时也能解决一些常见的问题,比如版本兼容性、软件更新以及网络访问速度等。
  • 由于Docker Hub的服务在国外,下载镜像比较慢,最好配置成为免费的国内镜像服务。

环境就绪,马上运行第一个容器,执行命令:

docker run -d -p 80:80 httpd

结果如图所示:

其过程可以简单描述为:

1. 从Docker Hub下载httpd镜像

2. 启动httpd容器,并将容器的80端口映射到host的80端口

3. 下面可以通过浏览器验证容器是否正常工作。在浏览器中输入:http://[your ubuntu host ip]/

结果如图所示:

二. 容器技术

容器技术,需要搞清楚 What、why 和 How三个方面:什么是容器、为什么使用容器、容器是如何工作的。其中容器是怎样工作的,是容器核心知识的最主要部分。

1. What - 什么是容器?

容器是一种轻量级、可移植、自包含的软件打包技术,使应用程序可以在几乎任何地方以相同的方式运行。

容器与虚拟机

谈到容器,就不得不将它与虚拟机进行对比,因为两者都是为应用提供封装和隔离。

  • 容器由两部分构成:应用程序本身、及其依赖(比如应用程序需要的库或者其他软件容器在Host操作系统的用户空间中运行,与操作系统的气压进程隔离,这一点显著区别于虚拟机)。
  • 传统的虚拟化技术:目标是创建完整的虚拟机。为了运行应用,除了部署应用本及其依赖,还得安装整个操作系统。

由于所有容器共享一个host os,这使得容器在体积上要比虚拟机小很多。另外,启动容器不需要启动整个操作系统,所以容器部署和启动更快、开销更小也更容易迁移。

2. Why - 为什么需要容器?

为什么需要容器,容器到底解决了什么问题?简要的答案是,容器使软件具备了超强的移植能力。

就像集装箱解决了货物运输过程中,不同种类的货物相互影响、干扰的难题。

任何货物,不论是钢琴和保时捷,都被放到各自的集装箱中。集装箱在整个运输过程中都是密封的,只有到达最终目的地才会被打开。集装箱被誉为运输界与世界贸易最重要的发明。(容器和集装箱的英文单词都是:Container)

Docker将集装箱思想用到软件打包上,为代码提供了一个基于容器的标准化运输系统。

Docker可以将任何应用以及依赖打包成一个轻量级、可移植、自包含的容器。容器可以运行在几乎所有的操作系统上。

3. How - 容器是如何工作的

Docker架构

Docker的核心组件包括:

  • Docker客户端:Client
  • Docker服务器:Docker daemon
  • Docker镜像:Image
  • Registry
  • Docker容器:Container

Docker架构如图所示

Docker采用的是Client / Server架构。客户端向服务器发送请求,服务器请求构建、运行和分发容器。客户端和服务器可以运行在同一个Host上,客户端也可以通过socket或REST API与远程服务器通信。

Docker服务器:Docker Daemon

Docker 服务器是容器管理的核心,负责实际的容器生命周期管理和资源分配。

Docker服务器是Docker的后台服务进程,通常定义为Docker守护进程。它负责管理Docker的生命周期,包括创建、运行、停止、删除容器等操作。

功能:

  • 容器管理:接收来自客户端的指令,执行容器的创建、启动、停止、删除等操作。
  • 镜像管理:管理Docker镜像的拉取、存储和推送
  • 网络管理:配置容器的网络环境,包括虚拟网络、端口映射等。
  • 存储管理:管理容器的存储卷,支持数据持久化。
  • 资源隔离:通过 Linux 内核的命名空间(Namespaces)和控制组(Cgroups)技术,为容器提供隔离的运行环境。

运行方式:Docker服务器通常在后台运行,监听来自客户端的请求,并执行相应的操作。

Docker客户端:Docker CLI

Docker 客户端是用户与 Docker 服务器之间的桥梁,提供用户友好的交互方式,方便用户发送命令和管理容器。最常用的Docker客户端是docker命令。通过docker我们可以方便地在Host上构建和运行容器。

  • Docker客户端是用户与Docker服务器交互的工具,通常是一个命令行界面(CLI),用户通过它发送命令来控制Docker服务器。

功能:

  • 命令执行:用户通过命令行输入指令,如 docker rundocker builddocker stop 等,将这些指令发送给 Docker 服务器。
  • 交互界面:提供用户友好的交互方式,方便用户管理容器和镜像。
  • 配置管理:允许用户配置 Docker 的运行参数,如网络设置、存储驱动等。

运行方式:Docker 客户端通常运行在用户的本地机器上,通过网络(默认是本地套接字)与 Docker 服务器通信。

Docker镜像:Image

可将Docker镜像看成只读模板,通过它可以创建Docker容器。

镜像有多种生成方法:

  • 从无到有开始创建镜像
  • 下载并使用别人创建好的现成的镜像
  • 在现有镜像上创建新的镜像

可以将镜像的内容和创建步骤描述在一个文本文件中,这个文件被称为Dockerfile,通过执行docker build <docker-file> 命令可以构建出Docker镜像。

Docker容器:Container

Docker容器就是Docker镜像的运行实例。

用户可以通过CLI(Docker)或是API启动、停止、移动或删除容器。可以这么认为:对于应用软件,镜像是软件生命周期的构建和打包阶段,而容器则是启动和运行阶段。

Registry:存放Docker镜像的仓库

Registry是存放Docker镜像的仓库,Registry分为私有和公有两种。

Docker Hub(https://hub.docker.com/)是默认的Registry,由Docker公司维护,上面有数以万计的镜像,用户可以自由下载和使用。

出于对速度或安全的考虑,用户也可以创建自己的私有Registry。

  • docker pull 命令可以从Registry下载镜像。
  • docker run 命令则是先下载镜像(如果本地没有),然后再启动容器。

还记得我们运行的第一个容器吗?现在通过它来体会一下Docker各个组件是如何协作的。容器启动过程如下:

1. Docker客户端执行docker run命令

2. Docker Daemon发现本地没有httpd镜像

3. daemon从Docker Hub下载镜像

4. 下载完成,镜像httpd被保存到本地

5. Docker daemon启动容器。

docker images已经可以查看到httpd已经下载到本地

docker ps 或者 docker container ls 显示容器正在运行。

4. 小结

Docker借鉴了集装箱的概念。标准集装箱将货物运往世界各地,Docker将这个模型运用到自己的设计哲学中。唯一不同的是:集装箱运输货物,Docker运输软件。

每个容器都有一个软件镜像,相当于集装箱中的货物。容器可以被创建、启动、关闭和销毁。和集装箱一样,Docker在执行这些操作时,并不关心容器里面到底装的什么,它不管里面是Web Server,还是Data-base。用户不需要关心容器最终在哪里运行,因为在哪里都可以运行

开发人员可以在笔记本上构建镜像并上传到Registry,然后QA人员将镜像下载到物理或虚拟机做测试,最终容器会部署到生产环境。

使用Docker以及容器技术,我们可以快速的构建一个应用服务器、一个消息中间件、一个数据库、一个持续集成的环境。因为Docker Hub上有我们能想到的几乎所有的镜像。

三. Docker镜像

镜像是Docker容器的基石,容器是镜像的运行实例,有了镜像才能启动容器。

本章内容安排如下:首先通过研究几个典型的镜像,分析镜像的内部结构;然后学习如何构建自己的镜像;最后介绍怎样管理和分发镜像。

1. 镜像的内部结构

为什么我们要讨论镜像的内部结构?如果只是使用镜像,当然不需要了解,直接通过Docker命令下载和运行就可以了。

但如果我们想构建自己的镜像,或者想理解Docker为什么是轻量级的,就非常有必要学习这部分知识了。

我们从一个最小的镜像开始学习。

hello-world -- 最小的镜像

hello-world是Docker官方提供的一个镜像,通常用来检验Docker是否安装成功。我们先通过docker pull 从Docker Hub下载它,如图所示:

用 docker images 查看镜像的信息,如图所示:

hello-world竟然还不到2kb,通过docker run运行,如图所示:

其实我们更关心 hello-world 镜像包含了哪些内容。

Dockerfile是镜像的描述文件,定义了如何构建Docker镜像。Dockerfile的语法简洁且可读性强,后面我们会讨论如何编写Dockerfile。

hello-world 的 Dockerfile内容如下图所示:

只有短短三条指令。

(1)From scratch镜像是白手起家,从0开始构建

(2)COPY hello/ 将文件 “hello”复制到镜像的根目录

(3)CMD ["/hello"] 容器启动时,执行 /hello

镜像hello-world中就只有一个可执行文件 “hello”,其功能就是打印出 “Hello from Docker...”等信息。

/hello 就是文件系统的全部内容,连最基本的 /bin /usr /lib /dev 都没有

hello-world虽然是一个完整的镜像,但它并没有什么实际用途。通常来说,我们希望镜像能够提供一个基本的操作系统环境,用户可以根据需要安装和配置软件。

这样的镜像我们称作 base镜像。

base镜像

base镜像有两层含义:

  • 不依赖于其他镜像,从scratch构建
  • 其他镜像可以以之为基础进行扩展

所以,能称作base镜像的通常都是各种Linux发行版的Docker镜像,比如Ubuntu、Debian、CentOS等。

我们以CentOS为基础为例考察base镜像包含哪些内容。

下载镜像:

docker pull centos

查看镜像信息,如下图:

镜像大小不到200MB

等一下!

一个CentOS才200MB?

平时我们安装一个CentOS至少都有几个GB,怎么可能才200MB!

相信这是几乎所有 Docker 初学者都会有的疑问,包括我自己。下面我们来解释这个问题。

Linux操作系统由内核空间和用户空间组成,如下图:

1. rootfs

内核空间是kernel,Linux刚启动时会加载bootfs文件系统,之后bootfs会被卸载掉。

用户空间的文件系统是rootfs,包含我们熟悉的 /dev /proc /bin等目录

对于 base镜像 来说,底层直接用 Host 的 kernel,自己只需要提供rootfs就行了。

  • 而对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了。相比其他的Linux发行版,CentOS的rootfs已经算臃肿的了,alpine还不到10MB
  • 我们平时还会安装的CentOS除了rootfs之外,还会选装很多软件、服务、图形桌面等等,需要好几个GB就不足为奇了。

2. base镜像提供的是最小安装的Linux发行版

CentOS镜像的Dockerfile的内容如下图所示:

第二行ADD指令添加到镜像的 tar 包就是 CentOS 7 的rootfs,在制作镜像时,这个tar包会自动解压到 / 目录下,生成 /dev、/proc、/bin等目录。

支持运行多种LinuxOS

不同Linux发行版的区别主要就是rootfs,所以Docker可以同时支持多种Linux镜像,模拟出多种操作系统环境。

上图Debian和BusyBox(一种嵌入式Linux)上层提供各自的rootfs,底层共用Docker Host的kernel

2. 镜像的分层结构

Docker支持通过扩展现有镜像,创建新的镜像。

实际上,Docker Hub中99%的镜像都是通过在base镜像中安装和配置需要的软件构建出来的。比如我们构建一个新的镜像,Dockerfile 如下图所示:

(1)新镜像不再是从scratch开始,而是直接在Debian base镜像上创建

(2)安装 emacs 编辑器

(3)安装 Apache2

(4)容器启动时运行 bash

构建过程中如下图:

可以看到,新镜像是从base镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。

为什么Docker镜像要采用这种分层结构呢?

最大的一个好处就是:共享资源。

3. 构建镜像

对于Docker用户来说,最好的情况是不需要自己创建镜像。几乎所有常用的数据库、中间件、应用软件等都有现成Docker官方镜像或其他人和组织创建的镜像,我们只需要稍作配置就可以直接使用。

使用现成镜像的好处除了省去自己做镜像的工作量外,更重要的是可以利用前人的经验。特别是使用官方的镜像,因为Docker工程师更知道如何更好地在容器中运行软件。

当然,某些情况下我们也不得不自己构建镜像,比如:

(1)找不到现成的镜像,比如自己开发的应用程序。

(2)需要在镜像中加入特定的功能,比如官方镜像几乎都不提供ssh

所以本节我们将介绍构建镜像的方法。同时分析构建的过程也能够加深我们对前面镜像分层结构的理解。

Docker提供了两种构建镜像的方法:docker commit命令与Dockerfile构建文件。

docker commit

docker commit 命令是创建新镜像最直观的方法,其过程包含三个步骤:

  • 运行容器
  • 修改容器
  • 将容器保存为新的镜像

举个例子:在Ubuntu base镜像中安装vi并保存为新镜像。

(1)运行容器

如图所示:

-it的作用是以交互模式进入容器,并打开终端。

(2)安装vi

确认vi没有安装,如下图所示:

安装vi,如下图所示:

(3)保存为新镜像

在新窗口中查看当前运行的容器,如图所示:

silly_goldberg是Docker为我们容器随机分配的名字。

执行 docker commit 命令将容器保存为镜像,如图所示:

新镜像命名为ubuntu-with-vi

查看新镜像的属性,如图所示:

从size上看到镜像因为安装了软件而变大了。

从新镜像启动容器,验证 vi 已经可以使用,如图所示:

以上演示了如何用 docker commit创建新镜像。然而,Docker并不建议用户通过这种方式构建镜像。原因如下:

(1)这是一种手动创建镜像的方式,容易出错,效率低且可重复性若。比如要在 debian base镜像中也加入vi,还得重复前面所有的步骤。

(2)更重要的:使用者并不知道镜像是如何创建出来的,里面是否有恶意程序。也就是说无法对镜像进行审计,存在安全隐患。

既然 docker commit不是推荐的方法,我们为什么还要花时间学习呢?原因是,即便是用Dockerfile(推荐方法)构建镜像,底层也是docker commit一层一层构建新镜像的。学习docker commit 能够帮助我们更加深入地理解构建过程和镜像的分层结构。

Dockerfile

Dockerfile是一个文本文件,记录了镜像够简单的所有步骤。

1. 第一个Dockerfile

用 Dockerfile 创建上节的 ubuntu-with-vi,其内容如图所示:

下面我们运行 docker build 命令构建镜像并详细分析每个细节。

root@ubuntu:~# pwd ①/rootroot@ubuntu:~# ls ②Dockerfileroot@ubuntu:~# docker build -t ubuntu-with-vi-dockerfile . ③Sending build context to Docker daemon 32.26 kB ④Step 1 : FROM ubuntu ⑤---> f753707788c5Step 2 : RUN apt-get update && apt-get install -y vim ⑥---> Running in 9f4d4166f7e3 ⑦......Setting up vim (2:7.4.1689-3ubuntu1.1) ...---> 35ca89798937 ⑧Removing intermediate container 9f4d4166f7e3 ⑨Successfully built 35ca89798937 ⑩root@ubuntu:~#

① 当前目录为 /root。

② Dockerfile准备就绪。

③ 运行docker build命令,-t将新镜像命名为ubuntu-with-vi-dockerfile,命令末尾的.指明build context为当前目录。Docker默认会从build context中查找Dockerfile文件,我们也可以通过-f参数指定Dockerfile的位置。

④ 从这步开始就是镜像真正的构建过程。

首先Docker将build context中的所有文件发送给Docker daemon。build context为镜像构建提供所需要的文件或目录。 Dockerfile中的ADD、COPY等命令可以将build context中的文件添加到镜像。此例中,build context为当前目录 /root,该目录下的所有文件和子目录都会被发送给Docker daemon。 所以,使用build context就得小心了,不要将多余文件放到build context,特别不要把 /、/usr作为build context,否则构建过程会相当缓慢甚至失败。

⑤ Step 1:执行FROM,将Ubuntu作为base镜像。 Ubuntu镜像ID为f753707788c5。

⑥ Step 2:执行RUN,安装vim,具体步骤为 ⑦ ⑧ ⑨。

⑦ 启动ID为9f4d4166f7e3的临时容器,在容器中通过apt-get安装vim。

⑧ 安装成功后,将容器保存为镜像,其ID为35ca89798937。 这一步底层使用的是类似docker commit的命令。

⑨ 删除临时容器9f4d4166f7e3。

⑩ 镜像构建成功。

通过docker images查看镜像信息,如图3-21所示。 [插图] 图3-21 镜像ID为35ca89798937,与构建时的输出一致。 在上面的构建过程中,我们要特别注意指令RUN的执行过程 ⑦ ⑧ ⑨。Docker会在启动的临时容器中执行操作,并通过commit保存为新的镜像。

2. 查看镜像的分层结构

ubuntu-with-vi-dockerfile 是通过在base镜像的顶部增加一个新的镜像层而得到的,如图所示:

这个新镜像层的内容由 RUN apt-get update && apt-get in stall -y vim 生成。这一点我们可以通过docker history命令验证,如图所示:

docker history会显示镜像的构建历史,也就是Dockerfile的执行过程。

ubuntu-with-vi-dockerfile 与 Ubuntu 镜像相比,确实只是多了顶部的一层35ca89798937,由apt-get命令创建,大小为97.07MB。docker history向我们展示了镜像的分层结构,每一层由上至下排列。

注:missing表示无法获取IM-AGE ID,通常从 Docker Hub 下载的镜像会有这个问题。

3. 镜像的缓存特征

我们接下来看Docker镜像的缓存特征。

Docker会缓存已有镜像的镜像层,构建新镜像时,如果某镜像直接存在,就直接使用,无需重新创建。

例如,如果在Dockerfile中添加一点新内容,往镜像中复制一个文件:

(1)确保 testfile 已存在

(2)由于之前已经运行过相同的 RUN 命令,这次直接使用缓存中的镜像层 35ca89798937

(3)执行 COPY 命令

其过程是启动临时容器,复制 testfile,提交新的镜像层 8d02784a78f4,删除临时容器。

在ubuntu-with-vi-dockerfile 镜像上直接添加一层就得到了新的镜像 ubuntu-with-vi-docker-file-2,如图所示:

如果我们希望在构建镜像时不使用缓存,可以在 docker build 命令中加上 no-cache 参数。

Dockerfile每一个指令就会创建一个镜像层,上层是依赖于下层的。无论什么时候,只要某一层发生变化,其上面所有层的缓存都会失效。 

也就是说,如果我们改变 Dockerfile 的执行顺序,或者修改或者添加指令,都会使缓存失效。举例说明:

  • 如果交换前面 RUN 和 COPY 的顺序,如图所示:
  • 虽然在逻辑上这种改动对镜像的内容没有影响,但由于分层的结构特征,Docker必须重建受影响的镜像层。
  • 从执行过程可以看到,生成了新的镜像层,缓存已经失效。

除了构建时使用缓存,Docker在下载镜像时也会使用。

4. 调试Dockerfile

总结一下通过 Dockerfile 构建镜像的过程:

(1)从base镜像运行一个容器

(2)执行一条指令,对容器做修改

(3)执行类似docker commit的操作,生成一个新的镜像

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

(5)重复2~~4步,直到Dockerfile中的所有指令执行完毕

5. Dockerfile 常用指令

是时候系统学习Dockerfile了

  • FROM:指定base镜像
  • MAINTAINER:设置镜像作者,可以是任意字符串
  • COPY:
    • 将文件从build context复制到镜像
    • COPY支持两种形式:COPY src dest 与 COPY ["src", "dest"]
    • 注意,src只能指定 build context 中的文件或目录
  • ADD:
    • 与COPY类似,从 build context 复制文件到镜像。不同的是,如果 src 是归档文件(tar、zip、tgz、xz等),文件会被自动解压到dest
  • ENV:
    • 设置环境变量,环境变量可以被后面的指令使用。例如:
    • ENV MY_VERSION 1.3 RUN apt-get install -y mypackage=$MY_VERSION

  • EXPOSE:

    • 指定容器中的进程会监听某一个端口,Docker可以将该端口暴露出来。

  • VOLUMN:

    • 将文件或者目录声明为volume

  • WORKDIR:

    • 为后面的RUN、CMD、ENTRY-POINT、ADD或COPY指令设置镜像中的当前工作目录

  • RUN

    • 在容器中执行指定的命令

  • CMD

    • 容器启动时运行指定的命令

    • Dockerfile可以有多个CMD指令,但只有最后一个生效。CMD可以被 docker run 之后的参数替换。

  • ENTRYPOINT

    • 设置容器启动时运行的命令。

    • Dockerfile中可以有多个ENTRYPOINT指令,但只有最后一个生效。CMD 或 docker run之后的参数会被当做参数传递给 ENRTYPOINT。

这是一个比较全面的Dockerfile(注:Dockerfile支持以 “#” 开头的注释)

构建镜像,如下图:

(1)构建前确保build context中存在需要的文件

(2)依次执行Dockerfile指令,完成构建

(3)运行容器,验证镜像内容,如下图

1. 进入容器,当前目录即为WORKDIR

如果WORKDIR不存在,Docker会自动帮我们创建

2. WORKDIR中保存了我们希望的文件和目录

目录bunch:由ADD指令从build context复制的归档文件bunch.tar.gz,已经自动解压。 文件tmpfile1:由RUN指令创建。 文件tmpfile2:由COPY指令从build context复制。

3. ENV指令定义的环境变量已经生效。

RUN vs CMD vs ENTRYPOINT

RUN、CMD和ENTRYPONIT这三个Dockerfile指令看上去很类似,很容易混淆。

简单地说:

(1)RUN:执行命令并创建新的镜像层,RUN经常用于安装软件包

(2)CMD:设置容器启动后默认执行的命令及其参数,但CMD能够被 docker run 后面接的命令行替换

(3)ENTRYPOINT:配置容器启动时运行的命令

最佳实践:

1. 使用RUN命令安装应用和软件包,构建镜像

2. 如果docker镜像的用途是运行应用程序或服务,比如运行一个MySQL,应该使用Exec格式的ENTRYPOINT指令。CMD可为ENTRYPONIT提供额外的默认参数,同时可以利用 docker run 命令行替换默认参数,同时可以利用 docker run 命令行替换默认参数。

3. 如果想为容器设置默认的启动命令,可使用CMD指令,用户可在 docker run 命令中替换此默认命令。

4. 小结

本章我们学习了Docker镜像。首先讨论了镜像的分层结构,然后学习了如何构建镜像,最后实践使用Docker Hub和本地registry。

下面是镜像的常用操作子命令:

  • images:显示镜像列表。
  • history:显示镜像构建历史。
  • commit:从容器创建新镜像。
  • build:从Dockerfile构建镜像。
  • tag:给镜像打tag。
  • pull:从registry下载镜像。
  • push:将镜像上传到registry。
  • rmi:删除Docker host中的镜像。
  • search:搜索Docker Hub中的镜像。

以上是 docker 技术的基本概念,其余知识明日继续连载

Good night~~

-- 2025年5月2日

相关文章:

  • STM32——GPIO
  • JAVA继承详细总结
  • MySQL 窗口函数
  • 解决Flutter项目中Gradle构建Running Gradle task ‘assembleDebug‘卡顿问题的终极指南
  • Ubuntu系统下Firefox浏览器完整指南:故障修复、国内版安装与下载加速
  • 如何封装一个线程安全、可复用的 HBase 查询模板
  • Midjourney 绘画 + AI 配音:组合玩法打造爆款短视频!
  • 模拟开发授权平台
  • Flutter BottomNavigationBar 详解
  • 定制开发开源AI智能名片S2B2C商城小程序驱动的无界零售基础设施变革研究——基于京东模式的技术解构与商业重构
  • 单链表操作(single list)
  • Unity 与 Lua 交互详解
  • (转)角色与动画的性能优化 | UnrealFest演讲干货
  • 第 7 篇:跳表 (Skip List):简单务实的概率性选手
  • MATLAB图像加密案例
  • 城市智控 | 废弃物分类可视化管理平台
  • MySQL 索引不生效的情况
  • python 桌面程序开发简述及示例
  • TS 常用类型
  • Redis宣布再次开源
  • 习近平给谢依特小学戍边支教西部计划志愿者服务队队员的回信
  • 融创中国清盘聆讯延至8月25日,清盘呈请要求遭到部分债权人反对
  • 月薪3万文科友好,“AI训练师”真有那么赚?
  • 菏泽家长“付费查成绩”风波调查:免费功能被误读
  • 49:49白热化,美参议院对新关税政策产生巨大分歧
  • 扬州市中医院“药膳面包”走红,内含党参、黄芪等中药材