Docker Compose service volume not reflecting my host machine changes to the running container

Viewed 769

I am not a really experienced user on Docker, and I am faced with a weird issue I cannot solve.

What I try to do, is to run three services using a docker-compose.yml. The three services are a MySQL Server, a PHP-FPM and an nGinx server.

So far, I have achieve to run the services, and I can do all the operation I want, like running the migration files inside the container, add fixtures data in the database, etc.

The only problem I have using the following configuration is that the changes I do on my host machine files, it is not reflected in the running containers.

If I stop the docker-compose, and restart it, then I can see my host machine changes, but I cannot see the changes while the containers are running.

In the following files, do you see any errors in my configuration? I have searched a lot, but unfortunately, I cannot find any solution.

My docker-compose.yml file looks like that:

version: "3.9"

services:
    mysql:
        image: mysql:8.0
        volumes:
            - ./docker/mysql/init:/docker-entrypoint-initdb.d
            - .data:/var/lib/mysql
        environment:
            MYSQL_ROOT_PASSWORD: root
            MYSQL_DATABASE: api

    php:
        build:
            context: .
        env_file:
            - .env
        ports:
            - "9000:9000"
        volumes:
            - ./:/srv/api

    web:
        image: nginx:latest
        ports:
            - "8080:80"
        volumes:
            - ./:/srv/api
            - ./docker/nginx/site.conf:/etc/nginx/conf.d/default.conf

For the PHP the Dockerfile is the following:

# the different stages of this Dockerfile are meant to be built into separate images
# https://docs.docker.com/develop/develop-images/multistage-build/#stop-at-a-specific-build-stage
# https://docs.docker.com/compose/compose-file/#target


# https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact
ARG PHP_VERSION=8.0.9

# "php" stage
FROM php:${PHP_VERSION}-fpm-alpine AS api_platform_php

# persistent / runtime deps
RUN apk add --no-cache \
        acl \
        fcgi \
        file \
        gettext \
        git \
        gnu-libiconv \
    ;

# install gnu-libiconv and set LD_PRELOAD env to make iconv work fully on Alpine image.
# see https://github.com/docker-library/php/issues/240#issuecomment-763112749
ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so

ARG APCU_VERSION=5.1.19
RUN set -eux; \
    apk add --no-cache --virtual .build-deps \
        $PHPIZE_DEPS \
        icu-dev \
        libzip-dev \
        mysql-dev \
        zlib-dev \
    ; \
    \
    docker-php-ext-configure zip; \
    docker-php-ext-install pdo pdo_mysql; \
    docker-php-ext-install -j$(nproc) \
        intl \
        zip \
    ; \
    pecl install \
        apcu-${APCU_VERSION} \
    ; \
    pecl clear-cache; \
    docker-php-ext-enable \
        apcu \
        opcache \
    ; \
    \
    runDeps="$( \
        scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \
            | tr ',' '\n' \
            | sort -u \
            | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
    )"; \
    apk add --no-cache --virtual .api-phpexts-rundeps $runDeps; \
    \
    apk del .build-deps

###> recipes ###
###< recipes ###

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

RUN ln -s $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini
COPY docker/php/conf.d/api-platform.prod.ini $PHP_INI_DIR/conf.d/api-platform.ini

VOLUME /var/run/php

# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser
ENV COMPOSER_ALLOW_SUPERUSER=1
ENV PATH="${PATH}:/root/.composer/vendor/bin"

WORKDIR /srv/api

# build for production
ARG APP_ENV=prod

# prevent the reinstallation of vendors at every changes in the source code
COPY composer.json composer.lock symfony.lock ./
RUN set -eux; \
    composer install --prefer-dist --no-dev --no-scripts --no-progress; \
    composer clear-cache

# copy only specifically what we need
COPY .env ./
ADD bin bin/
COPY config config/
COPY migrations migrations/
COPY public public/
COPY src src/
COPY templates templates/
COPY ./ ./


COPY docker/php/docker-healthcheck.sh /usr/local/bin/docker-healthcheck
RUN chmod +x /usr/local/bin/docker-healthcheck

HEALTHCHECK --interval=10s --timeout=3s --retries=3 CMD ["docker-healthcheck"]

COPY docker/php/docker-entrypoint.sh /usr/local/bin/docker-entrypoint
RUN chmod +x /usr/local/bin/docker-entrypoint

ENV SYMFONY_PHPUNIT_VERSION=9

CMD ["php-fpm"]

WORKDIR /srv/api

EXPOSE 9000

and finally my local file system is like that:

/bin
/config
/docker
    /mysql
        /init
            init-script.sql
    /nginx
        site.conf
    /php
        /conf.d
            api-platform.dev.ini
            api-platform.prod.ini
        /php-fpm.d
            zz-docker.conf
        docker-entrypoint.sh
        docker-healthcheck.sh
/migrations
/public
    /bundles
    [...]
    index.php
    [...]
/src
    /Controller
    /DataFixtures
    /Entity
    /EventSubscriber
    /Exception
    /OpenApi
    /Repository
    /Security
    /Serializer
    /Validation
    Kernel.php
/templates
/tests
/var
/vendor
.env
[...]
docker-compose.yml
Dockerfile
[...]
2 Answers

It should have nothing to do with your Dockerfile.

Perhaps for some reason your mounts default to :delegated mode.

Try adding :consistent to your volume specification, as in:

- ./docker/nginx/site.conf:/etc/nginx/conf.d/default.conf:consistent

From the docs:

  • consistent: perfect consistency (host and container have an identical view of the mount at all times)
  • cached: the host’s view is authoritative (permit delays before updates on the host appear in the container)
  • delegated: the container’s view is authoritative (permit delays before updates on the container appear in the host)

EDIT: Check out this (long) thread: https://github.com/docker/for-win/issues/5530 (it has started as a Windows issue, but Ubuntu users report the same issue in the thread).

It has a lot of things in common with your issue, including PHP and more than one container using the same host folder as a volume. It seems a bug related to very frequent file updates and the caching system. For some, adding :consistent worked, for some not. The bug report is now closed - it seems fixed, even tough I do not see a very obvious explanation at the end. I do recommend to make sure your Docker / docker-compose deployment is up to date.

I had similar issues on my Mac - and this turned out to be related to the option in Docker Desktop which was enabled to "Use gRPC FUSE for file sharing". Once I disabled this option I was able to add and edit files on the host and see the updates reflected in the container without having to stop and start the containers.

Docker Preferences

Related