Docker برای مبتدیان: ایجاد محیط توسعه Backend شما

من در حال حاضر در یک استارتآپ در مراحل اولیه کار میکنم که در آن به قدری روی جنبه تهاجمی چیزها، مانند توسعه ویژگیهای جدید تمرکز کردهایم، که از دفاع خود، یعنی آزمایش غفلت کردهایم.
به طور خاص، ما هنوز محیط توسعه خود را محدود نکردهایم، و به همان DB (RDS) در توسعهدهنده و محلی ارجاع میدهیم، که باعث ایجاد موانع قابلتوجهی برای توسعه تیم میشود – بله، این تا حدودی کمدی از خطاها است.
من که در درجه اول مسئول بخش مقدماتی و هوش مصنوعی بودم، با Docker آشنایی چندانی نداشتم. با این حال، متوجه شدم که برای جلوگیری از از هم پاشیدن توسعه تیم ما، معرفی Docker به محیط توسعه ما به یک ضرورت تبدیل شده است. در اینجا اهداف اصلی این تصمیم وجود دارد:
- کاهش بار روی RDS در محیط توسعه (عدم استفاده از RDS).
- حذف اثرات مهاجرت بین اعضای تیم (حل مشکل DB مشترک).
- تسریع در راه اندازی محیط توسعه (تسریع در روند ساخت و ساز).
- بهبود دردسر راه اندازی مجدد سرور به دلیل تایم اوت های بیکار.
من تصمیم گرفته ام که DB موجود خود را به یک DB کانتینری منتقل کنم و از docker-compose برای راه اندازی backend و DB استفاده کنم. من روش را در زیر شرح داده ام. بیایید داکر را در آغوش بگیریم و کمی هماهنگی را به روند توسعه تیم خود بازگردانیم!
1. ایجاد فایل های مرتبط با Docker
ما در حال مدیریت خدمات خود هستیم که شامل چندین فرانت اند (./frontend/
) و باطن (./backend/
)، در monorepo (فرانت اند React است، بک اند NestJS است).
در حالی که docker-compose به ما امکان میدهد این سرویسها را به طور جمعی راهاندازی کنیم، برخی از فرانتاندها در حال توسعه فعال نیستند، بنابراین در حال حاضر، ما تصمیم گرفتهایم تنها باطن و DB لازم را در کانتینرهای Docker راهاندازی کنیم.
ایجاد Dockerfile
ابتدا اجازه دهید Dockerfile را ایجاد کنیم (Dockerfile.dev
) برای باطن، به شرح زیر است.
FROM node:18.15.0
# Set timezone to Tokyo (JST)
ENV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
WORKDIR /app
# Copy package dependencies
COPY package*.json ./
# Ignore prepare script to avoid husky install errors
RUN yarn install --ignore-scripts
EXPOSE 8000
CMD ["yarn", "start:dev"]
منطقه زمانی روی JST تنظیم شده است زیرا DB موجود (RDS) در JST پیکربندی شده است. همچنین، ما مشکلی با شکست مرحله نصب هاسکی داشتیم، بنابراین آن را طوری تنظیم کردهایم که هنگام نصب وابستگیها با Yarn، اسکریپتها را نادیده بگیرد. --ignore-scripts
گزینه.
ایجاد docker-compose.yml
بعد، ما ایجاد می کنیم docker-compose.yml
به صورت زیر فایل کنید این فایل کانتینرهای backend و DB (MySQL) را مدیریت می کند.
version: "3.9"
services:
backend:
build:
context: ./backend
dockerfile: Dockerfile.dev
ports:
- "3010:3010" # Map local and container ports
depends_on:
- db # Wait for DB service to start
env_file: ./backend/.env # Specify environment variables
volumes:
- ./backend:/app # Map host and container directories
db:
image: mysql:8.0.28
platform: linux/x86_64
container_name: db
env_file: ./backend/.env # Specify environment variables
volumes:
- db-data:/var/lib/mysql # Persist data
ports:
- "3306:3306" # Map local and container ports
command: --default-authentication-plugin=mysql_native_password --sql_mode=NO_ENGINE_SUBSTITUTION
volumes:
db-data: # Define volume to persist DB data
با استفاده از Dockerfile.dev
و docker-compose.yml
ما به تازگی ایجاد کرده ایم، اکنون می توانیم باطن و DB را راه اندازی کنیم.
اگر به یک frontend نیاز دارید، می توانید یک Dockerfile در آن ایجاد کنید ./frontend/
مراحل مشابه را دنبال کنید و یک سرویس به آن اضافه کنید docker-compose.yml
برای تطبیق این.
یادداشت 1
در MySQL، بسته به پیکربندی DB، یک فیلد از نوع DATETIME بدون مقدار پیشفرض میتواند به طور خودکار روی آن تنظیم شود. 0000-00-00 00:00:00
. با این حال، این پیکربندی در کانتینر DB وجود نداشت و در نتیجه پس از راهاندازی کانتینر خطاهای INSERT ایجاد شد.
من پیکربندی MySQL را به صورت زیر تأیید کردم:
SHOW VARIABLES;
هنگام بررسی sql_mode
، تنظیمات مختلفی را بین DB ظرف و DB موجود (RDS) پیدا کردم. لذا اضافه کردم --sql_mode=NO_ENGINE_SUBSTITUTION
به db
command
.
# Container DB
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
# Existing DB (RDS)
NO_ENGINE_SUBSTITUTION
تبصره 2
پس از راهاندازی کانتینر، تغییرات در قسمت پشتیبان بارگیری مجدد نشدند. لذا اضافه کردم ./backend:/app
به حجم های باطن، نقشه برداری از فهرست هاست و کانتینر.
نکته 3
قبلاً اشاره کردم که ما در حال مدیریت یک سرویس مونورپو هستیم و فرانتاند را کانتینری نمیکنیم. با این حال، از آنجایی که این احتمال وجود دارد که frontend در آینده کانتینری شود، من آن را قرار دادم docker-compose.yml
در دایرکتوری ریشه برای بارگذاری ./backend/Dockerfile.dev
، این جمله را بیان کردم:
build:
context: ./backend
dockerfile: Dockerfile.dev
من آن را برای خواندن تنظیمات اتصال MySQL تنظیم کرده ام env_file: ./backend/.env
.
2. اضافه کردن متغیرهای محیطی
اطلاعات پیکربندی DB را به آن اضافه کنید ./backend/.env
به عنوان متغیرهای محیطی (هر مقدار).
MYSQL_ROOT_PASSWORD=
MYSQL_DATABASE=
MYSQL_USER=
MYSQL_PASSWORD=
مثال:
MYSQL_DATABASE=db_local
MYSQL_USER=admin
3. راه اندازی کانتینر
دستور زیر را در دایرکتوری ریشه اجرا کنید تا چندین کانتینر (بکاند، DB) راهاندازی شود.
$ docker-compose up
4. MySQL Workbench Setup
با استفاده از MySQL Workbench به MySQL DB در Docker متصل شوید.
- MySQL Workbench را باز کنید
- کلیک کنید بر روی [+] در لیست اتصالات MySQL در سمت چپ صفحه را فشار دهید.
- تنظیمات اتصال را به صورت زیر تنظیم کنید:
- نام اتصال: هر نام اتصال (مثال: db-local-docker)
- نام میزبان:
localhost
(یا آدرس IP میزبانی که Docker در آن اجرا می شود) - بندر:
3306
(شماره پورت تنظیم شده استdocker-compose.yml
) - نام کاربری: MYSQL_USER از
./backend/.env
- رمز عبور: MYSQL_PASSWORD از
./backend/.env
- کلیک [Test Connection] برای انجام تست اتصال اگر مشکلی وجود ندارد، کلیک کنید [OK] برای ذخیره اتصال
5. صادر کردن Dump از پایگاه داده موجود
Dump (اطلاعات و داده های جدول) را از RDS برای MySQL DB که در محیط توسعه دهنده استفاده می شود، صادر کنید.
شما از پورت ماشین محلی متصل خواهید شد (<local_port>
) از طریق سرور پرش (<ssh_user>@<remote_server_ip>
) به پورت RDS (<remote_database_port>
) (تونل SSH).
برای جلوگیری از تداخل پورت، مانند زمانی که MySQL از قبل روی ماشین محلی در حال اجرا است، از پورت های مختلف برای local_port
و remote_database_port
این بار.
$ ssh -f -N -L <local_port>:<remote_database_url>:<remote_database_port> -i <path_to_your_ssh_key> <ssh_user>@<remote_server_ip>
- local_port: پورتی که میخواهید در دستگاه محلی خود باز کنید (به عنوان مثال، 3307)
- remote_database_url: URL پایگاه داده راه دور (به عنوان مثال database.db.coedadadas22.ap-northeast-1.rds.amazonaws.com)
- remote_database_port: پورتی که توسط پایگاه داده راه دور استفاده می شود (به عنوان مثال، 3306)
- path_to_your_ssh_key: مسیری به کلید SSH شما (به عنوان مثال، ~/.ssh/db-pem-key.pem)
- ssh_user: نام کاربری مورد استفاده برای اتصال به سرور راه دور (به عنوان مثال، ec2-user)
- remote_server_ip: آدرس IP سرور راه دور (به عنوان مثال، 54.168.32.10)
به پورت وصل خواهید شد (<local_port>
) از لوکال هاست و نوشتن تمام نام جدول DB مربوطه (<database_name>
) در RDS به یک فایل متنی (<output_file>
).
$ mysql -h <localhost_ip> -P <local_port> -u <username> -p <database_name> -e 'show tables' | tail -n +2 > <output_file>
- localhost_ip: آدرس IP میزبانی که کلاینت MySQL در آن اجرا می شود (مثلاً 127.0.0.1)
- local_port: پورت دستگاه محلی شما برای دسترسی به پایگاه داده راه دور از طریق ارسال پورت SSH (به عنوان مثال، 3307)
- نام کاربری: نام کاربری مورد استفاده برای اتصال به پایگاه داده (مثلاً admin)
- database_name: نام پایگاه داده ای که به آن متصل می شوید (به عنوان مثال db-prod)
- output_file: نام فایل برای ذخیره نام جدول به دست آمده از پایگاه داده (به عنوان مثال، all_tables.txt)
پایگاه داده را بر اساس لیست جداولی که می خواهید صادر کنید، تخلیه کنید.
$ mysqldump -h <localhost_ip> -P <local_port> -u <username> -p <database_name> $(cat <tables_list_file>) > <output_file>
- localhost_ip: آدرس IP میزبان پایگاه داده (به عنوان مثال، 127.0.0.1)
- local_port: پورتی که پایگاه داده به آن گوش می دهد (مثلاً 3307)
- نام کاربری: نام کاربری برای اتصال به پایگاه داده (مثلاً مدیر)
- database_name: نام پایگاه داده برای ایجاد یک Dump از (مثلاً db-prod)
- tables_list_file: فایلی که حاوی لیست جداول برای ایجاد یک Dump از (مثلا all_tables.txt) است.
- output_file: نام فایل برای ذخیره خروجی (فایل dump) (به عنوان مثال database_export.sql)
6. وارد کردن Dump به پایگاه داده کانتینر
ما Dump را از MySQL Workbench به پایگاه داده کانتینر وارد می کنیم.
- MySQL Workbench را باز کنید.
- از صفحه اصلی روی اتصال پایگاه داده ای که می خواهید به آن متصل شوید کلیک کنید.
- هنگامی که اتصال پایگاه داده باز شد، “Server” -> “Data Import” را از نوار منو انتخاب کنید.
- هنگامی که صفحه “واردات داده” ظاهر می شود، “Import from Self-Contained File” را انتخاب کنید، سپس روی دکمه “…” در سمت راست کلیک کنید تا فایل SQL را که می خواهید وارد کنید انتخاب کنید.
- پایگاه داده مقصد را برای وارد کردن از منوی کشویی “Default Target Schema” انتخاب کنید.
- روی دکمه “شروع واردات” در بخش “پیشرفت واردات” کلیک کنید.