首页 > 解决方案 > 容器没有代码更改,图像有

问题描述

是的,这个问题之前已经发布过。是的,我已经应用了相关的解决方案并忽略了不相关的解决方案。我只是不明白这里发生了什么。

问题:我通过修改默认返回消息来更改我的源代码。我将 src 树复制到我的 baseImage 中(多阶段构建)。我从 baseImage 构建了一个 stagingImage。baseImage 有代码更改,但运行 stagingImage 的容器返回代码更改前消息。我已经在 MacOs (Catalina) 和 Amazon Linux 2 上复制了这种行为。

请注意,我是手动执行此操作的,即我不依赖 IDE 和 inotfy-s 等。唯一涉及的工具是 CLI、vim、make 和 docker(-compose)。

详细信息:我有一个能够进行多阶段构建的 Dockerfile。这是 baseImage 构建的相关部分:

COPY ./composer.json /var/www/html/composer.json
COPY ./php-apache/auth.json  /root/.composer
COPY ./ /var/www/html

这是我如何构建其他图像的示例:

FROM php:7.4-apache AS cleanImage
COPY --from=baseImage / /

FROM cleanImage AS stagingImage
COPY ./.env.staging /var/www/html/.env
RUN /bin/bash -c 'rm -rf /var/lib/apt/lists/*'
# Set entrypoint
CMD ["-D", "FOREGROUND"]
ENTRYPOINT ["apachectl"]

我修改了“Docker In Action”第 10 章中的 Makefile。这是一个示例:

## image-base   : Build the base image that the others are based on
.PHONY: image-base
image-base: metadata
  @echo "Building Base Image"
  docker image build --no-cache --force-rm --tag src:$(BUILD_ID)-base \
  -f src/Dockerfile \
  --target baseImage \
  --build-arg BUILD_ID='$(BUILD_ID)' \
  --build-arg BUILD_DATE='$(BUILD_TIME_RFC_3339)' \
  --build-arg VCS_REF='$(VCS_REF)' \
  ./src
  @echo "Built Base Image. BUILD_ID: $(BUILD_ID)"

## image-staging    : Build the staging image
.PHONY: image-staging
image-staging: metadata image-base
  @echo "Building Staging App Image"
  docker image build -t src:$(BUILD_ID)-staging \
  -f src/Dockerfile \
  --target=stagingImage \
  --build-arg BUILD_ID='$(BUILD_ID)' \
  --build-arg BUILD_DATE='$(BUILD_TIME_RFC_3339)' \
  --build-arg VCS_REF='$(VCS_REF)' \
  ./src
  @echo "Built Staging App Image. BUILD_ID: $(BUILD_ID)-staging"

## up env=<env>   : Bring up environments. env values are prod, local, staging.
.PHONY: up
up:
ifeq ($(strip $(BUILD_ID)),)
    $(error BUILD_ID environment variable is not set. Run `make metadata` to generate one)
endif
  docker-compose -f docker-compose.yml -f docker-$(env).yml up -d

其中 BUILD_ID 的格式为 YYYYMMDD-epoch-git_SHA。请注意,baseImage 使用 --no-cache 标志。

到目前为止,一切都很好(我认为)。

我的 docker-compose.yml 文件如下所示:

version: '3.7'

volumes:
  web_app:

services:
  php-apache:
    logging:
      driver: "json-file"
      options:
        max-file: "5"
        max-size: "10m"
    volumes:
      - web_app:/var/www/html
    env_file:
      - ./src/.env.prod

我的docker-staging.yml文件如下所示:

version: '3.7'
services:
  php-apache:
    image: 'src:20200924-174443-3f16358-staging'
    container_name: perfboard-staging
    ports:
      - 8888:80
      - 9261:443
    env_file:
      - ./src/.env.staging

是的,为了调试,我已经硬编码了 stagingImage 的名称。

我希望看到的内容:当我点击 localhost:8888 时,我希望看到我修改后的消息。我不。

检查 baseImage 时,修改后的消息在那里。我无法直接检查 stagingImage,因为我不断收到 Apache 错误,大概是因为入口点。

如果我从系统中删除每个图像和容器,这将按预期运行。

删除上述特定的 baseIamge 和 stagingImage 并不能解决问题。

关于在哪里看的任何想法?

标签: dockerdocker-compose

解决方案


您的docker-compose.yml文件指定

volumes:
  - web_app:/var/www/html

这会导致web_app卷的内容被挂载到/var/www/html容器中的目录上,隐藏最初在映像中的任何内容。

您应该删除此卷声明。

只有在第一次运行容器时,Docker 才会将镜像的内容复制到一个空的命名卷中。从那时起,它将卷视为用户数据并且永远不会对其进行任何更改;即使基础映像已更新,卷内容也不会更新,并且当您运行容器时,卷优先于更新后的映像代码。

依赖于“从映像复制到卷”行为存在许多实际问题(它不适用于主机绑定挂载;它不适用于 Kubernetes;它会导致映像更新被忽略),我会非常努力地避免在您的应用程序代码上安装任何类型的卷。

如果您认为出于其他原因拥有该卷很重要,则需要使 Compose 删除它,以便重新创建它并再次具有“仅限第一次”行为。 docker-compose down -v将删除所有容器、网络和卷,但这也将包括您的数据库数据之类的内容。您可以使用docker-compose down(不带-v)停止容器,然后使用docker volume ls; docker volume rm dirname_web_app手动删除卷。


推荐阅读