How to mount a directory created during docker image build?

Viewed 682

My docker-compose file is as follows:

version: "3"

services:
  db:
    image: postgres
    environment:
      POSTGRES_PASSWORD: qwerty
      POSTGRES_USER: qwerty
    volumes:
      - /data/db:/var/lib/postgresql/data

  backend:
    build:
      context: .
      dockerfile: dockerfile_backend
    image: backend:dev1.0.0
    entrypoint: ["sh", "-c"]
    command: python manage.py runserver
    ports:
      - "4000:4000"

In my dockerfile_backend i have a git clone statement which clones the project from a git repo. There is a folder called configs which comes as a part of git clone. I need to mount this folder as volume(similar to postgres volume mount point). Mounting of configs is necessary because during runtime the content of the folder gets modified or updated,these changes should not be lost.

How can i mount the folder that image build creates ?

I have tried adding a volumes as follows under the backend service :

    volumes:
      - /data/configs:/git_folder/configs

Here the problem is mount point(/data/configs) is empty initially so the image folder(/git_folder/configs) also gets empty.

1 Answers

How can i mount the folder that image build creates?

The most straightforward way is to avoid this path altogether: run the git clone command from the host. Copying data out of a built image isn't that easy, and if an important part of the build process is getting content on to the host, you can't do everything from the Dockerfile.

If the data you're dealing with is actually configuration data (as the name implies), checking in (a copy of) the files to a repository with the docker-compose.yml file is a reasonable approach. Frequently you'll include these files in the application repository itself, if you control that repository too. Then you can bind-mount the directory as normal:

backend:
  build: .
  ports:
    - "4000:4000"
  volumes:
    - ./configs:/git_folder/configs

If it's application data, you can store it in a named volume. You won't be able to directly access it from the host. Docker will populate the volume with content from the image, but only the first time you run the container: if you change the image, the volume will remain unchanged.

version: '3'
volumes:
  configs:
services:
  backend:
    build: .
    ports:
      - "4000:4000"
    volumes:
      - configs:/git_folder/configs

A third approach is to have your container's startup detect if the data directory is empty, and if so, populate it. You mention the postgres image as an example, and that's what this image does (running PostgreSQL's initdb command if a known file doesn't exist). You could write a script like:

#!/bin/sh
# Create the `configs` directory if it's empty
if [ -f /git_folder/configs/some_file ]; then
  cp -a /git_folder/configs_base/* /git_folder/configs
fi
# Run the main container command
exec "$@"

In your Dockerfile, make this script be the ENTRYPOINT. You must invoke it using JSON-array syntax. Do not override entrypoint: in the docker-compose.yml (and especially not to something that changes the ordinary shell-command meaning of command:).

COPY entrypoint.sh /git_folder
RUN chmod +x /git_folder/entrypoint.sh
ENTRYPOINT ["/git_folder/entrypoint.sh"]
CMD python manage.py runserver
Related