Docker-compose Veri Kaybı

Merhaba ‘docker-compose’ ile bir proje yapıyorum. projeyi herhangi bir sebeple kapatıp açtığımda veriler kayboluyor. Sebebi ne olabilir?

docker-compose restart deyince de down & up deyince de veri kayboluyor.

docker-compose dosyası:

version: '3.7'

services:
  backend:
    build: ./backend
    container_name: backend
    command: python manage.py runserver 0.0.0.0:8000
    restart: 'no'
    volumes:
      - ./backend/:/usr/src/app/
    ports:
      - 8000:8000
    env_file:
      - ./.env.dev
    depends_on:
      - db
  frontend:
    build: ./frontend
    container_name: frontend
    command: npm run serve
    restart: 'no'
    ports:
      - 8080:8080
    env_file:
      - ./.env.dev
    depends_on:
      - backend
  db:
    image: postgres:13.0-alpine
    container_name: database
    restart: 'no'
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    env_file:
      - ./.env.dev
      
volumes:
  postgres_data:

backend Dockerfile

# pull official base image
FROM python:3.8-alpine

# set work directory
WORKDIR /usr/src/app

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# install psycopg2 dependencies
RUN apk update \
    && apk add icu-data-full\
    && apk add --no-cache curl gpg gnupg\
    && apk add --no-cache postgresql-dev gcc libc-dev g++ libffi-dev libxml2 python3-dev musl-dev unixodbc unixodbc-dev mariadb-dev

# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt

# copy project
COPY . .

# mssql dependicies
RUN apk add --allow-untrusted msodbcsql17_17.10.1.1-1_amd64.apk \
    && apk add --allow-untrusted mssql-tools_17.10.1.1-1_amd64.apk

# run entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]

entrypoint.sh dosyasında projeyi başlatırken veri eklemesi için kod yazmıştım.

#!/bin/sh

if [ "$DATABASE" = "postgres" ]
then
    echo "Waiting for postgres..."

    while ! nc -z $SQL_HOST $SQL_PORT; do
      sleep 0.1
    done

    echo "PostgreSQL started"
fi

python manage.py flush --no-input
python manage.py makemigrations
python manage.py migrate
python manage.py createcachetable

# create superuser
if [ "$DJANGO_SUPERUSER_USERNAME" ]
then
    python manage.py createsuperuser \
        --noinput \
        --username $DJANGO_SUPERUSER_USERNAME  \
        --email $DJANGO_SUPERUSER_EMAIL
fi

# create user
python manage.py add_user

# create object samples
python manage.py add_external_data_samples
python manage.py add_tableau_samples

exec "$@"

terminalden proje açıkken ya da kapalıyken baktığımda volume görünüyor. bunu tamamen silip denediğimde de sorun aynı şekilde devam etti.

/project$ sudo docker volume ls
DRIVER    VOLUME NAME
local     project_postgres_data

sanırım volume tanımlarken özellikle datayı tutan volume’ün key’i container ismiyle aynı olmalı. postgres_data yerine db yazarak deneyebilir misin?

volumes:
  - db:/var/lib/postgresql/data/

EDIT: üstte yazdığımla alakası yokmuş
postgres_data:/var/lib/postgresql/data/ kısmı / ile bittiğinden bu hatayı veriyor olabilir.

1 Beğeni

Veri kaybindan kasit nedir? Hangi veri, ne sekilde kayboluyor?

DB sunucularini virtualization arkasinda calistirmak cok mantikli degil, cunku normal isleyen programlardan farkli olarak dusuk seviyeli hafiza ve dosya sistemi islemleri yapmak isteyebiliyorlar.

Mesela kullandigin volume driver’i Postgres’in fsync/fdatasync cagrilarini kaale aliyor mu?

Her halukarda, DB’yi container icinde calistiracaksan bu konu hakkinda ekstra okuman lazim.

Bana sorun baska bir sey gibi geliyor ama veri kaybi ne demek bilmeden tahmin yurutmek zor.

Bu arada proje calistirilabiliyor ise calistirmayi deneyecegim.

Bildiğimden değil de şuradaki örneğe bakarak yapmıştım. kontrol ettim. benimle aynı şekilde isim kullanmış.
testdriven.io

silip denedim. sonuç değişmedi.

django da oluşturduğum modellere admin paneli üzerinden bir iki örnek ekliyorum. daha sonra kapatıp açtığımda bütün modeller silinmiş oluyor.
Ayrıca entrypoint.sh dosyasında eğer superuser yoksa oluştur gibi bir kod var. kapatıp tekrar başlattığımda bunun da yeniden çalıştığını görüyorum. yani superuser da silinmiş oluyor.
Diğer bir deyişle volume hiçbir işe yaramıyor. Bütün veriler kayboluyor.

fsync/fdatasync nasıl kontrol edeceğimi bilmiyorum. Dediğiniz gibi okuyayım.

Database’de neler oluyor peki?

Yani ayni incelemeyi database katmaninda yapmaniz lazim.

konteynere terminallden bağlanıp baktım. kayıtlar gerçekleşiyor görünüyor. (<> özel isim)

$ sudo docker exec -it <container_name> psql -U <user_name> -d <database_name>

bağlanıp tabloyu kontrol ettim.

_dev=# SELECT * FROM tableau_plaintable;
id |  title  | is_private | is_case_sensitive | created_by_id | init_source_id 
----+---------+------------+-------------------+---------------+----------------
 2 | No name | f          | f                 |             2 |              2
 3 | hede    | t          | f                 |             2 |              1
(2 rows)

Konteyneri kapatıp açtığımda bu veriler gidiyor.


konteyner açıkken şu şekilde volume e bağlanıp baktığımda veritabanının bağlı olduğuna ilişkin bir şey göremedim…

$ sudo docker run -it --rm -v project_postgres_data:/volume_data alpine sh
/ # ls /volume_data
/ # 
$ sudo docker volume inspect project_postgres_data
[
    {
        "CreatedAt": "2023-06-22T15:12:07+03:00",
        "Driver": "local",
        "Labels": {
            "com.docker.compose.project": "project",
            "com.docker.compose.version": "1.25.0",
            "com.docker.compose.volume": "postgres_data"
        },
        "Mountpoint": "/var/lib/docker/volumes/project_postgres_data/_data",
        "Name": "project_postgres_data",
        "Options": null,
        "Scope": "local"
    }
]
$ sudo ls -a /var/lib/docker/volumes/project_postgres_data/
.  ..  _data
$ sudo ls -a /var/lib/docker/volumes/project_postgres_data/_data
.  ..

$ docker-compose up

[…]
database | 2023-06-23 07:00:55.865 UTC [1] LOG: starting PostgreSQL 13.0 on x86_64-pc-linux-usl, compiled by gcc (Alpine 9.3.0) 9.3.0, 64-bit
[…]

$ docker exec -it database psql -U postgres -a postgres -c "CREATE TABLE foo(id INT)"

CREATE TABLE foo(id INT)
CREATE TABLE

$ docker-compose down && docker-compose up

[…]
Removing database … done
[…]
database | 2023-06-23 07:05:24.312 UTC [21] LOG: database system was shut down at 2023-06-23 07:05:12 UTC
database | 2023-06-23 07:05:24.316 UTC [1] LOG: database system is ready to accept connections
[…]

$ docker exec -it database psql -U postgres -a postgres -c "\dt"

dt
        List of relations
 Schema | Name | Type  |  Owner   
--------+------+-------+----------
 public | foo  | table | postgres
(1 row)

$ sudo ls /var/lib/docker/volumes/fyp_postgres_data/_data

base/    pg_commit_ts/  pg_hba.conf    pg_logical/    pg_notify/    pg_serial/     pg_stat/      pg_subtrans/  pg_twophase/  pg_wal/   postgresql.auto.conf  postmaster.opts
global/  pg_dynshmem/   pg_ident.conf  pg_multixact/  pg_replslot/  pg_snapshots/  pg_stat_tmp/  pg_tblspc/    PG_VERSION    pg_xact/  postgresql.conf

$ docker run -it --rm -v fyp_postgres_data:/volume_data alpine sh
/ # ls /volume_data/

PG_VERSION            pg_commit_ts          pg_ident.conf         pg_notify             pg_snapshots          pg_subtrans           pg_wal                postgresql.conf
base                  pg_dynshmem           pg_logical            pg_replslot           pg_stat               pg_tblspc             pg_xact               postmaster.opts
global                pg_hba.conf           pg_multixact          pg_serial             pg_stat_tmp           pg_twophase           postgresql.auto.conf
1 Beğeni

Yani dedigin problemi duplike edemedim.

Farklarim: frontend projesi yok; tamamen sildim. backend projesi entrypoint.sh ve “django” iceren requirements’tan ibaret. .env.dev’de sadece POSTGRES_PASSWORD=foobar var.

En olasi sey postgres’in /var/lib/postgresql yerine baska bir yeri kullanmaya konfigure edilmis olmasi. .env.dev’de ne var? Veya daha dusuk ihtimalle: manage.py DB’ye ne yapiyor?

Her iki adimda bir container’larin imajlarini silmeyi hatirliyor musun? Ben unuttum. backend/ ile backend container’inin icleri cok farkli olabilir. (“Ne alaka” dersen haklisin ama docker kurcalarken akilda bulundurmakta fayda var.)

1 Beğeni

Yaptıklarınızın aynısını yaptım. hemen aynı görüntüleri aldım.
sudo docker exec -i database psql -U <user> -a <database_name> -c "CREATE TABLE foo(id INT)"
database_name: .env.dev de belirttiğim tablo adı.

Bu ifadeyi göremedim.


bu da tek başına değil tabi. pek çok table var.


Bu iki komut aynı şekilde listeleme yapıyor. herkisinde de fazladan bir öğe daha var:
sudo ls /var/lib/docker/volumes/project_postgres_data/_data
/ # ls /volume_data/

 postmaster.pid

Bir kaç kere veri ekleyip down/up yaptım. Benim eklediğim veriler yine kayboluyor. Ama public | foo | table | postgres bu table silinmiyor. admin panelinden eklediğim veriler siliniyor.


.env.dev
111 yazanlar birbiriyle aynı değer; 222 yazanlar birbiriyle aynı. (çok mühim gizli bilgi olduğu için kamuya açmıyorum. :p)

# settingsfile keys
DEBUG=1
SECRET_KEY=
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1] localhost:8080
CORS_ALLOWED_HOSTS=http://localhost:8000 http://127.0.0.1:8000 http://localhost:8080 http://127.0.0.1:8080 

# Database info 
SQL_ENGINE=django.db.backends.postgresql
SQL_DATABASE=111
SQL_USER=222
SQL_PASSWORD=333
SQL_HOST=db
SQL_PORT=5432
DATABASE=postgres

# postgre info
POSTGRES_USER=222
POSTGRES_PASSWORD=333
POSTGRES_DB=111

#default super user info
DJANGO_SUPERUSER_PASSWORD=
DJANGO_SUPERUSER_USERNAME=
DJANGO_SUPERUSER_EMAIL=

#default non moderator user info
DJANGO_USER_PASSWORD=
DJANGO_USER_USERNAME=
DJANGO_USER_EMAIL=

# Vue
VUE_APP_BASE_URL=http://localhost:8000
APP_TITLE=

setttings.py

DATABASES = {
    "default": {
        "ENGINE": os.environ.get("SQL_ENGINE", "django.db.backends.sqlite3"),
        "NAME": os.environ.get("SQL_DATABASE", BASE_DIR / "db.sqlite3"),
        "USER": os.environ.get("SQL_USER", "user"),
        "PASSWORD": os.environ.get("SQL_PASSWORD", "password"),
        "HOST": os.environ.get("SQL_HOST", "localhost"),
        "PORT": os.environ.get("SQL_PORT", "5432"),
    }
}

print edip baktım defaultlara gitmiyor. tüm değerleri .env.dev den alıyor.


Nihayetinde bu cevabı yazarken sorunun entrypoint.sh de olabileceğini düşünüp baktığımda fark ettim ki:

python manage.py flush --no-input

:scream: :scream_cat:


Harcadığınız bütün emek için çok teşekür ederim. Her ne kadar sorun ‘epic fail’ olsa da epeyce şey öğrendim.

:laughing:

Bazen pragmatik(/aptal) sorular sormak ise yariyor :slight_smile:

Rica ederim, ben de biraz daha Docker kurcalamis oldum