Docker-compose + dockerfile: host volume empty inside container

tl;dr I want to be able to mount a populated host directory inside the container. The Dockerfile fails to build, but with docker-compose shell I can verify that the directory is mounted and the file exists.

Docker Version: Docker version 20.10.6, build 370c289
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION=“Ubuntu 20.04.2 LTS”

This is a pretty simple scenario to reproduce.

Directory structure:

+ /project/
  + Dockerfile.custom
  + docker-compose.yml
  +- my-custom-data/
    +- test.txt

Dockerfile.custom:

FROM alpine

EXPOSE 443 80 5432 5434

VOLUME ["/app/my-custom-data"]
WORKDIR /app/my-custom-data

RUN apk add --no-cache --verbose git curl gcc python3-dev libc-dev openssl-dev musl-dev jpeg-dev zlib-dev libffi-dev cairo-dev pango-dev gdk-pixbuf-dev python3 py3-pip

RUN python3 -m pip install --upgrade pip

RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3 -
RUN source /root/.poetry/env
ENV PATH=$PATH:/root/.poetry/bin

RUN ls -l /app/my-custom-data/

docker-compose.yml:

version: "3.7"
services:
    db:
        image: postgres
        restart: always
        ports: 
            - "5432:5434"
        environment:
            - POSTGRES_USER=postgres
            - POSTGRES_PASSWORD=coolserver
            - POSTGRES_DB=cooldb
    server:
        image: alpine
        build:
            context: .
            dockerfile: ./Dockerfile.custom
        volumes:
            - ./my-custom-data:/app/my-custom-data
        environment: 
            - "DATABASE_URL=postgres://postgres:coolserver@db:5434/cooldb"
        depends_on:
            - db
        # command: tail -F anything

Expectation

I expect that I’ll see ‘test.txt’ printed out after the container was built.

Reality

The directory is apparently empty, based on what Dockerfile reports

However, when I uncomment the “command” line (in order to keep the container open) and run “docker-compose exec server ls” I see that test.txt is present.

I have a feeling this has to do with the runtime heirarchy between Dockerfile and docker-compose. Is that right?

I assume you expect that docker mounts the hosts path into the container? This is not what it does. The VOLUME instruction marks this container folder as target for a volume. If a container is created using this imag and no actualy volume is mapped into that folder, an anoymous volume will be created and used.
See: Dockerfile reference | Docker Docs

Isn’t this exactly what happens? It is mounted thru container runtime, which you test verifyed. Though, it is not mounted through build time. You might want to check https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/syntax.md on how to use mounts during build time. I have no idea whether a counterpart for docker-compose exists.