آموزش استفاده از Docker در توسعهی نرمافزار
۴ اسفند ۱۳۹۹
در این مقاله قصد داریم تا استفاده از Docker در توسعهی نرمافزار را به شما آموزش دهیم اما بهتر است بدانید چرا باید از Docker برای توسعهی نرمافزار استفاده کرد؟
چرا باید از Docker برای توسعهی نرمافزار استفاده کرد؟
دلایل بسیار زیادی برای استفاده از Docker وجود دارد اما برخی از آنها عبارتند از:
- محیط توسعه برای همهی اعضای تیم یکسان است و فرقی نمیکند که توسعهدهندگان از چه سیستمعاملی استفاده میکنند.
- محیط development دقیقا همانند محیط production است. این یعنی بدون دردسر و نگرانی میتوانید عملیات استقرار نرمافزار را انجام دهید و برنامهی شما بهخوبی اجرا خواهد شد.
- اگر برنامههایی توسعه میدهید که نیاز به کامپایل داشته باشند مطمئنا از سختیها و دردسرهای این کار اطلاع دارید. اما با استفاده از Docker دیگر مهم نیست که از چه سیستمعاملی استفاده میکنید و میتوانید کامپایل برنامههایتان را درون Docker انجام دهید.
- برای توسعهی نرمافزار فقط به Docker نیاز دارید. این یعنی نیازی نیست که زبانهای برنامهنویسی مختلف را برای توسعهی هر پروژه بر روی سیستم خود نصب کنید. مثلا اگر قصد اجرای یک اسکریپت توسعه داده شده با زبان Ruby را داشته باشید فقط لازم است تا از یک Ruby Docker Image استفاده کنید.
- شما میتوانید به چندین نسخهی مختلف از زبانهای مورد نیاز خود دسترسی داشته باشید. برای مثال شاید بخواهید برنامهای که با زبان Python توسعه دادهاید را با Python3 اجرا کنید اما فقط Python2 بر روی سیستم شما نصب است. راه حل بسیار ساده است و میتوانید بهراحتی با استفاده از Python3 Image برنامهی خود را اجرا کنید.
- توسعهی نرمافزار در Docker باعث شده تا استقرار برنامه بر روی سرور آسان شود زیرا برنامهی نهایی همانطور که در Docker شما اجرا میشود، به همان صورت نیز در سرور اجرا خواهد شد و کافیست تا کدهای خود را به یک پکیج تبدیل کرده و آن را در سروری با همان Docker Image مستقر کنید. حتی میتوانید Docker Image خود را بههمراه کدهایتان به سرور push کرده و آن Image جدید را اجرا کنید.
- در توسعهی نرمافزار با استفاده از Docker میتوانید برنامهی خود را بدون نیاز به نصب VM در VirtualBox و SSH، با ویرایشگر مورد علاقه خود توسعه دهید.
نحوهی استفاده از Docker
در استفاده از Docker برای توسعهی پروژههای مختلف معمولا تفاوت زیادی وجود ندارد اما برای درک بهتر این موضوع در ادامهی مقاله به توسعهی پروژههای مختلفی میپردازیم:
Ruby
با یک برنامه ساده شروع میکنیم که Hello Ruby!
را در Console چاپ میکند. البته توجه داشته باشید که برای اجرای این اسکریپت نیازی به نصب زبان Ruby نیست. در قدم اول یک فایل با نام hello.rb
در پوشهای با نام app
ایجاد کنید و کد زیر را در آن قرار دهید:
puts 'Hello Ruby!'
پس از ذخیرهی کدهای بالا، در Terminal سیستمعامل خود به پوشهی app بروید و با اجرای دستور زیر اسکریپت Ruby اجرا خواهد شد:
docker run --rm -v "$(pwd)":/app -w /app ruby ruby hello.rb
اگر از command line سیستمعامل Windows استفاده میکنید بایستی $(pwd)
را با %CD%
جایگزین کنید:
docker run --rm -v "%CD%":/app -w /app ruby ruby hello.rb
به همین سادگی بدون نصب داشتن زبان Ruby بر روی سیستم خود میتوانید با استفاده از Docker یک اسکریپت توسعه داده شده با زبان Ruby را اجرا کنید. حال بیایید تا یک وابستگی به اسکریپت اضافه کنیم. یک Gemfile
در مسیر پروژه ایجاد کنید و کدهای زیر را در آن قرار دهید:
source 'https://rubygems.org'
gem 'hello-world'
در مرحلهی بعد فایل hello.rb
را با ویرایشگر مورد نظر خود باز کرده و hello-world
را در آن require کنید:
require 'hello-world'
puts 'Hello Ruby!'
اگر با زبان Ruby کار کرده باشید میدانید که برای نصب وابستگی جدید بایستی دستور bundle install
را اجرا کنید تا اسکریپت hello.rb
به درستی اجرا شود اما اگر شما این اسکریپت را در یک Docker container اجرا کنید، با خطا روبرو خواهید شد زیرا وابستگی مورد نیاز اسکریپت، در container نصب نشده و برای نصب وابستگیهای پروژه بهتر است از یک vendor استفاده کنید:
docker run --rm -v "$(pwd)":/app -w /app ruby bundle install --standalone
با اجرای دستور فوق، نصب وابستگیهای اسکریپت انجام شده و در صورت نیاز کامپایل کدها انجام خواهد شد. اکنون برای استفاده از bundle جدید بایستی require_relative
را در ابتدای فایل hello.rb
قرار دهیم:
require_relative 'vendor/bundle/bundler/setup'
require 'hello-world'
puts 'Hello Ruby!'
پس از ذخیرهی فایل، با اجرای دستور زیر میتوانید خروجی اسکریپت را در Console خود مشاهده کنید:
docker run --rm -v "$(pwd)":/app -w /app ruby ruby hello.rb
حتی اگر بخواهید این اسکریپت را با ورژن خاصی از Ruby اجرا کنید میتوانید بهصورت زیر عمل کنید:
docker run --rm -v "$(pwd)":/app -w /app ruby:2.4 ruby hello.rb
راهاندازی برنامهی وب با Ruby
برای ساخت برنامههای وب نیاز است تا یک پورت را باز کنیم و این کار در Docker با اضافه کردن -p PORT:PORT
به دستور docker run
انجام میشود. کدهای زیر را در یک فایل با نام webapp.rb
ذخیره کنید:
require_relative 'bundle/bundler/setup'
require 'sinatra'
set :port, 8080
set :bind, '0.0.0.0' # required to bind to all interfaces
get '/' do
"Hello World!"
end
در مرحلهی بعد sinatra
را به Gemfile
اضافه کرده و با دستور bundle install
این gem جدید را در Docker container نصب کنید. همچنین sinatra
به یک پیشنیاز بهنام thin
نیاز دارد بنابراین بایستی با اجرای دستور زیر آن را نصب کرده:
docker run --rm -it -v "$(pwd)":/docktest -w /docktest ruby gem install thin
و در نهایت با اجرای دستور زیر برنامهی وب ما اجرا خواهد شد:
docker run -i -t --rm -v "$(pwd)":/app -w /app -p 8080:8080 ruby ruby webapp.rb
برای مشاهدهی برنامه میتوانید وارد لینک localhost:8080 شوید.
Node.js
برای ایجاد اسکریپت Node.js و اجرای آن با Docker بایستی در وهلهی اول پیشنیازهای مورد نیاز را در Docker container نصب کنید:
docker run --rm -it -v $PWD:/app -w /app node npm install hello-world-npm
سپس کدهای زیر را در در فایلی با نام hello.js
در پوشهی app
ذخیره کرده:
const helloWorld = require('hello-world-npm');
console.log(helloWorld());
console.log("Hello Node!");
در نهایت برای اجرای اسکریپت میتوانید از دستور زیر استفاده کنید:
docker run --rm -it -v $PWD:/app -w /app node hello.js
Go
کدهای زیر را در یک با نام hello.go
ذخیره کنید:
package main
import (
"fmt"
hello "github.com/treeder/go-hello-world"
)
func main() {
fmt.Println(hello.Hello())
fmt.Println("Hello Go!")
}
سپس دستورهای زیر را بهترتیب برای نصب وابستگیها و کامپایل برنامه اجرا کنید:
docker run --rm -i -v $PWD:/app -w /app golang go get github.com/treeder/go-hello-world
docker run --rm -i -v $PWD:/app -w /app golang go build -o myapp
docker run --rm -i -v $PWD:/app -w /app golang ./myapp
جمعبندی
ما در تمام مثالهای قبل از --rm
استفاده کردیم و این سوئیچ باعث میشود تا container ایجاد شده پس از اجرای دستور مورد نظر ما حذف شود. حال شاید در برنامهی شما یک وابستگی مانند RocksDB وجود داشته باشد که زمان زیادی برای build آن نیاز است. در چنین سناریویی میتوانید از ترفند زیر استفاده کنید:
docker run --name goapp -it -v $PWD:/app -w /app golang sh -c "go build -o myapp && ./myapp" || docker start -ia goapp
با اجرای دستور فوق یک container با نام goapp
ساخته شده و دستور go build -o myapp && ./myapp
را اجرا میکند اما حذف نخواهد شد بنابراین میتوانید هر زمان که دوست داشته باشید با اجرای دستور docker start -ia goapp
بدون نیاز به کامپایل مجدد برنامه، آن container را اجرا کنید.
مطمئنا تابهحال متوجه شدهاید که توسعه به کمک Docker تغییری در روند توسعهی شما ایجاد نمیکند اما میتوانید به مزایایی که در ابتدای مقاله به آنها اشاره کرده بودیم دست پیدا کنید.
منبع: https://medium.com/better-programming/why-and-how-to-use-docker-for-development-a156c1de3b24