ادامهی بحث در اینجا: «فعالسازی Windows Authentication در برنامههای ASP.NET Core 2.0»
نظرات مطالب
معرفی ASP.NET Identity
سلام
آیا در پروژههای windows application که از wcf استفاده میکنند هم میتوانیم از این سیستم استفاده کنیم.؟
آیا در پروژههای windows application که از wcf استفاده میکنند هم میتوانیم از این سیستم استفاده کنیم.؟
سلام ممنونم از مطلبتون جالب بود ! .چجور میشه این نمونه گزارش گیری رو در Windows Application استفاده کرد؟
راه حلی دیگر
cd c:\windows\system32\inetsrv
appcmd list wp
appcmd list wp
خیلی دوست داشتم یه همچین سیستمی رو روی Windows Form پیاده کنم که بشه با ویکیپدیا هم سازگارش کرد...
سلام برای اجرای Vitual Pc احتیاج به نصب Windows Xp Mode پیدا نکردید؟
تا اینجا نحوهی اجرای برنامهها را داخل کانتینرها بررسی کردیم؛ اما هنوز در مورد دادههای آنها بحث نکردهایم. اگر بانکهای اطلاعاتی را به درون کانتینرها منتقل کنیم، چه بر سر دادههای آنها میآید؟
بررسی روش اجرای MS SQL Server Express درون یک Container
اگر مخازن Imageهای رسمی مایکروسافت را در داکرهاب بررسی کنیم، به مخازنی مانند mssql-server-windows-express ، mssql-server و یا mssql-server-linux نیز خواهیم رسید. در اینجا آخرین نگارش Image مربوط به SQL Server Express آن، حدود 7GB حجم دارد. برای دریافت آن ابتدا به Windows Containers سوئیچ کنید و سپس دستور زیر را صادر نمائید:
پس از دریافت آن، اگر به مستندات رسمی آن در داکر هاب مراجعه کنیم، دستوری را به صورت زیر برای اجرای آن عنوان کردهاست:
در این دستور:
- سوئیچ d سبب میشود تا پس از اجرای این دستور، بلافاصله به command prompt بازگشت داده شویم و SQL Server Express در background اجرا شود.
- سپس پورت 1433 میزبان به پورت 1433 کانتینر، نگاشت شدهاست که پورت استاندارد SQL Server است.
- سوئیچ e، امکان تنظیم متغیرهای محیطی را میسر میکند؛ برای مثال ورود کلمهی عبور کاربر SA و یا پذیرش مجوز آن. برای نمونه، این کلمهی عبور را مساوی password وارد کنید؛ هرچند کار نخواهد کرد، اما بررسی خطاهای به همراه آن مفید است.
- و در آخر نام image مرتبط ذکر شدهاست.
پس از اجرای این دستور، کانتینر SQL Server Express، در پس زمینه شروع به کار خواهد کرد و بلافاصله به خط فرمان بازگشت داده میشویم. در اینجا ممکن است آغاز SQL Server اندکی طول بکشد. برای اینکه دریابیم در این لحظه وضعیت پروسهی آن به چه صورتی است، دستور docker logs id را صادر کنید. پس از آن خطایی مانند password validation failed را مشاهده خواهیم کرد. عنوان میکند که پیچیدگی کلمهی عبور وارد شده کافی نیست.
یک نکته: زمانیکه دستور docker run را اجرا میکنیم، یک هش طولانی را نمایش میدهد و پس از آن به خط فرمان بازگشت داده میشویم. این هش طولانی، همان id کانتینر در حال اجرا است. برای مثال در دستور docker logs id میتوان 3 حرف ابتدای این هش را بجای id وارد کرد. البته این id را توسط دستور docker ps نیز میتوان بدست آورد.
بنابراین با توجه به اینکه دستور docker logs id، خطایی را گزارش کردهاست، توسط دستور docker stop id، این کانتینر را متوقف کرده و آنرا مجددا با کلمهی عبوری مانند pass!w0rd1 اجرا میکنیم:
اینبار نیز مجددا دستور docker logs id را بر اساس id جدید این کانتینر اجرا میکنیم که پیام Started SQL Server را نمایش میدهد. بنابراین تا به اینجا موفق شدیم پروسهی SQL Server Express را بدون مشکلی آغاز کنیم.
همانطور که در قسمت سوم نیز عنوان شد، اگر این کانتینر را بر روی ویندوز سرور، در حالت Windows Containers اجرا کنیم (و نه در حالت Hyper-V)، پروسههای اجرای شدهی داخل یک Container را میتوان با Job Object Idهای یکسانی که دارند، در Task Manager ویندوز، در کنار سایر پروسههای سیستم، شناسایی کرد.
اتصال به SQL Server Express اجرا شدهی داخل یک Container توسط SQL Server Management Studio
پس از اجرای SQL Server Express دخل کانتینر، مطابق تنظیمات آن، چه در سیستم میزبان و چه در داخل کانتینر، به پورت 1433 گوش فرا داده میشود. به همین منظور نیاز است IP این کانتینر را نیز بدست آوریم. برای اینکار دستور ipconfig را در سیستم میزبان صادر کنید تا بر اساس مشخصات کارت شبکهی مجازی آن، بتوان IP آنرا بدست آورد (دستور docker inspect id نیز چنین اطلاعاتی را به همراه دارد). اکنون میتوان از داخل سیستم راه دور دیگری که SQL Server Management Studio بر روی آن نصب است، توسط این IP و پورت، به SQL Server Express متصل شد.
البته در اینجا نیازی به ذکر پورت نیست؛ چون پورت 1433، شماره پورت پیشفرض است. بعد از اتصال، میتوان کارهای متداولی مانند ایجاد یک بانک اطلاعاتی جدید را انجام داد.
برای آزمایش، یکبار دستور docker ps را صادر کنید تا id این کانتینر مشخص شود. سپس دستور docker stop id را صادر کنید تا پروسه SQL Server Express خاتمه یابد. اکنون اگر در SQL Server Management Studio قصد کار با آنرا داشته باشیم، پیام عدم اتصال مشاهده میشود. اکنون برای اجرای مجدد کانتینر، دستور docker start id را صادر کنید.
بررسی روش اجرای MySQL داخل یک Container
برای اجرای MySQL نیاز است به Linux Containers سوئیچ کنیم. حجم tag ویژهی latest آن نیز حدود 138MB است که نسبت به SQL Server Express هفت گیگابایتی، بسیار کمتر است!
در همان صفحهی مستندات آن در داکرهاب، دستور اجرایی آن نیز ذکر شدهاست:
در اینجا نیز توسط سوئیچ e که مخفف environment است، یکسری از متغیرهای محیطی MySQL، مانند کلمهی عبور آن قابل تنظیم هستند. همچنین سوئیچ d نیز برای اجرای آن در پس زمینه، ذکر شدهاست. همین دستور را به همین شکل، صرفا با حذف tag آن، جهت اشارهی به آخرین نگارش موجود این image، اجرا میکنیم:
با اجرای این دستور، در ابتدا MySQL از داکرهاب دریافت شده و سپس در پس زمینه اجرا خواهد شد. پیش از بازگشت به command prompt، یک هش طولانی نیز نمایش داده میشود که همان id کانتینر در حال اجرای آن است. برای اینکه بتوانیم ریز جزئیات رخ داده را بهتر مشاهده کنیم، میتوان از دستور docker logs id استفاده کرد.
یک نکته: میتوان یک command prompt جدید را باز کرد و سپس دستور docker logs -f id را در آن صادر کرد. به این صورت لاگهای لحظهای یک کانتینر را نیز میتوان مشاهده کرد (f در اینجا به معنای follow است).
اکنون میخواهیم MySQL Client موجود در همین Container در حال اجرا را، اجرا کنیم (اجرای پروسهای درون یک کانتینر در حال اجرا). برای اینکار از دستور docker exec استفاده میشود:
ابتدا توسط دستور docker ps مقدار id این کانتینر را بدست میآوریم و سپس در دستور بعدی، از آن استفاده خواهیم کرد.
در اینجا توسط دستور docker exec ابتدا یک interactive shell را درخواست کردهایم (اجرای foreground یک برنامهی شل). سپس id این کانتینر باید ذکر شود. پس از آن نام فایل اجرایی MySQL Client قید شده و در پایان، نام کاربری و کلمهی عبور اتصال به آن که در دستور docker run تنظیم شدهاند، ذکر میشوند.
با اجرای این دستور، به خط فرمان MySQL Client داخل این کانتینر دسترسی پیدا میکنیم. در اینجا میتوان دستورات مختلفی را برای کار با پروسهی mysql اجرا کرد؛ مانند اجرای دستور show databases که لیست بانکهای اطلاعاتی موجود را نمایش میدهد:
روش مدیریت دادههای بانکهای اطلاعاتی توسط Docker
در قسمت قبل دریافتیم که لایهی رویی یک container، دارای قابلیت read/write است و برای مثال میتوان فایلهای یک وب سایت استاتیک را در آنجا کپی و سپس هاست کرد. اما این لایه، لایهی مناسبی برای ذخیره سازی دادههای یک بانک اطلاعاتی نیست. در اینجا برای مدیریت بهتر این نوع دادهها، از مفهومی به نام volume استفاده میشود.
برای درک روش مدیریت دادهها توسط داکر، دستور docker volume ls را اجرا کنید. مشاهده خواهید کرد که docker یک volume پیشفرض را نیز ایجاد کردهاست. البته با volumes پیشتر در قسمت چهارم، در بخش «روش به اشتراک گذاری فایل سیستم میزبان با کانتینرها» نیز آشنا شدهایم. این volume پیشفرض، کار ذخیره سازی اطلاعات را حتی اگر کانتینری در حال اجرا نباشد نیز انجام میدهد. وجود یک چنین قابلیتی جهت از دست نرفتن اطلاعات ارزشمند ذخیره شدهی در بانکهای اطلاعاتی بسیار ضروری است.
البته لازم به ذکر است، این volume ای را که در اینجا مشاهده میکنید، توسط Dockerfile خود mysql به صورت خودکار ایجاد میشود. برای مثال در داکرهاب، در قسمت full description این image، در ابتدای توضیحات قسمتی است به نام supported tags and respective dockerfile links. در اینجا هر tag نامبرده شده، در حقیقت لینکی است به یک Dockerfile. اگر یکی از آنها را باز کنید، چنین سطری را در آن مشاهده خواهید کرد:
این دستور سبب میشود چنین مسیری (مسیر پیشفرض ثبت اطلاعات mysql) به صورت یک volume جدید، خارج از فایل سیستم کانتینر، بر روی سیستم میزبان، ایجاد شود. سپس این مسیر و volume جدید، توسط داکر به صورت خودکار به این کانتینر mount خواهد شد و برای این موارد نیازی نیست کار خاصی توسط ما انجام شود.
اینکار نه فقط برای بالابردن کارآیی اعمال read/write انجام شدهی توسط container انجام میشود، بلکه حتی اگر این کانتینر را توسط دستور docker rm id حذف کنیم، دستور docker volume ls، هنوز همان volume ای را که در حین نصب mysql به صورت خودکار ایجاد شده بود، نمایش میدهد. علت اینجا است که طول عمر این volume، وابستهی به طول عمر کانتینر آن نیست. به این ترتیب حذف تصادفی یک کانتینر، سبب از دست رفتن اطلاعات ارزشمند داخل بانک اطلاعاتی آن نمیشود.
روش تعیین صریح یک volume برای یک کانتینر بانک اطلاعاتی، توسط volumeهای نامدار
دستور docker run ای را که برای اجرای mysql صادر کردیم، یک volume خودکار را ایجاد کردهاست و اگر آنرا با دستور docker volume ls بررسی کنیم، دارای یک نام هش مانند است که به آن anonymous volume هم گفته میشود. در ادامه قصد داریم یک volume نامدار را ایجاد کنیم و سپس از آن جهت ذخیره سازی اطلاعات چندین وهله از کانتینر mysql استفاده نمائیم.
پیش از ادامه بحث، ابتدا توسط دستور docker rm id، کانتینر mysql ای را که پیشتر ایجاد کردیم حذف کنید؛ هرچند این دستور، volume متناظر با آنرا حذف نمیکند.
سپس برای اینکه یک کانتینر جدید mysql را با ذکر صریح volume آن ایجاد و اجرا کنیم، میتوان از دستور زیر استفاده کرد:
در اینجا از سوئیچ v برای ایجاد یک volume نامدار استفاده شدهاست و در آن بجای ذکر قسمت مسیر پوشهای در سمت میزبان، صرفا یک نام، مانند db، پیش از ذکر : قید شدهاست. پس از :، مسیری که این volume قرار است در آن کانتینر به آن نگاشت شود، ذکر شدهاست.
اکنون اگر دستور docker volume ls را صادر کنیم، در لیست خروجی آن، نام db قابل مشاهدهاست.
و تغییراتی را به صورت زیر اعمال میکنیم:
در اینجا بانک اطلاعاتی جدید pets ایجاد شدهاست.
اکنون در ابتدا این کانتینر را متوقف کرده و سپس آنرا حذف میکنیم:
هرچند اگر دستور حذف را با سوئیچ f- نیز اجرا کنیم (به معنای force)، کار stop را به صورت خودکار انجام میدهد.
در ادامه مجددا همان دستور قبلی را که توسط آن volume نامداری، ایجاد کردیم، اجرا میکنیم:
اینبار اگر دستور docker volume ls را مجددا صادر کنیم، مشاهده خواهیم کرد این کانتینر جدید، بجای ایجاد یک volume جدید، از همان volume موجود db که آنرا پیشتر ایجاد کردیم، استفاده میکند؛ هرچند کانتینری که آنرا ایجاد کردهاست، دیگر وجود خارجی ندارد. در این حالت اگر MySQL Client این کانتینر را اجرا نمائیم:
و سپس دستور نمایش بانکهای اطلاعاتی آنرا صادر کنیم:
در خروجی آن هنوز بانک اطلاعاتی pets که پیشتر ایجاد شده بود، قابل مشاهدهاست. بنابراین حذف و یا ایجاد کانتینرها، تاثیری را بر روی volumeهای ایجاد شده، نخواهند داشت.
روش حذف volumes اضافی
با توجه به اینکه volumeها، طول عمر متفاوتی را نسبت به کانتینرها دارند، ممکن است پس از مدتی فضای دیسک سخت شما را پر کنند. برای مثال به ازای هربار اجرای دستور docker run مربوط با MYSQL با نامی متفاوت، یک volume جدید نیز ایجاد میشود.
خروجی دستور docker inspect id به همراه قسمتی است به نام mounts که خاصیت name آن، دقیقا مساوی نام volume متناظر با کانتینر بررسی شدهاست. همچنین خاصیت source آن، محل دقیق ذخیره سازی این volume را بر روی فایل سیستم میزبان مشخص میکند.
برای حذف آنها، ابتدا نیاز است کانتینرها را متوقف کرد. دستور زیر تمام کانتینرهای در حال اجرا را متوقف میکند. در اینجا دستور docker ps -q، لیست id تمام کانتینرهای در حال اجرا را باز میگرداند (در این دستورات، افزودن پارامتر q، سبب بازگشت صرفا idها میشود):
اگر میخواهید تمام کانتینرهای موجود را حذف کنید:
و یا دستور زیر ابتدا تمام کانتینرهای موجود را متوقف کرده و سپس آنها را حذف میکند:
دستور زیر تمام volumes موجود را حذف میکند:
دستور زیر یک کانتینر با id مشخص شده را به همراه volume نامگذاری نشدهی مرتبط با آن، متوقف و سپس حذف میکند:
دستور زیر، لیست تمام volumes غیراستفاده شدهی توسط کانتینرهای موجود را نمایش میدهد (به یک چنین volumeهای در اینجا dangling گفته میشود؛ volume ای که کانتینر آن حذف شدهاست):
که میتواند لیست مناسبی برای حذف باشند:
بررسی روش اجرای MS SQL Server Express درون یک Container
اگر مخازن Imageهای رسمی مایکروسافت را در داکرهاب بررسی کنیم، به مخازنی مانند mssql-server-windows-express ، mssql-server و یا mssql-server-linux نیز خواهیم رسید. در اینجا آخرین نگارش Image مربوط به SQL Server Express آن، حدود 7GB حجم دارد. برای دریافت آن ابتدا به Windows Containers سوئیچ کنید و سپس دستور زیر را صادر نمائید:
docker pull microsoft/mssql-server-windows-express
docker run -d -p 1433:1433 -e sa_password=<SA_PASSWORD> -e ACCEPT_EULA=Y microsoft/mssql-server-windows-express
- سوئیچ d سبب میشود تا پس از اجرای این دستور، بلافاصله به command prompt بازگشت داده شویم و SQL Server Express در background اجرا شود.
- سپس پورت 1433 میزبان به پورت 1433 کانتینر، نگاشت شدهاست که پورت استاندارد SQL Server است.
- سوئیچ e، امکان تنظیم متغیرهای محیطی را میسر میکند؛ برای مثال ورود کلمهی عبور کاربر SA و یا پذیرش مجوز آن. برای نمونه، این کلمهی عبور را مساوی password وارد کنید؛ هرچند کار نخواهد کرد، اما بررسی خطاهای به همراه آن مفید است.
- و در آخر نام image مرتبط ذکر شدهاست.
پس از اجرای این دستور، کانتینر SQL Server Express، در پس زمینه شروع به کار خواهد کرد و بلافاصله به خط فرمان بازگشت داده میشویم. در اینجا ممکن است آغاز SQL Server اندکی طول بکشد. برای اینکه دریابیم در این لحظه وضعیت پروسهی آن به چه صورتی است، دستور docker logs id را صادر کنید. پس از آن خطایی مانند password validation failed را مشاهده خواهیم کرد. عنوان میکند که پیچیدگی کلمهی عبور وارد شده کافی نیست.
یک نکته: زمانیکه دستور docker run را اجرا میکنیم، یک هش طولانی را نمایش میدهد و پس از آن به خط فرمان بازگشت داده میشویم. این هش طولانی، همان id کانتینر در حال اجرا است. برای مثال در دستور docker logs id میتوان 3 حرف ابتدای این هش را بجای id وارد کرد. البته این id را توسط دستور docker ps نیز میتوان بدست آورد.
بنابراین با توجه به اینکه دستور docker logs id، خطایی را گزارش کردهاست، توسط دستور docker stop id، این کانتینر را متوقف کرده و آنرا مجددا با کلمهی عبوری مانند pass!w0rd1 اجرا میکنیم:
docker run -d -p 1433:1433 -e sa_password=pass!w0rd1 -e ACCEPT_EULA=Y microsoft/mssql-server-windows-express
همانطور که در قسمت سوم نیز عنوان شد، اگر این کانتینر را بر روی ویندوز سرور، در حالت Windows Containers اجرا کنیم (و نه در حالت Hyper-V)، پروسههای اجرای شدهی داخل یک Container را میتوان با Job Object Idهای یکسانی که دارند، در Task Manager ویندوز، در کنار سایر پروسههای سیستم، شناسایی کرد.
اتصال به SQL Server Express اجرا شدهی داخل یک Container توسط SQL Server Management Studio
پس از اجرای SQL Server Express دخل کانتینر، مطابق تنظیمات آن، چه در سیستم میزبان و چه در داخل کانتینر، به پورت 1433 گوش فرا داده میشود. به همین منظور نیاز است IP این کانتینر را نیز بدست آوریم. برای اینکار دستور ipconfig را در سیستم میزبان صادر کنید تا بر اساس مشخصات کارت شبکهی مجازی آن، بتوان IP آنرا بدست آورد (دستور docker inspect id نیز چنین اطلاعاتی را به همراه دارد). اکنون میتوان از داخل سیستم راه دور دیگری که SQL Server Management Studio بر روی آن نصب است، توسط این IP و پورت، به SQL Server Express متصل شد.
البته در اینجا نیازی به ذکر پورت نیست؛ چون پورت 1433، شماره پورت پیشفرض است. بعد از اتصال، میتوان کارهای متداولی مانند ایجاد یک بانک اطلاعاتی جدید را انجام داد.
برای آزمایش، یکبار دستور docker ps را صادر کنید تا id این کانتینر مشخص شود. سپس دستور docker stop id را صادر کنید تا پروسه SQL Server Express خاتمه یابد. اکنون اگر در SQL Server Management Studio قصد کار با آنرا داشته باشیم، پیام عدم اتصال مشاهده میشود. اکنون برای اجرای مجدد کانتینر، دستور docker start id را صادر کنید.
بررسی روش اجرای MySQL داخل یک Container
برای اجرای MySQL نیاز است به Linux Containers سوئیچ کنیم. حجم tag ویژهی latest آن نیز حدود 138MB است که نسبت به SQL Server Express هفت گیگابایتی، بسیار کمتر است!
در همان صفحهی مستندات آن در داکرهاب، دستور اجرایی آن نیز ذکر شدهاست:
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql
یک نکته: میتوان یک command prompt جدید را باز کرد و سپس دستور docker logs -f id را در آن صادر کرد. به این صورت لاگهای لحظهای یک کانتینر را نیز میتوان مشاهده کرد (f در اینجا به معنای follow است).
اکنون میخواهیم MySQL Client موجود در همین Container در حال اجرا را، اجرا کنیم (اجرای پروسهای درون یک کانتینر در حال اجرا). برای اینکار از دستور docker exec استفاده میشود:
docker ps docker exec -it id mysql --user=root --password=my-secret-pw
در اینجا توسط دستور docker exec ابتدا یک interactive shell را درخواست کردهایم (اجرای foreground یک برنامهی شل). سپس id این کانتینر باید ذکر شود. پس از آن نام فایل اجرایی MySQL Client قید شده و در پایان، نام کاربری و کلمهی عبور اتصال به آن که در دستور docker run تنظیم شدهاند، ذکر میشوند.
با اجرای این دستور، به خط فرمان MySQL Client داخل این کانتینر دسترسی پیدا میکنیم. در اینجا میتوان دستورات مختلفی را برای کار با پروسهی mysql اجرا کرد؛ مانند اجرای دستور show databases که لیست بانکهای اطلاعاتی موجود را نمایش میدهد:
mysql> show databases; use mysql; show tables; select * from user; exit;
روش مدیریت دادههای بانکهای اطلاعاتی توسط Docker
در قسمت قبل دریافتیم که لایهی رویی یک container، دارای قابلیت read/write است و برای مثال میتوان فایلهای یک وب سایت استاتیک را در آنجا کپی و سپس هاست کرد. اما این لایه، لایهی مناسبی برای ذخیره سازی دادههای یک بانک اطلاعاتی نیست. در اینجا برای مدیریت بهتر این نوع دادهها، از مفهومی به نام volume استفاده میشود.
برای درک روش مدیریت دادهها توسط داکر، دستور docker volume ls را اجرا کنید. مشاهده خواهید کرد که docker یک volume پیشفرض را نیز ایجاد کردهاست. البته با volumes پیشتر در قسمت چهارم، در بخش «روش به اشتراک گذاری فایل سیستم میزبان با کانتینرها» نیز آشنا شدهایم. این volume پیشفرض، کار ذخیره سازی اطلاعات را حتی اگر کانتینری در حال اجرا نباشد نیز انجام میدهد. وجود یک چنین قابلیتی جهت از دست نرفتن اطلاعات ارزشمند ذخیره شدهی در بانکهای اطلاعاتی بسیار ضروری است.
البته لازم به ذکر است، این volume ای را که در اینجا مشاهده میکنید، توسط Dockerfile خود mysql به صورت خودکار ایجاد میشود. برای مثال در داکرهاب، در قسمت full description این image، در ابتدای توضیحات قسمتی است به نام supported tags and respective dockerfile links. در اینجا هر tag نامبرده شده، در حقیقت لینکی است به یک Dockerfile. اگر یکی از آنها را باز کنید، چنین سطری را در آن مشاهده خواهید کرد:
VOLUME /var/lib/mysql
اینکار نه فقط برای بالابردن کارآیی اعمال read/write انجام شدهی توسط container انجام میشود، بلکه حتی اگر این کانتینر را توسط دستور docker rm id حذف کنیم، دستور docker volume ls، هنوز همان volume ای را که در حین نصب mysql به صورت خودکار ایجاد شده بود، نمایش میدهد. علت اینجا است که طول عمر این volume، وابستهی به طول عمر کانتینر آن نیست. به این ترتیب حذف تصادفی یک کانتینر، سبب از دست رفتن اطلاعات ارزشمند داخل بانک اطلاعاتی آن نمیشود.
روش تعیین صریح یک volume برای یک کانتینر بانک اطلاعاتی، توسط volumeهای نامدار
دستور docker run ای را که برای اجرای mysql صادر کردیم، یک volume خودکار را ایجاد کردهاست و اگر آنرا با دستور docker volume ls بررسی کنیم، دارای یک نام هش مانند است که به آن anonymous volume هم گفته میشود. در ادامه قصد داریم یک volume نامدار را ایجاد کنیم و سپس از آن جهت ذخیره سازی اطلاعات چندین وهله از کانتینر mysql استفاده نمائیم.
پیش از ادامه بحث، ابتدا توسط دستور docker rm id، کانتینر mysql ای را که پیشتر ایجاد کردیم حذف کنید؛ هرچند این دستور، volume متناظر با آنرا حذف نمیکند.
سپس برای اینکه یک کانتینر جدید mysql را با ذکر صریح volume آن ایجاد و اجرا کنیم، میتوان از دستور زیر استفاده کرد:
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d -v db:/var/lib/mysql mysql
اکنون اگر دستور docker volume ls را صادر کنیم، در لیست خروجی آن، نام db قابل مشاهدهاست.
در ادامه پروسهی MySQL Client داخل این کانتینر را اجرا کرده:
docker exec -it some-mysql mysql --user=root --password=my-secret-pw
mysql> show databases; create database pets; show databases; exit;
اکنون در ابتدا این کانتینر را متوقف کرده و سپس آنرا حذف میکنیم:
docker ps docker stop id docker rm id
در ادامه مجددا همان دستور قبلی را که توسط آن volume نامداری، ایجاد کردیم، اجرا میکنیم:
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d -v db:/var/lib/mysql mysql
docker exec -it some-mysql mysql --user=root --password=my-secret-pw
mysql> show databases;
روش حذف volumes اضافی
با توجه به اینکه volumeها، طول عمر متفاوتی را نسبت به کانتینرها دارند، ممکن است پس از مدتی فضای دیسک سخت شما را پر کنند. برای مثال به ازای هربار اجرای دستور docker run مربوط با MYSQL با نامی متفاوت، یک volume جدید نیز ایجاد میشود.
خروجی دستور docker inspect id به همراه قسمتی است به نام mounts که خاصیت name آن، دقیقا مساوی نام volume متناظر با کانتینر بررسی شدهاست. همچنین خاصیت source آن، محل دقیق ذخیره سازی این volume را بر روی فایل سیستم میزبان مشخص میکند.
برای حذف آنها، ابتدا نیاز است کانتینرها را متوقف کرد. دستور زیر تمام کانتینرهای در حال اجرا را متوقف میکند. در اینجا دستور docker ps -q، لیست id تمام کانتینرهای در حال اجرا را باز میگرداند (در این دستورات، افزودن پارامتر q، سبب بازگشت صرفا idها میشود):
docker stop $(docker ps -q)
docker rm $(docker ps -aq)
docker rm -f $(docker ps -aq)
docker volume rm $(docker volume ls -q)
docker rm -fv id
docker volume ls -f dangling=true
docker volume rm $(docker volume ls -qf dangling=true)
به همراه بسته Features pack اس کیوال سرور 2012، دو بسته SqlDom.msi نیز وجود دارند (نسخههای X86 و X64). این بسته حاوی اسمبلی Microsoft.SqlServer.TransactSql.ScriptDom.dll میباشد که نهایتا در آدرس Program Files\Microsoft SQL Server\110\SDK\Assemblies کپی خواهد شد.
به کمک آن میتوان عبارات پیچیده T-SQL را Parse و آنالیز کرد. البته باید در نظر داشت هرچند این بسته جهت SQL Server 2012 ارائه شده اما این اسمبلی با نگارشهای 2005 به بعد اس کیوال سرور کاملا سازگار است و اساسا نیازی هم به SQL Server ندارد. در ادامه مروری خواهیم داشت بر نحوه استفاده از آن.
یافتن کوئریهای * Select در بین انبوهی از اسکریپتها به کمک SQLDom
در مورد مضرات کوئریهای * select پیشتر مطلبی را در این سایت خواندهاید. در ادامه قصد داریم به کمک امکانات اسمبلی Microsoft.SqlServer.TransactSql.ScriptDom.dll، تعدادی عبارت T-SQL را آنالیز کرده و مشخص کنیم که آیا حاوی * select هستند یا خیر. کد کامل آنرا در ذیل مشاهده میکنید:
توضیحات:
پس از نصب SQLDom.msi، ارجاعی را به اسمبلی زیر اضافه نمائید تا بتوانید کد فوق را کامپایل کنید:
Program Files\Microsoft SQL Server\110\SDK\Assemblies\Microsoft.SqlServer.TransactSql.ScriptDom.dll
کار با ایجاد وهلهای از TSql110Parser شروع میشود. متد Parse آن، آرگومانی از نوع TextReader را قبول میکند. برای مثال با استفاده از StringReader میتوان محتوای یک متغیر رشتهای را به آن ارسال کرد و یا توسط StreamReader یک فایل sql را.
پس از فراخوانی متد Parse، بهتر است بررسی شود که آیا عبارت T-SQL دریافتی معتبر بوده است یا خیر. اینکار را توسط لیستی از ParseErrorهای دریافتی میتوان انجام داد.
خروجی متد Parse، حاوی یک سری Batch آنالیز شده است. هر عبارت Go در اینجا یک Batch را تشکیل میدهد. سپس در داخل هر batch به دنبال batch.Statements خواهیم گشت تا بتوان به عبارات T-SQL آنها دسترسی یافت.
در ادامه کار اصلی توسط متد processStatement صورت میگیرد. عبارات دریافتی، در حالت کلی از نوع TSqlStatement هستند اما در اصل میتوانند یکی از مشتقات آن نیز باشند. در اینجا فقط دو مورد CreateProcedureStatement و SelectStatement بررسی شدهاند (مطابق رشته tSql ابتدای مثال). هر دو عبارت، از کلاس TSqlStatement مشتق شدهاند.
در متد processStatement عبارات select معمولی و همچنین آنهایی که داخل رویههای ذخیره شده تعریف شدهاند، استخراج شده و در نهایت بررسی میشوند که آیا از نوع SelectStarExpression هستند یا خیر (همان * select صورت مساله).
خروجی مثال فوق به شرح زیر است:
به کمک آن میتوان عبارات پیچیده T-SQL را Parse و آنالیز کرد. البته باید در نظر داشت هرچند این بسته جهت SQL Server 2012 ارائه شده اما این اسمبلی با نگارشهای 2005 به بعد اس کیوال سرور کاملا سازگار است و اساسا نیازی هم به SQL Server ندارد. در ادامه مروری خواهیم داشت بر نحوه استفاده از آن.
یافتن کوئریهای * Select در بین انبوهی از اسکریپتها به کمک SQLDom
در مورد مضرات کوئریهای * select پیشتر مطلبی را در این سایت خواندهاید. در ادامه قصد داریم به کمک امکانات اسمبلی Microsoft.SqlServer.TransactSql.ScriptDom.dll، تعدادی عبارت T-SQL را آنالیز کرده و مشخص کنیم که آیا حاوی * select هستند یا خیر. کد کامل آنرا در ذیل مشاهده میکنید:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using Microsoft.SqlServer.TransactSql.ScriptDom; namespace DbCop { // Microsoft® SQL Server® 2012 Transact-SQL ScriptDom // SQL Server 2012 managed parser, Supports SQL Server 2005+ // SQLDom.msi (redist x86/x64) // http://www.microsoft.com/en-us/download/details.aspx?id=29065 // X86: http://go.microsoft.com/fwlink/?LinkID=239634&clcid=0x409 // X64: http://go.microsoft.com/fwlink/?LinkID=239635&clcid=0x409 // Program Files\Microsoft SQL Server\110\SDK\Assemblies\Microsoft.SqlServer.TransactSql.ScriptDom.dll class Program { static void Main() { const string tSql = @" -- select * in PROCEDURE CREATE PROCEDURE dbo.SelectStarTest AS SELECT * FROM dbo.tbl1 go -- select * in PROCEDURE with TableVar Create PRocedure SelectAll AS Declare @X table(Id integer) Select * from @x go -- select * in PROCEDURE with ctex CREATE PROCEDURE dbo.SelectAllCte AS WITH ctex AS ( SELECT * FROM sys.objects ) SELECT * FROM ctex go -- normal select * select * from tbl1; select * from dbo.tbl2; "; IList<ParseError> errors; TSqlScript sqlFragment; using (var reader = new StringReader(tSql)) { var parser = new TSql110Parser(initialQuotedIdentifiers: true); sqlFragment = (TSqlScript)parser.Parse(reader, out errors); } if (errors != null && errors.Any()) { var sb = new StringBuilder(); foreach (var error in errors) sb.AppendLine(error.Message); throw new InvalidOperationException(sb.ToString()); } var i = 0; foreach (var batch in sqlFragment.Batches) { Console.WriteLine("Batch: {0}, Statement(s): {1}", ++i, batch.Statements.Count); foreach (var statement in batch.Statements) { processStatement(statement); } Console.WriteLine(); } Console.WriteLine("\nPress a key..."); Console.Read(); } private static void processStatement(TSqlStatement statement) { var createProcedureStatement = statement as CreateProcedureStatement; if (createProcedureStatement != null) { var statementList = createProcedureStatement.StatementList; foreach (var procedureStatement in statementList.Statements) { processStatement(procedureStatement); } } var selectStatement = statement as SelectStatement; if (selectStatement != null) { var query = selectStatement.QueryExpression; var selectElements = ((QuerySpecification)query).SelectElements; foreach (var selectElement in selectElements) { var expression = selectElement as SelectStarExpression; if (expression == null) continue; Console.WriteLine( "`Select *` detected @StartOffset:{0}, Line:{1}, T-SQL: {2}", expression.StartOffset, expression.StartLine, statementToString(selectStatement)); } } } private static string statementToString(TSqlFragment selectStatement) { var text = new StringBuilder(); for (var i = selectStatement.FirstTokenIndex; i <= selectStatement.LastTokenIndex; i++) { text.Append(selectStatement.ScriptTokenStream[i].Text); } return text.ToString(); } } }
توضیحات:
پس از نصب SQLDom.msi، ارجاعی را به اسمبلی زیر اضافه نمائید تا بتوانید کد فوق را کامپایل کنید:
Program Files\Microsoft SQL Server\110\SDK\Assemblies\Microsoft.SqlServer.TransactSql.ScriptDom.dll
کار با ایجاد وهلهای از TSql110Parser شروع میشود. متد Parse آن، آرگومانی از نوع TextReader را قبول میکند. برای مثال با استفاده از StringReader میتوان محتوای یک متغیر رشتهای را به آن ارسال کرد و یا توسط StreamReader یک فایل sql را.
پس از فراخوانی متد Parse، بهتر است بررسی شود که آیا عبارت T-SQL دریافتی معتبر بوده است یا خیر. اینکار را توسط لیستی از ParseErrorهای دریافتی میتوان انجام داد.
خروجی متد Parse، حاوی یک سری Batch آنالیز شده است. هر عبارت Go در اینجا یک Batch را تشکیل میدهد. سپس در داخل هر batch به دنبال batch.Statements خواهیم گشت تا بتوان به عبارات T-SQL آنها دسترسی یافت.
در ادامه کار اصلی توسط متد processStatement صورت میگیرد. عبارات دریافتی، در حالت کلی از نوع TSqlStatement هستند اما در اصل میتوانند یکی از مشتقات آن نیز باشند. در اینجا فقط دو مورد CreateProcedureStatement و SelectStatement بررسی شدهاند (مطابق رشته tSql ابتدای مثال). هر دو عبارت، از کلاس TSqlStatement مشتق شدهاند.
در متد processStatement عبارات select معمولی و همچنین آنهایی که داخل رویههای ذخیره شده تعریف شدهاند، استخراج شده و در نهایت بررسی میشوند که آیا از نوع SelectStarExpression هستند یا خیر (همان * select صورت مساله).
خروجی مثال فوق به شرح زیر است:
Batch: 1, Statement(s): 1 `Select *` detected @StartOffset:140, Line:5, T-SQL: SELECT * FROM dbo.tbl1 Batch: 2, Statement(s): 1 `Select *` detected @StartOffset:368, Line:12, T-SQL: Select * from @x Batch: 3, Statement(s): 1 `Select *` detected @StartOffset:659, Line:22, T-SQL: WITH ctex AS ( SELECT * FROM sys.objects ) SELECT * FROM ctex Batch: 4, Statement(s): 2 `Select *` detected @StartOffset:753, Line:26, T-SQL: select * from tbl1; `Select *` detected @StartOffset:791, Line:27, T-SQL: select * from dbo.tbl2;
اشتراکها