Как сохранить sqlite3 db в папке проекта при использовании Docker

У меня есть небольшой проект, над которым работаю я и еще один человек. Приложение собирает некоторые данные и хранит их в sqlite db (расположенной в ./data/db.sqlite3 ), которые мы хотим сохранить и обмениваться ими через наше git-репо вместе со всем остальным кодом проекта.

Когда я пытаюсь докеризировать приложение, на каждой из наших машин данные сохраняются, но не в самой папке проекта.

Это docker-compose.yml:

version: "3.8"
services:
  gcs:
    build: .
    volumes:
      - type: bind
        source: ./data
        target: /data
    ports:
      - "8000:8000"

А вот и сам Dockerfile:

FROM python:3.8-slim-buster

WORKDIR /gcs
COPY requirements.txt requirements.txt
RUN apt-get update && apt-get install nginx vim binutils libproj-dev gdal-bin -y --no-install-recommends
RUN pip3 install -r requirements.txt

COPY . .

CMD python3 manage.py runserver 0.0.0.0:8000

Как-то я бы сказал, что вышеописанное монтирует папку 'data' в папке наших проектов в папку data в контейнере. Когда я использую docker inspect, чтобы посмотреть, что там находится - все выглядит нормально, исходная папка идеально соответствует расположению моей базы данных проекта:

        "Mounts": [
            {
                "Type": "bind",
                "Source": "/Users/rleblon/projects/gcsproject/data",
                "Destination": "/data",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }

Однако каким-то образом постоянные данные хранятся в другом месте, и никогда ./data/db.sqlite3 не обновляются на хост-машине.

После прочтения документации Docker и аналогичных вопросов я действительно немного потерялся. Я бы хотел понять, что здесь происходит. Насколько я понимаю, Docker просто создает обычный том в другом месте на моем компьютере и разделяет его между контейнерами, но какой смысл тогда указывать источник и цель, если исходный файл уже скопирован в сам контейнер?

Как заставить Docker использовать и изменять именно тот sqlite3 файл, который я хочу, вместо того, чтобы создавать том в другом месте и сохранять там копию?

Похоже, что вы оба копируете sqlite3 db в ваш образ - через строку в вашем Dockerfile

COPY . .

что, учитывая определенный вами рабочий каталог в Dockerfile

WORKDIR /gcs

и внешний вид вашей структуры каталогов, может скопировать db в

/gcs/data

а также монтирование той же sqlite3 db через ваш файл docker-compose в строке

    volumes:
      - type: bind
        source: ./data
        target: /data

to

/data

в вашем работающем контейнере этого образа.

Таким образом, у вас может быть две версии ваших данных, запущенных в контейнере этого образа: at

/gcs/data <-- скопировано на образ в Dockerfile

/data <-- смонтирован как том в docker-compose

Убедитесь, что вы не копируете версию db в образ через Dockerfile.

Если ваша служба gcs взаимодействует с версией вашей базы данных sqlite3, расположенной в /gcs/data, а не на смонтированном томе в /data, то любые изменения в базе данных не сохранятся после уничтожения контейнера.

С другой стороны, если ваше приложение указывает на смонтированную версию тома вашей базы данных на /data, то убедитесь, что разрешения, установленные на вашем хосте / образе, позволяют выполнять операции с базой данных, которые вы хотите.

Помните, что вы используете bind mount в вашем compose файле - это означает, что смонтированный каталог является общим для вашего хоста и запущенного контейнера. Это утверждение

As far as I understand Docker simply creates a regular volume elsewhere on my computer and shares that between containers

это верно для томов docker, но не для типа монтирования bind, который вы использовали. Смотрите, например, официальную документацию или этот хороший обобщающий пост , где хорошо описана разница между типами томов.

Похоже, что вы оба копируете sqlite3 db в ваш образ - через строку в вашем Dockerfile

COPY . .

что, учитывая определенный вами рабочий каталог в Dockerfile

WORKDIR /gcs

и внешний вид вашей структуры каталогов, может скопировать db в

/gcs/data

а также монтирование той же sqlite3 db через ваш файл docker-compose в строке

    volumes:
      - type: bind
        source: ./data
        target: /data

to

/data

в вашем работающем контейнере этого образа.

Таким образом, у вас может быть две версии ваших данных, запущенных в контейнере этого образа: at

/gcs/data <-- скопировано на образ в Dockerfile

/data <-- смонтирован как том в docker-compose

Убедитесь, что вы не копируете версию db в образ через Dockerfile.

Если ваша служба gcs взаимодействует с версией вашей базы данных sqlite3, расположенной в /gcs/data, а не на смонтированном томе в /data, то любые изменения в базе данных не сохранятся после уничтожения контейнера.

С другой стороны, если ваше приложение указывает на смонтированную версию тома вашей базы данных на /data, то убедитесь, что разрешения, установленные на вашем хосте / образе, позволяют выполнять операции с базой данных, которые вы хотите.

Помните, что вы используете bind mount в вашем compose файле - это означает, что смонтированный каталог является общим для вашего хоста и запущенного контейнера. Это утверждение

As far as I understand Docker simply creates a regular volume elsewhere on my computer and shares that between containers

это верно для томов docker, но не для типа монтирования bind, который вы использовали. Смотрите, например, официальную документацию или этот хороший обобщающий пост , где хорошо описана разница между типами томов.

Вернуться на верх