Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用docker compose构建多阶段DockerFile时,如何保留所有工件?_Docker_Docker Compose_Dockerfile - Fatal编程技术网

使用docker compose构建多阶段DockerFile时,如何保留所有工件?

使用docker compose构建多阶段DockerFile时,如何保留所有工件?,docker,docker-compose,dockerfile,Docker,Docker Compose,Dockerfile,我正在做一个使用多阶段Dockerfile的项目。这对CircleCI很有效,但我对Docker不是很有经验,所以我在本地运行时遇到了问题。从文件中: 第二个FROM指令使用 阿尔卑斯山:以最新图片为基础。复制--from=0行仅复制 从上一个阶段到这个新阶段的构建工件。前进 SDK和任何中间构件都会被留下,而不会保存在中 最后的图像 如果我理解正确,这意味着如果我在第1阶段安装了一组依赖项,在第2阶段安装了另一组依赖项,那么在运行docker compose up之后,我将只看到安装的一些依赖

我正在做一个使用多阶段Dockerfile的项目。这对CircleCI很有效,但我对Docker不是很有经验,所以我在本地运行时遇到了问题。从文件中:

第二个FROM指令使用 阿尔卑斯山:以最新图片为基础。复制--from=0行仅复制 从上一个阶段到这个新阶段的构建工件。前进 SDK和任何中间构件都会被留下,而不会保存在中 最后的图像

如果我理解正确,这意味着如果我在第1阶段安装了一组依赖项,在第2阶段安装了另一组依赖项,那么在运行
docker compose up
之后,我将只看到安装的一些依赖项。这就是当地正在发生的事情。但是,为了连接到容器并运行开发服务器,我需要安装所有项目依赖项。我在这里读到,可以将
--rm=false
参数用于build命令(我不确定这是指
docker build
docker compose build
,还是有任何区别)。我试图在docker compose中添加一个
rm
设置,但显然它不存在

version: "3.8"
services:
    app:
        container_name: my.container
        build:
            context: .
            dockerfile: Dockerfile.dev
            rm: false
        entrypoint: sh -c
        command: tail -f /dev/null
        stdin_open: true
        tty: true
    app2:
        ...
我的Dockerfile大致如下所示:

ARG PYTHON_VERSION=3.8-alpine3.12

FROM python:$PYTHON_VERSION AS base
ARG USER=myuser

# Install application run-time dependencies.
RUN addgroup -S ${USER} && \
    adduser -S -g ${USER} ${USER} && \
    apk add --no-cache \
            --upgrade \
        bash && \
    rm -rf /var/cache/apk/*

FROM base AS builder

RUN mkdir /install
RUN mkdir /e2e_install
WORKDIR /install

# Install application build-time dependencies.
RUN apk update && \
    apk add --no-cache --upgrade \
    bash \
    build-base \
    libffi-dev \
    pcre-dev \
    linux-headers \
    zlib-dev \
    python3-dev \
    openssh \
    openssh-keygen \
    git \
    gcc \
    musl-dev && \
    rm -rf /var/cache/apk/*

# Install project and test dependencies.
RUN pip install --no-cache-dir --disable-pip-version-check pip==20.0.2

COPY requirements.txt /tmp/requirements.txt
RUN pip install --no-cache-dir \
    --no-warn-script-location \
    --prefix=/install \
    --disable-pip-version-check -r /tmp/requirements.txt

COPY test_requirements.txt /tmp/test_requirements.txt
RUN pip install --no-cache-dir \
    --ignore-installed \
    --no-warn-script-location \
    --prefix=/install \
    --disable-pip-version-check -r /tmp/test_requirements.txt

# install e2e-test dependencies
COPY e2e/requirements.txt /tmp/e2e_test_requirements.txt
RUN cat /tmp/e2e_test_requirements.txt
RUN pip install --no-cache-dir \
                --ignore-installed \
                --disable-pip-version-check \
                --no-warn-script-location \
                --prefix=/e2e_install \
                -r /tmp/e2e_test_requirements.txt

# Tag version number into source code.
ARG VERSION_NUMBER=unversioned
WORKDIR /source
COPY . .
RUN sed -i -e "s/__version__ = \"unversioned\"/__version__ = \"${VERSION_NUMBER}\"/" external_api/__init__.py

# -------------------- e2e Image --------------------
FROM base as e2e-test
ARG USER=myuser

COPY --from=builder /e2e_install /usr/local

WORKDIR /opt/company/myapp
COPY --from=builder /source/e2e ./e2e
COPY --from=builder /source/scripts/entry_point.sh .

# Set file owner group,
RUN chown -R ${USER}:${USER} /opt/company
ENTRYPOINT ["./entry_point.sh"]

# -------------------- Production Image --------------------
FROM base
ARG USER=myuser

# Copy necessary files from builder.
WORKDIR /opt/company
COPY --from=builder /install /usr/local
COPY --from=builder /source .

# Set file owner group,
RUN chown -R ${USER}:${USER} /opt/company

# Run unit tests.
RUN PYTHONPATH=. pytest tests/unit_test --cov=. --cov-report=xml

COPY ./scripts/entry_point.sh .
ENTRYPOINT ["./entry_point.sh"]
当我运行
docker compose build
时,我会得到一系列的结果:

Step 20/26 : ARG VERSION_NUMBER=unversioned
 ---> Running in 1ce3e682b483
Removing intermediate container 1ce3e682b483
 ---> dcc4d4b6b4b5
Step 21/26 : WORKDIR /source
 ---> Running in c8d9c1349305
Removing intermediate container c8d9c1349305

当我连接到容器并尝试运行Django development server时,它无法工作,因为依赖项未安装(即使
docker compose build
输出显示它们已安装)。我想这是因为“中间容器”正在被移除。我曾尝试将多阶段Dockerfile转换为单阶段Dockerfile,但我仍然不断收到“删除中间容器”消息,并且依赖项并未全部安装。我必须在一条运行指令中安装所有依赖项吗?这是我进入容器时安装所有依赖项的唯一方法吗?难道我没有办法保持这个Dockerfile的完整性,并告诉docker compose在使用它进行构建时停止“留下中间工件”吗?我是否正确使用了“工件”这个词?我找不到一个清晰的解释,我也不确定我是否完全理解“docker工件”是什么。

在我看来,您需要单独的docker compose服务,每个图像一个。您说其中涉及4个独立的Python项目,所以听起来您的docker-compose.yaml中应该(至少)定义4个服务

因此,与在一个Dockerfile中定义所有服务不同,我希望每个服务都有自己的Dockerfile,并在您的
docker compose.yaml
中分别定义

version: "3.7"

services:

  e2e:
    - build ./e2e
    ...
  production:
    - build ./production
    ...

你说你所有的服务都必须互相沟通。Docker Compose使这变得非常简单,例如,
生产
映像可以使用URI
e2e
访问
e2e
映像。(例如,
curl e2e
)。

您可以使用普通的Python虚拟环境进行日常开发吗?我正在从事的项目使用微服务体系结构。涉及到4个独立的Python项目,它们都必须相互通信,其中2个有自己的数据库,其他依赖项如redis、rabbitmq。不可能在本地安装所有这些东西。您应该能够将
--no rm
应用于
docker compose build
命令本身。你是正确的,在撰写文件中似乎没有这样做的方法。我认为你有2个选择。我不确定哪一个更好,我也没有试过。首先,确定哪个中间容器包含所需的依赖项,并且Python脚本不会被
COPY---from
命令移动。编辑撰写文件以按ID引用中间容器映像。其次,将多阶段DockerFile合并到一个阶段中。正如您所写的,多阶段的目的通常是清除运行时不需要的构建-开发依赖关系,因此这种方法可以让您恢复一切。第二种方法可能是更好的选择。它还提供了两种我认为有用的图像。开发人员的开发映像包括所有内容,运行时的最终用户映像不包括。对不起,我用一个服务共享了docker compose的最低版本,但事实上我有很多服务,每个Python应用程序(+postgres、redit等)都有一个,而且它们都有自己的Dockerfile。问题是这些DockerFile都是多阶段的,当我在构建之后进入容器时,依赖项就不存在了。