Как сохранить 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
, который вы использовали. Смотрите, например, официальную документацию или этот хороший обобщающий пост , где хорошо описана разница между типами томов.