docker-compose:不同的运行、执行和层会发生什么

据我了解dockerdocker-compose流程是这样的:

Dockerfile --build--> Docker Image --create--> Docker Container #1
                                   --create--> Docker Container #2
                                   --create--> ...
                                   --create--> Docker Container #n

所以Image是由 中的命令制作的,Dockerfile但纯粹是某种“离线”版本。您可以将其“联机”,然后作为容器使用。

我的理解docker-compose up是通过service里面的定义为我们做这个两步过程docker-compose.yml,除了一些其他的东西,比如安装卷,暴露端口等等。


我的第一个问题是:

如果我运行docker-compose exec some_command,那么我正在操纵 docker 容器 - 对吗?

据我了解的文档,docker-compose run some_command几乎是一样的,但是,它事先创建了一个新的“层”,所以…… 像这样:

Docker Container #n (layer 0) ----> Docker Container #n (layer 1)

some_command正确的-然后对层1中执行?此外,它似乎run正在传递some_command到入口点,而exec确实覆盖了定义的入口点。

我的第二个问题是:

run之后创建的新层会发生什么?有没有办法在不创建新层的情况下执行命令?我想知道,因为我添加了一个这样的入口点脚本:

#!/bin/sh

case "$@" in
    "update")
        pip3 install -r requirements.txt
        ;;
    "start")
        python manage.py runserver
        ;;
    *)
        echo "executing $@"
        exec "$@"
        ;;
esac

我这样做是为了能够通过运行像docker-compose run backend update. 问题是run如果我up之后运行,则不会使用创建的图层。

回答

首先让我们澄清这里的基本术语。引用官方文档:

一个图像是用于创建一个码头工人容器指令的只读模板。

基本上,映像只是一个文件系统存档,其中包含文件和目录结构以及容器的一些附加元数据(如ENVCMD)。因此,您也可以将其视为一个tarzip存档。

容器是图像的可运行实例。

要从镜像启动一个新容器,需要解压镜像docker,设置各自的命名空间,并使用解压后的镜像作为文件系统根启动一个进程。

通常所说的通过在生成过程中创建的图像中,并且被用于高速缓存和重用在多个图像中的公共文件/层。因此,您只需要在Dockerfile.

而不是为每个新容器提取/复制图像内容,docker只会在存储该容器更改的图像顶部添加一个薄的可写层。这的确切机制是一个实现细节取决于使用的存储驱动程序!在大多数情况下,使用时docker您不需要关心这一点。


现在使用docker-compose:它在后台所做的基本上是构建和执行相应的docker命令*,以根据您的docker-compose.yml配置文件运行和管理您的服务所需的容器。因此,让我们看看docker-compose与相应docker命令的关系:

  • docker-compose build: 将docker build使用指定build选项为每个服务执行相应的命令
  • docker-compose pull: docker pulls 所有服务的图像,带有image来自相应存储库的选项
  • docker-compose up
    • 如有必要:将首先docker-compose build/docker-compose pull所有您的服务
    • 通过构建和执行相应的docker run命令来启动服务容器
  • docker-compose exec: 将运行docker exec以在现有的运行容器中启动新进程/命令
  • docker-compose run: 启动一个新的容器来交互执行指定​​的命令,即执行docker run

* 请注意,docker-compose实际上没有调用docker命令,而是docker直接使用 API与守护程序对话。但为了更容易理解,你可以假装它确实如此。


现在回答你的问题:

如果我运行docker-compose exec some_command,那么我正在操纵 docker 容器 - 对吗?

据我了解的文档,docker-compose run some_command几乎是一样的,但是,它事先创建了一个新的“层”,所以…… 像这样:

docker-compose exec将在您现有的、正在运行的服务容器中运行,同时docker-compose run将启动一个新的、独立的容器

此外,它似乎run正在传递some_command到入口点,而exec确实覆盖了定义的入口点。

正确,exec不使用入口点。

run之后创建的新层会发生什么?有没有办法在不创建新层的情况下执行命令?

这些更改是由其启动的容器的一部分,run并将持续到您删除容器为止。但是,如果要将更改应用于服务容器(由 使用docker-compose up),则需要运行docker-compose exec!

我想知道,因为我添加了一个这样的入口点脚本:

我这样做是为了能够通过运行像docker-compose run backend update.

由于docker-compose run将在新容器中执行该命令,因此您需要运行docker-compose exec而不是手动调用入口点:

docker-compose exec app /entrypoint.sh update

# and if you need to restart your app restart the service containers
docker-compose restart

然而,这是错误的使用方式docker因为容器是短暂的,在容器中执行的命令只会影响该特定容器。当您必须在该映像上运行新的容器实例(您停止容器、电源故障等)时,所有更改都将丢失。

相反,您应该将update命令作为(最后一个)命令添加到您Dockerfile的图像中并重建(最后一层)图像:

docker-compose up --build

或者,如果您必须跳过构建缓存以强制进行新构建:

docker-compose build --no-cache
docker-compose up


以上是docker-compose:不同的运行、执行和层会发生什么的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>