پشتیبانگیری از کانتینر و volume داکر MySQL

یک اسکریپت نوشتم که هر روز از volume کانتینر MySQL پشتیبان بگیره و ذخیره کنه و برای تست هم خود کانتینر با volume اش رو پاک کردم و و دوباره بک آپ رو برگردوندم و تمامی جدول ها و داده های توی اون هم برگشت.

کامند پشتیبان گیری:

و با کامندهای زیر هم پشتیبان رو به روی کانتینر جدید برگردوندم:

لازمه که بدونیم که خود کانتینر با compose زیر ساخته شده و دو تا volume داره:

فایل Compose برای MySQL

میخایم یه کانتینر از MySQL بسازیم به صورتی که فایلهای دیتابیس شامل کانفیگ هاش توی یک volume ذخیره بشه.

برای این کار باید فایل compose به صورت زیر باشه:

مقایسه docker volume و bind mount

توی داکر به سه شکل میتونیم فایل ها رو با خود هاست داکر به اشتراک بزاریم. اگر یک کانتینر از بین بره طبیعتا تمامی داده های توی اون هم از بین میره و این خطرناکه.

داکر یک مکانیزم داره به اسم volume که اینها رو خود داکر مدیریت میکنه و اگر کانتینر خاموش بشه یا از بین بره میشه یه کانتینر دیگه بالا آورد که از اون استفاده کنه. البته بهتره قبل از پاک کردن کانتینر فعلی یکی دیگه بسازیم.

توی داکر میشه بجای volume از bind mount هم استفاده کرد. bind mount ساده است مثل اینکه یک فولدر رو بین کانتینر و هاست فعلی به اشتراک بزاریم.

حالت بعدی استفاده از tmpfs هست که فقط در صورتی که هاست لینوکس باشه قابل استفاده است. و این دیتا توی حافظه memory ذخیره میشه بنابراین دائمی نیست.

شمای کلی قابلیت های داکر در این زمینه توی عکس زیر معلومه:

پشتیبانگیری از docker containers

یکی از چالش هایی که برخوردیم پشتیبان گیری از سرویس هایی بود که روی داکر هستن. چند تا اپلیکیشن و یک دیتابیس داریم که هر کدوم توی یک container هستن. طبیعتا اگر container پاک بشه تمامی اون داده ها هم از بین می روند. برای اینکه این اتفاق نیوفته باید پشتیبان بگیریم.

data volume توی برای نگهداری دیتا خارج از فایل سیستم کانتینر هست. داکر هیچ وقت این data volume ها رو پاک نمیکنه مگر اینکه خودمون volume های مربوط به یک کانتینر رو باهاش پاک کنیم.

docker rm -v

اگر همه کانتینرهایی که با یک volume کار میکنن رو پاک کنیم، پاک کردن و دسترسی به اون volume سخت میشه. به این volume ها میگن dangling volume. برای اینکه dangling volume وجود نداشته باشه بهتره همیشه یک کانتینر مرتبط با اون volume بسازیم.

برای اینکه بک آپ کاملی داشته باشیم باید از موارد زیر پشتیبان بگیریم:

  • image های داکر
    • از کانتینرهای داکر
    • از volume های موجود

    نصب gitlab روی داکر

    میخایم gitlab رو روی داکر بالا بیاریم. برای این کار از docker compose استفاده میکنیم. فایل compose.yml زیر رو مینویسیم:

    این یه کانتینر از gitlab-ce میسازه که پورتهاش رو به هم مپ میکنه.

    environment variable ای که استفاده شده GITLAB_HOME رو لازمه با دستور زیر تعریف کنیم

    یا کار بهتر اینه که فایل custom.sh رو توی /etc/profile.d/ میسازیم و اون اکسپورت رو توش میزاریم.

    قسمت environment توی فایل کامپوز برای متغیرهای توی خود کانتینر هست و ربطی به سرور اصلی نداره.

    آخر هم دستور زیر کانتینر رو میسازه.

    دستورات اولیه نصب Odoo

    دستورات تست شده برای نصب Odoo رو توی این پست میارم:

    Coroutine و Awaitables

    Coroutine در واقع یک تابع هست که میتونیم اونو pause کنیم. فرض کنیم دو تا تابع داریم و میخایم کنترل اجرا بین این دو تا جابجا بشه مثل ping pong مثلا تابع اول چند خط رو اجرا کنه بعد کنترل رو به تابع دوم بده و اون چند خط اجرا کنه و … در واقع دو تا routine که اینجا بهشون میگیم تابع با هم cooperate کنن.

    برای تریفش توی پایتون از async کلیدواژه استفاده میکنیم. که اون وقت اون تابع coroutine میشه. میتونیم هر جای کد coroutine ازش بخایم وایسه تا اجرای یه تابع دیگه تموم شه برای این کار await میکنیم.

    مقایسه Celery و Channels و Singnal

    در جدول زیر مقایسه Celery و Django Channels و Django Signals رو میبینیم

    Here’s a comparison of Django Channels, Django Signals, and Celery, presented in a tabular format, focusing on their use cases, features, and suitable scenarios:

    Feature/AspectDjango ChannelsDjango SignalsCelery
    Primary Use CaseReal-time communication, WebSockets, and long-lived connectionsDecoupled event handling within Django applicationsAsynchronous task queue/job queue for running background tasks
    CommunicationWebSockets, HTTP2, server-sent eventsIn-process communication within the same Django appDistributed communication, allowing task distribution across multiple workers
    ConcurrencyHandles concurrent connections and async processingSynchronous, works within the Django request-response cycleHandles concurrent tasks, designed for parallel processing
    ScalabilityScalable for handling many concurrent connectionsLimited by the Django processHighly scalable, can distribute tasks across multiple servers
    Real-time UpdatesYes, supports real-time updatesNoNo, tasks are run asynchronously but not in real-time
    Event HandlingHandles real-time eventsHandles events within the Django lifecycle (e.g., model save, user login)Handles events as background tasks
    Persistent ConnectionsYes, supports long-lived connections (e.g., chat apps)No, operates within the request-response cycleNo, designed for discrete, short-lived tasks
    IntegrationIntegrates with WebSockets, WebRTC, etc.Integrates with Django ORM and lifecycle hooksIntegrates with message brokers (RabbitMQ, Redis, etc.)
    Typical Use CasesChat applications, live notifications, live dashboardsSending signals on model changes, user actionsSending emails, processing data, generating reports, scheduled tasks
    ExampleLive chat app with instant messagingLogging changes to models when savedSending periodic email reports, processing user-uploaded files in the background
    Fault ToleranceBasic fault tolerance, relies on infrastructureBasic, depends on Django’s fault toleranceHigh fault tolerance, can retry failed tasks, distributed task execution
    DependenciesRedis, RabbitMQ (for channel layers)None beyond DjangoMessage broker (e.g., RabbitMQ, Redis), result backend (optional)
    Ease of UseRequires understanding of asynchronous programmingSimple to use with DjangoRequires setup of a message broker and understanding of task queues

    Detailed Use Case Examples

    1. Django Channels:
      • Chat Application: Users can send and receive messages in real-time, with updates being pushed to all connected clients instantly.
      • Live Notifications: Real-time notifications for events such as new comments, likes, or mentions in a social media application.
      • Live Dashboard: Real-time updates of metrics and analytics in a monitoring dashboard.
    2. Django Signals:
      • Model Change Notifications: Automatically trigger a function to log changes or send an email when a model instance is saved or deleted.
      • User Activity Tracking: Capture user login, logout, or profile update events to maintain an activity log.
      • Post-Processing: Perform additional actions after saving a model, such as updating related records or sending a confirmation email.
    3. Celery:
      • Email Sending: Send emails asynchronously to avoid blocking the main thread during the request-response cycle.
      • Data Processing: Handle large data processing tasks, such as generating reports or processing user-uploaded files, in the background.
      • Scheduled Tasks: Run periodic tasks like clearing expired sessions, generating nightly reports, or updating external APIs.

    By comparing these tools, you can choose the most appropriate solution based on the specific requirements and characteristics of your project.

    database_sync_to_async و async_to_sync

    کاربرد این دوتابع در django channels هست. به طور کلی وقتی توی یه consumer که به صورت Asynchronous تعریف شده بخایم از یک تابع Synchronous استفاده کنیم باید اون رو به Asynchronous تبدیل کنیم و برعکس و کاربرد این دو تابع همینه.

    میدونیم که ORM جنگو Synchronous هست بنابراین وقتی توی یه کانسومر Asynchronous ازش استفاده میکنیم باید اونو توی database_sync_to_async بزاریمو

    میدونیم که Channel Layer ها ذاتا Asynchronous هستند و همه متدهای اون مثل self.send group_send و group_add همگی Async هستند بنابراین اگر بخایم توی یه کلاس sync ازشون استفاده کنیم باید از async_to_syn استفاده بشه.

    لازم به ذکر است که channels.db.database_sync_to_async یک wrapper از asgiref.sync.sync_to_async هست که بعد از کانکشن دیتابیس رو هم clean میکنه

    برای استفاده از اون بهتره اول خود query رو توی یه تابع بنویسیم بعد اون تابع رو بدیم به این تابع مثل:

    یا

    Channel Layers توی Django Channels چیه؟

    توی Django Channels هر instance توی یک پروسه اجرا میشه. اگر بخایم پیامی بین پروسه های مختلف برنامه یعنی به instance های مختلف ارسال بشه باید از مکانیسم Channels layer استفاده کنیم. یعنی اگر بخایم پیامی به شخصی دیگه ارسال بشه یا به گروه خاصی ارسال بشه باید از این مکانیسم استفاده کرد.

    یعنی اگر بخایم بخش های مختلف برنامه یا consumer های مختلف با هم صحبت کنن باید از Layers استفاده کنیم.