一、Docker 构建过程中,FROM 拉取基础镜像原理

在 Docker 构建过程中,FROM 指令在 Dockerfile 中用于指定基础镜像,它告诉 Docker 从哪个镜像开始构建你的新镜像。这个指令是每个 Dockerfile 的起点,也是构建自定义镜像的基础。以下是这一步骤拉取动作的内部工作原理:

拉取基础镜像的过程

  1. 解析 FROM 指令:当 Docker 解析 Dockerfile 并遇到 FROM 指令时,它会查看指令后面指定的镜像名称和标签(或摘要)。例如,FROM ubuntu:20.04 指定了使用名为 ubuntu 的镜像和 20.04 这个版本标签。

  2. 检查本地缓存:Docker 首先检查本地是否已经存在指定的镜像和标签。如果本地存在且用户没有通过命令显式要求强制拉取最新版本(例如,在构建前手动执行 docker pull ubuntu:20.04),Docker 将使用本地缓存的镜像进行构建,不会从远程仓库拉取。

  3. 从远程仓库拉取:如果本地不存在指定的镜像和标签,Docker 则会从配置的远程仓库(默认是 Docker Hub)拉取所需的镜像。Docker 客户端会向仓库发送请求,下载镜像和所有必要的层到本地。

  4. 使用基础镜像构建新镜像:一旦基础镜像被拉取到本地(或确认本地已有),Docker 会使用这个镜像作为新镜像构建的起点。接下来,Dockerfile 中的其他指令(如 RUNCOPYCMD 等)会被执行,以在基础镜像上添加新的层,最终形成新的镜像。

控制拉取行为

  • 要确保总是使用最新版本的基础镜像进行构建,可以在构建之前手动执行 docker pull 命令强制拉取最新版本的镜像。
  • 对于重要或生产环境的构建,推荐在 Dockerfile 中使用具体的版本号而不是 latest 标签,以保证构建的一致性和可重复性。

自动拉取的触发

当执行 docker build 命令开始构建镜像时,如果 Dockerfile 中的 FROM 指令指定的基础镜像不在本地,或者用户通过 docker build --pull 选项强制更新,Docker 就会自动执行上述拉取过程。这样确保了每次构建都基于最新或指定的基础镜像。

二、使用 latest 标签拉取基础镜像并不是最新版本原因

当你在 Dockerfile 中指定使用 latest 标签拉取基础镜像,但实际上拉取到的并不是最新版本,可能是由于以下几个原因:

1. 本地缓存

最常见的原因是 Docker 在你的机器上已经有了该镜像的 latest 版本的本地缓存。当 Docker 发现本地已经存在请求的镜像和标签时,它默认会使用这个本地版本,而不会去远程仓库检查是否有更新。这意味着即使远程仓库中的 latest 标签已经更新,你仍然会得到本地缓存的版本。

解决方案

要确保每次都能拉取到最新版本的镜像,你可以在拉取镜像时使用 docker pull 命令手动强制更新:

docker pull imagename:latest

这个命令告诉 Docker 忽略本地缓存,直接从远程仓库拉取 latest 标签的镜像。

2. 远程仓库的 latest 标签没有更新

latest 标签可能并不总是指向最新的镜像版本。镜像的维护者可能没有更新 latest 标签来指向最新发布的版本。这种情况下,即使你拉取 latest 标签,也可能不是最新的发行版本。

解决方案

  • 手动检查镜像版本:在 Docker Hub 或其他 Docker 镜像仓库中查看该镜像的所有可用标签,确认哪个是最新版本。
  • 使用特定版本号:如果可行,最好在 Dockerfile 中指定特定的版本号而不是使用 latest 标签。这样可以确保构建的一致性和可重复性。

3. Docker 镜像拉取策略

Docker 的默认行为是优先使用本地缓存的镜像,这是为了减少不必要的网络请求,加快构建过程。但这也可能导致使用了旧的镜像。

总结

要确保总是使用最新版本的基础镜像,建议定期更新本地镜像库,并在必要时手动拉取最新的镜像。同时,明确指定需要使用的镜像版本号可以避免因 latest 标签更新延迟带来的问题,确保你的项目依赖于一个确定和稳定的环境。

三、进入docker容器

要查看 Docker 镜像中的文件,你可以通过创建并运行一个容器来实现,然后在这个容器的环境中探索文件系统。这是一个相对简单且常见的做法,允许你查看、修改甚至测试镜像中的文件而不影响原始镜像。以下是具体的步骤:

1. 创建并启动容器

首先,你需要从镜像创建一个容器。使用以下命令启动一个容器,并进入其命令行界面:

docker run -it --name temp-container your-image-name bash

这里,your-image-name 是你想要探索的镜像名称。如果镜像中包含了 bashsh(大多数 Linux 基础镜像都包含),该命令将启动一个交互式终端。如果镜像不包含 bash,你可以尝试使用 sh 或其他可用的 shell。

  • -it 选项表示交互式地分配一个伪终端。
  • --name temp-container 是给新创建的容器指定一个名称,这样稍后如果需要,你可以通过名字来引用它。
  • bash 指的是在容器内启动的 shell,如果容器内部有 bash 的话。

2. 探索文件系统

一旦容器启动,并且你已经进入了容器的 shell,你就可以使用 Linux 命令来探索文件系统了。例如:

  • 使用 lscd 命令浏览目录。
  • 使用 catmoreless 查看文件内容。
  • 使用 find 命令搜索特定的文件。

3. 退出容器

当你完成文件系统的探索后,可以通过输入 exit 命令退出容器的 shell。这将停止并退出容器,但容器的文件系统更改(如果有的话)将保留在该容器中,直到容器被删除。

4. 清理(可选)

如果你完成了探索并且不需要保留对容器所做的任何更改,可以删除这个临时容器。首先,停止容器(如果它还在运行的话):

docker stop temp-container

然后,删除容器:

docker rm temp-container

如果你只是想查看文件而不打算做任何修改,这些步骤可以帮你在不更改原始镜像的情况下查看镜像内容。如果你需要对镜像做修改,考虑创建一个新的 Dockerfile 并根据需要调整,然后重新构建镜像。

四、进入容器后jar包解压

在容器内部处理 .jar 文件(Java ARchive 文件,一种打包 Java 类和元数据的压缩格式)时,你可以使用 jar 命令进行解压,如果该容器基于 JDK 或 JRE 镜像,jar 命令应该已经可用。如果容器环境中没有 jar 命令,你可能需要使用其他工具如 unzip 来进行解压,因为 JAR 文件本质上是 ZIP 文件。

使用 jar 命令解压

在容器的命令行中,你可以运行以下命令来解压一个 JAR 文件:

jar -xvf your-file.jar

这里:

  • -x 表示解压模式。
  • -v 表示生成详细输出。
  • -f 指定被操作的文件。

使用 unzip 命令解压

如果 jar 工具不可用,你可以尝试使用 unzip 命令,这需要你的容器中安装了 unzip 工具:

unzip your-file.jar

如果发现 unzip 命令也不可用,且你有权限修改容器或者可以请求容器的维护者进行更改,可以安装 unzip。例如,在基于 Debian 或 Ubuntu 的容器中,你可以使用:

apt-get update && apt-get install -y unzip

然后再次尝试使用 unzip 命令解压 JAR 文件。

注意

在进行上述操作时,请确保你有足够的权限来安装软件或者运行这些命令,特别是在生产环境中的容器。如果是生产环境中的容器,最佳实践是避免在容器内部安装额外的软件或者修改容器环境,以保持环境的干净和稳定。如果需要频繁进行此类操作,考虑创建一个自定义镜像,其中包含所需的所有工具和依赖。

五、删除、停止容器

要停止运行中的 Docker 容器,你可以使用 docker stop 命令。这个命令会向容器发送 SIGTERM 信号,请求容器正常停止。如果容器在一定时间内(默认为 10 秒)没有响应,docker 会进一步发送 SIGKILL 信号强制停止容器。

基本用法

docker stop [OPTIONS] CONTAINER [CONTAINER...]

这里,[OPTIONS] 是可选项,CONTAINER 是你想要停止的容器的 ID 或名称。如果你想同时停止多个容器,可以在命令中列出它们的 ID 或名称,用空格分隔。

示例

假设你有一个运行中的容器,其名称或 ID 为 my_container,你可以使用以下命令停止它:

docker stop my_container

如果你有多个容器需要停止,比如 container1container2,可以这样:

docker stop container1 container2

强制停止容器

如果一个容器没有响应 docker stop 命令,你可以使用 docker kill 命令立即强制停止它。docker kill 命令默认发送 SIGKILL 信号,确保容器被立即停止。

docker kill [OPTIONS] CONTAINER [CONTAINER...]

例如,要强制停止 my_container,你可以使用:

docker kill my_container

注意事项

  • 尽管 docker kill 命令可以立即停止容器,但最好首先尝试使用 docker stop,以便容器可以正常清理并完成必要的关闭操作。
  • 使用 docker stopdocker kill 命令停止容器后,容器的状态将变为停止,但容器的文件系统和设置仍然保留在 Docker 主机上。如果你想删除容器及其文件系统,可以使用 docker rm 命令。

通过这些命令,你可以有效管理 Docker 容器的运行状态,确保资源得到合理分配和使用。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐